Browse Source

Merge pull request #633 from thvdveld/sixlowpan-poll-at

Modify `poll_at` for 6LoWPAN outgoing fragments
Dario Nieuwenhuis 2 years ago
parent
commit
57e788fbdd
4 changed files with 86 additions and 8 deletions
  1. 18 7
      examples/sixlowpan.rs
  2. 27 0
      src/iface/fragmentation.rs
  3. 41 0
      src/iface/interface.rs
  4. 0 1
      src/wire/sixlowpan.rs

+ 18 - 7
examples/sixlowpan.rs

@@ -86,18 +86,29 @@ fn main() {
         64,
     )];
 
-    let cache = FragmentsCache::new(vec![], BTreeMap::new());
-
-    let mut out_packet_buffer = [0u8; 1280];
-
     let mut builder = InterfaceBuilder::new()
         .ip_addrs(ip_addrs)
         .pan_id(Ieee802154Pan(0xbeef));
     builder = builder
         .hardware_addr(ieee802154_addr.into())
-        .neighbor_cache(neighbor_cache)
-        .sixlowpan_fragments_cache(cache)
-        .sixlowpan_out_packet_cache(&mut out_packet_buffer[..]);
+        .neighbor_cache(neighbor_cache);
+
+    #[cfg(feature = "proto-ipv4-fragmentation")]
+    {
+        let ipv4_frag_cache = FragmentsCache::new(vec![], BTreeMap::new());
+        builder = builder.ipv4_fragments_cache(ipv4_frag_cache);
+    }
+
+    #[cfg(feature = "proto-sixlowpan-fragmentation")]
+    let mut out_packet_buffer = [0u8; 1280];
+    #[cfg(feature = "proto-sixlowpan-fragmentation")]
+    {
+        let sixlowpan_frag_cache = FragmentsCache::new(vec![], BTreeMap::new());
+        builder = builder
+            .sixlowpan_fragments_cache(sixlowpan_frag_cache)
+            .sixlowpan_out_packet_cache(&mut out_packet_buffer[..]);
+    }
+
     let mut iface = builder.finalize(&mut device);
 
     let mut sockets = SocketSet::new(vec![]);

+ 27 - 0
src/iface/fragmentation.rs

@@ -1,5 +1,7 @@
 #![allow(unused)]
 
+use core::fmt;
+
 use managed::{ManagedMap, ManagedSlice};
 
 use crate::storage::Assembler;
@@ -26,6 +28,23 @@ enum AssemblerState {
     },
 }
 
+impl fmt::Display for AssemblerState {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            AssemblerState::NotInit => write!(f, "Not init")?,
+            AssemblerState::Assembling {
+                assembler,
+                total_size,
+                expires_at,
+                offset_correction,
+            } => {
+                write!(f, "{} expires at {}", assembler, expires_at)?;
+            }
+        }
+        Ok(())
+    }
+}
+
 impl<'a> PacketAssembler<'a> {
     /// Create a new empty buffer for fragments.
     pub fn new<S>(storage: S) -> Self
@@ -151,8 +170,16 @@ impl<'a> PacketAssembler<'a> {
                 let len = data.len();
                 self.buffer[offset..][..len].copy_from_slice(data);
 
+                net_debug!(
+                    "frag assembler: receiving {} octests at offset {}",
+                    len,
+                    offset
+                );
+
                 match assembler.add(offset, data.len()) {
                     Ok(overlap) => {
+                        net_debug!("assembler: {}", self.assembler);
+
                         if overlap {
                             net_debug!("packet was added, but there was an overlap.");
                         }

+ 41 - 0
src/iface/interface.rs

@@ -43,6 +43,14 @@ pub(crate) struct OutPackets<'a> {
     _lifetime: core::marker::PhantomData<&'a ()>,
 }
 
+impl<'a> OutPackets<'a> {
+    #[cfg(feature = "proto-sixlowpan-fragmentation")]
+    /// Returns `true` when all the data of the outgoing buffers are transmitted.
+    fn all_transmitted(&self) -> bool {
+        self.sixlowpan_out_packet.finished() || self.sixlowpan_out_packet.is_empty()
+    }
+}
+
 #[allow(unused)]
 #[cfg(feature = "proto-sixlowpan")]
 pub(crate) struct SixlowpanOutPacket<'a> {
@@ -81,6 +89,29 @@ impl<'a> SixlowpanOutPacket<'a> {
             ll_src_addr: Ieee802154Address::Absent,
         }
     }
+
+    /// Return `true` when everything is transmitted.
+    #[inline]
+    fn finished(&self) -> bool {
+        self.packet_len == self.sent_bytes
+    }
+
+    /// Returns `true` when there is nothing to transmit.
+    #[inline]
+    fn is_empty(&self) -> bool {
+        self.packet_len == 0
+    }
+
+    // Reset the buffer.
+    fn reset(&mut self) {
+        self.packet_len = 0;
+        self.datagram_size = 0;
+        self.datagram_tag = 0;
+        self.sent_bytes = 0;
+        self.fragn_size = 0;
+        self.ll_dst_addr = Ieee802154Address::Absent;
+        self.ll_src_addr = Ieee802154Address::Absent;
+    }
 }
 
 macro_rules! check {
@@ -916,6 +947,11 @@ impl<'a> Interface<'a> {
     pub fn poll_at(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Instant> {
         self.inner.now = timestamp;
 
+        #[cfg(feature = "proto-sixlowpan-fragmentation")]
+        if !self.out_packets.all_transmitted() {
+            return Some(Instant::from_millis(0));
+        }
+
         let inner = &mut self.inner;
 
         sockets
@@ -1197,6 +1233,11 @@ impl<'a> Interface<'a> {
                     ) {
                         net_debug!("failed to transmit: {}", e);
                     }
+
+                    // Reset the buffer when we transmitted everything.
+                    if self.out_packets.sixlowpan_out_packet.finished() {
+                        self.out_packets.sixlowpan_out_packet.reset();
+                    }
                 }
                 Err(e) => {
                     net_debug!("failed to transmit: {}", e);

+ 0 - 1
src/wire/sixlowpan.rs

@@ -910,7 +910,6 @@ pub mod iphc {
         ) -> usize {
             self.set_cid_field(0);
             self.set_sac_field(0);
-            self.set_sam_field(0b00);
             let src = src_addr.as_bytes();
             if src_addr == ipv6::Address::UNSPECIFIED {
                 self.set_sac_field(1);