Browse Source

iface: unify ipv4/6lowpan fragmenters.

Same rationale as previous commit.

Also, rename "OutPacket" to "Fragmenter".
Dario Nieuwenhuis 2 years ago
parent
commit
d13db8b291

+ 12 - 4
src/iface/interface/igmp.rs

@@ -51,7 +51,9 @@ impl Interface {
                         .ok_or(MulticastError::Exhausted)?;
 
                     // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
-                    self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                    self.inner
+                        .dispatch_ip(tx_token, pkt, &mut self.fragmenter)
+                        .unwrap();
 
                     Ok(true)
                 } else {
@@ -91,7 +93,9 @@ impl Interface {
                         .ok_or(MulticastError::Exhausted)?;
 
                     // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
-                    self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                    self.inner
+                        .dispatch_ip(tx_token, pkt, &mut self.fragmenter)
+                        .unwrap();
 
                     Ok(true)
                 } else {
@@ -125,7 +129,9 @@ impl Interface {
                     // Send initial membership report
                     if let Some(tx_token) = device.transmit(self.inner.now) {
                         // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
-                        self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                        self.inner
+                            .dispatch_ip(tx_token, pkt, &mut self.fragmenter)
+                            .unwrap();
                     } else {
                         return false;
                     }
@@ -153,7 +159,9 @@ impl Interface {
                             // Send initial membership report
                             if let Some(tx_token) = device.transmit(self.inner.now) {
                                 // NOTE(unwrap): packet destination is multicast, which is always routable and doesn't require neighbor discovery.
-                                self.inner.dispatch_ip(tx_token, pkt, None).unwrap();
+                                self.inner
+                                    .dispatch_ip(tx_token, pkt, &mut self.fragmenter)
+                                    .unwrap();
                             } else {
                                 return false;
                             }

+ 17 - 19
src/iface/interface/ipv4.rs

@@ -332,20 +332,16 @@ impl InterfaceInner {
     }
 
     #[cfg(feature = "proto-ipv4-fragmentation")]
-    pub(super) fn dispatch_ipv4_out_packet<Tx: TxToken>(
-        &mut self,
-        tx_token: Tx,
-        pkt: &mut Ipv4OutPacket,
-    ) {
+    pub(super) fn dispatch_ipv4_frag<Tx: TxToken>(&mut self, tx_token: Tx, frag: &mut Fragmenter) {
         let caps = self.caps.clone();
 
         let mtu_max = self.ip_mtu();
-        let ip_len = (pkt.packet_len - pkt.sent_bytes + pkt.repr.buffer_len()).min(mtu_max);
-        let payload_len = ip_len - pkt.repr.buffer_len();
+        let ip_len = (frag.packet_len - frag.sent_bytes + frag.ipv4.repr.buffer_len()).min(mtu_max);
+        let payload_len = ip_len - frag.ipv4.repr.buffer_len();
 
-        let more_frags = (pkt.packet_len - pkt.sent_bytes) != payload_len;
-        pkt.repr.payload_len = payload_len;
-        pkt.sent_bytes += payload_len;
+        let more_frags = (frag.packet_len - frag.sent_bytes) != payload_len;
+        frag.ipv4.repr.payload_len = payload_len;
+        frag.sent_bytes += payload_len;
 
         let mut tx_len = ip_len;
         #[cfg(feature = "medium-ethernet")]
@@ -360,7 +356,7 @@ impl InterfaceInner {
 
             let src_addr = self.hardware_addr.unwrap().ethernet_or_panic();
             frame.set_src_addr(src_addr);
-            frame.set_dst_addr(pkt.dst_hardware_addr);
+            frame.set_dst_addr(frag.ipv4.dst_hardware_addr);
 
             match repr.version() {
                 #[cfg(feature = "proto-ipv4")]
@@ -373,27 +369,29 @@ impl InterfaceInner {
         tx_token.consume(tx_len, |mut tx_buffer| {
             #[cfg(feature = "medium-ethernet")]
             if matches!(self.caps.medium, Medium::Ethernet) {
-                emit_ethernet(&IpRepr::Ipv4(pkt.repr), tx_buffer);
+                emit_ethernet(&IpRepr::Ipv4(frag.ipv4.repr), tx_buffer);
                 tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
             }
 
-            let mut packet = Ipv4Packet::new_unchecked(&mut tx_buffer[..pkt.repr.buffer_len()]);
-            pkt.repr.emit(&mut packet, &caps.checksum);
-            packet.set_ident(pkt.ident);
+            let mut packet =
+                Ipv4Packet::new_unchecked(&mut tx_buffer[..frag.ipv4.repr.buffer_len()]);
+            frag.ipv4.repr.emit(&mut packet, &caps.checksum);
+            packet.set_ident(frag.ipv4.ident);
             packet.set_more_frags(more_frags);
             packet.set_dont_frag(false);
-            packet.set_frag_offset(pkt.frag_offset);
+            packet.set_frag_offset(frag.ipv4.frag_offset);
 
             if caps.checksum.ipv4.tx() {
                 packet.fill_checksum();
             }
 
-            tx_buffer[pkt.repr.buffer_len()..][..payload_len].copy_from_slice(
-                &pkt.buffer[pkt.frag_offset as usize + pkt.repr.buffer_len()..][..payload_len],
+            tx_buffer[frag.ipv4.repr.buffer_len()..][..payload_len].copy_from_slice(
+                &frag.buffer[frag.ipv4.frag_offset as usize + frag.ipv4.repr.buffer_len()..]
+                    [..payload_len],
             );
 
             // Update the frag offset for the next fragment.
-            pkt.frag_offset += payload_len as u16;
+            frag.ipv4.frag_offset += payload_len as u16;
         })
     }
 

+ 134 - 175
src/iface/interface/mod.rs

@@ -64,37 +64,18 @@ pub(crate) struct FragmentsBuffer {
     sixlowpan_reassembly_timeout: Duration,
 }
 
-pub(crate) struct OutPackets {
-    #[cfg(feature = "proto-ipv4-fragmentation")]
-    ipv4_out_packet: Ipv4OutPacket,
-    #[cfg(feature = "proto-sixlowpan-fragmentation")]
-    sixlowpan_out_packet: SixlowpanOutPacket,
-}
-
-impl OutPackets {
-    #[cfg(any(
-        feature = "proto-ipv4-fragmentation",
-        feature = "proto-sixlowpan-fragmentation"
-    ))]
-    /// Returns `true` when all the data of the outgoing buffers are transmitted.
-    fn all_transmitted(&self) -> bool {
-        #[cfg(feature = "proto-ipv4-fragmentation")]
-        if !self.ipv4_out_packet.is_empty() {
-            return false;
-        }
-
-        #[cfg(feature = "proto-sixlowpan-fragmentation")]
-        if !self.sixlowpan_out_packet.is_empty() {
-            return false;
-        }
+#[cfg(not(feature = "_proto-fragmentation"))]
+pub(crate) struct Fragmenter {}
 
-        true
+#[cfg(not(feature = "_proto-fragmentation"))]
+impl Fragmenter {
+    pub(crate) fn new() -> Self {
+        Self {}
     }
 }
 
-#[allow(unused)]
-#[cfg(feature = "proto-ipv4-fragmentation")]
-pub(crate) struct Ipv4OutPacket {
+#[cfg(feature = "_proto-fragmentation")]
+pub(crate) struct Fragmenter {
     /// The buffer that holds the unfragmented 6LoWPAN packet.
     buffer: [u8; FRAGMENTATION_BUFFER_SIZE],
     /// The size of the packet without the IEEE802.15.4 header and the fragmentation headers.
@@ -102,6 +83,14 @@ pub(crate) struct Ipv4OutPacket {
     /// The amount of bytes that already have been transmitted.
     sent_bytes: usize,
 
+    #[cfg(feature = "proto-ipv4-fragmentation")]
+    ipv4: Ipv4Fragmenter,
+    #[cfg(feature = "proto-sixlowpan-fragmentation")]
+    sixlowpan: SixlowpanFragmenter,
+}
+
+#[cfg(feature = "proto-ipv4-fragmentation")]
+pub(crate) struct Ipv4Fragmenter {
     /// The IPv4 representation.
     repr: Ipv4Repr,
     /// The destination hardware address.
@@ -113,67 +102,8 @@ pub(crate) struct Ipv4OutPacket {
     ident: u16,
 }
 
-#[cfg(feature = "proto-ipv4-fragmentation")]
-impl Ipv4OutPacket {
-    pub(crate) fn new() -> Self {
-        Self {
-            buffer: [0u8; FRAGMENTATION_BUFFER_SIZE],
-            packet_len: 0,
-            sent_bytes: 0,
-            repr: Ipv4Repr {
-                src_addr: Ipv4Address::default(),
-                dst_addr: Ipv4Address::default(),
-                next_header: IpProtocol::Unknown(0),
-                payload_len: 0,
-                hop_limit: 0,
-            },
-            #[cfg(feature = "medium-ethernet")]
-            dst_hardware_addr: EthernetAddress::default(),
-            frag_offset: 0,
-            ident: 0,
-        }
-    }
-
-    /// 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.sent_bytes = 0;
-        self.repr = Ipv4Repr {
-            src_addr: Ipv4Address::default(),
-            dst_addr: Ipv4Address::default(),
-            next_header: IpProtocol::Unknown(0),
-            payload_len: 0,
-            hop_limit: 0,
-        };
-        #[cfg(feature = "medium-ethernet")]
-        {
-            self.dst_hardware_addr = EthernetAddress::default();
-        }
-    }
-}
-
-#[allow(unused)]
-#[cfg(feature = "proto-sixlowpan")]
-pub(crate) struct SixlowpanOutPacket {
-    /// The buffer that holds the unfragmented 6LoWPAN packet.
-    buffer: [u8; FRAGMENTATION_BUFFER_SIZE],
-    /// The size of the packet without the IEEE802.15.4 header and the fragmentation headers.
-    packet_len: usize,
-    /// The amount of bytes that already have been transmitted.
-    sent_bytes: usize,
-
+#[cfg(feature = "proto-sixlowpan-fragmentation")]
+pub(crate) struct SixlowpanFragmenter {
     /// The datagram size that is used for the fragmentation headers.
     datagram_size: u16,
     /// The datagram tag that is used for the fragmentation headers.
@@ -189,19 +119,38 @@ pub(crate) struct SixlowpanOutPacket {
     ll_src_addr: Ieee802154Address,
 }
 
-#[cfg(feature = "proto-sixlowpan-fragmentation")]
-impl SixlowpanOutPacket {
+#[cfg(feature = "_proto-fragmentation")]
+impl Fragmenter {
     pub(crate) fn new() -> Self {
         Self {
             buffer: [0u8; FRAGMENTATION_BUFFER_SIZE],
             packet_len: 0,
-            datagram_size: 0,
-            datagram_tag: 0,
-            datagram_offset: 0,
             sent_bytes: 0,
-            fragn_size: 0,
-            ll_dst_addr: Ieee802154Address::Absent,
-            ll_src_addr: Ieee802154Address::Absent,
+
+            #[cfg(feature = "proto-ipv4-fragmentation")]
+            ipv4: Ipv4Fragmenter {
+                repr: Ipv4Repr {
+                    src_addr: Ipv4Address::default(),
+                    dst_addr: Ipv4Address::default(),
+                    next_header: IpProtocol::Unknown(0),
+                    payload_len: 0,
+                    hop_limit: 0,
+                },
+                #[cfg(feature = "medium-ethernet")]
+                dst_hardware_addr: EthernetAddress::default(),
+                frag_offset: 0,
+                ident: 0,
+            },
+
+            #[cfg(feature = "proto-sixlowpan-fragmentation")]
+            sixlowpan: SixlowpanFragmenter {
+                datagram_size: 0,
+                datagram_tag: 0,
+                datagram_offset: 0,
+                fragn_size: 0,
+                ll_dst_addr: Ieee802154Address::Absent,
+                ll_src_addr: Ieee802154Address::Absent,
+            },
         }
     }
 
@@ -220,12 +169,31 @@ impl SixlowpanOutPacket {
     // 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;
+
+        #[cfg(feature = "proto-ipv4-fragmentation")]
+        {
+            self.ipv4.repr = Ipv4Repr {
+                src_addr: Ipv4Address::default(),
+                dst_addr: Ipv4Address::default(),
+                next_header: IpProtocol::Unknown(0),
+                payload_len: 0,
+                hop_limit: 0,
+            };
+            #[cfg(feature = "medium-ethernet")]
+            {
+                self.ipv4.dst_hardware_addr = EthernetAddress::default();
+            }
+        }
+
+        #[cfg(feature = "proto-sixlowpan-fragmentation")]
+        {
+            self.sixlowpan.datagram_size = 0;
+            self.sixlowpan.datagram_tag = 0;
+            self.sixlowpan.fragn_size = 0;
+            self.sixlowpan.ll_dst_addr = Ieee802154Address::Absent;
+            self.sixlowpan.ll_src_addr = Ieee802154Address::Absent;
+        }
     }
 }
 
@@ -254,7 +222,7 @@ use check;
 pub struct Interface {
     inner: InterfaceInner,
     fragments: FragmentsBuffer,
-    out_packets: OutPackets,
+    fragmenter: Fragmenter,
 }
 
 /// The device independent part of an Ethernet network interface.
@@ -573,12 +541,7 @@ impl Interface {
                 #[cfg(feature = "proto-sixlowpan-fragmentation")]
                 sixlowpan_reassembly_timeout: Duration::from_secs(60),
             },
-            out_packets: OutPackets {
-                #[cfg(feature = "proto-ipv4-fragmentation")]
-                ipv4_out_packet: Ipv4OutPacket::new(),
-                #[cfg(feature = "proto-sixlowpan-fragmentation")]
-                sixlowpan_out_packet: SixlowpanOutPacket::new(),
-            },
+            fragmenter: Fragmenter::new(),
             inner: InterfaceInner {
                 now: Instant::from_secs(0),
                 caps,
@@ -778,14 +741,23 @@ impl Interface {
         #[cfg(feature = "_proto-fragmentation")]
         self.fragments.assembler.remove_expired(timestamp);
 
-        #[cfg(feature = "proto-ipv4-fragmentation")]
-        if self.ipv4_egress(device) {
-            return true;
-        }
-
-        #[cfg(feature = "proto-sixlowpan-fragmentation")]
-        if self.sixlowpan_egress(device) {
-            return true;
+        match self.inner.caps.medium {
+            #[cfg(feature = "medium-ieee802154")]
+            Medium::Ieee802154 =>
+            {
+                #[cfg(feature = "proto-sixlowpan-fragmentation")]
+                if self.sixlowpan_egress(device) {
+                    return true;
+                }
+            }
+            #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
+            _ =>
+            {
+                #[cfg(feature = "proto-ipv4-fragmentation")]
+                if self.ipv4_egress(device) {
+                    return true;
+                }
+            }
         }
 
         let mut readiness_may_have_changed = false;
@@ -821,8 +793,8 @@ impl Interface {
     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() {
+        #[cfg(feature = "_proto-fragmentation")]
+        if !self.fragmenter.is_empty() {
             return Some(Instant::from_millis(0));
         }
 
@@ -876,8 +848,7 @@ impl Interface {
                                 .process_ethernet(sockets, &frame, &mut self.fragments)
                         {
                             if let Err(err) =
-                                self.inner
-                                    .dispatch(tx_token, packet, Some(&mut self.out_packets))
+                                self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
                             {
                                 net_debug!("Failed to send response: {:?}", err);
                             }
@@ -888,11 +859,10 @@ impl Interface {
                         if let Some(packet) =
                             self.inner.process_ip(sockets, &frame, &mut self.fragments)
                         {
-                            if let Err(err) = self.inner.dispatch_ip(
-                                tx_token,
-                                packet,
-                                Some(&mut self.out_packets),
-                            ) {
+                            if let Err(err) =
+                                self.inner
+                                    .dispatch_ip(tx_token, packet, &mut self.fragmenter)
+                            {
                                 net_debug!("Failed to send response: {:?}", err);
                             }
                         }
@@ -903,11 +873,10 @@ impl Interface {
                             self.inner
                                 .process_ieee802154(sockets, &frame, &mut self.fragments)
                         {
-                            if let Err(err) = self.inner.dispatch_ip(
-                                tx_token,
-                                packet,
-                                Some(&mut self.out_packets),
-                            ) {
+                            if let Err(err) =
+                                self.inner
+                                    .dispatch_ip(tx_token, packet, &mut self.fragmenter)
+                            {
                                 net_debug!("Failed to send response: {:?}", err);
                             }
                         }
@@ -948,20 +917,8 @@ impl Interface {
                     EgressError::Exhausted
                 })?;
 
-                #[cfg(any(
-                    feature = "proto-ipv4-fragmentation",
-                    feature = "proto-sixlowpan-fragmentation"
-                ))]
                 inner
-                    .dispatch_ip(t, response, Some(&mut self.out_packets))
-                    .map_err(EgressError::Dispatch)?;
-
-                #[cfg(not(any(
-                    feature = "proto-ipv4-fragmentation",
-                    feature = "proto-sixlowpan-fragmentation"
-                )))]
-                inner
-                    .dispatch_ip(t, response, None)
+                    .dispatch_ip(t, response, &mut self.fragmenter)
                     .map_err(EgressError::Dispatch)?;
 
                 emitted_any = true;
@@ -1036,19 +993,19 @@ impl Interface {
         D: Device + ?Sized,
     {
         // Reset the buffer when we transmitted everything.
-        if self.out_packets.ipv4_out_packet.finished() {
-            self.out_packets.ipv4_out_packet.reset();
+        if self.fragmenter.finished() {
+            self.fragmenter.reset();
         }
 
-        if self.out_packets.ipv4_out_packet.is_empty() {
+        if self.fragmenter.is_empty() {
             return false;
         }
 
-        let pkt = &self.out_packets.ipv4_out_packet;
+        let pkt = &self.fragmenter;
         if pkt.packet_len > pkt.sent_bytes {
             if let Some(tx_token) = device.transmit(self.inner.now) {
                 self.inner
-                    .dispatch_ipv4_out_packet(tx_token, &mut self.out_packets.ipv4_out_packet);
+                    .dispatch_ipv4_frag(tx_token, &mut self.fragmenter);
                 return true;
             }
         }
@@ -1066,21 +1023,19 @@ impl Interface {
         D: Device + ?Sized,
     {
         // Reset the buffer when we transmitted everything.
-        if self.out_packets.sixlowpan_out_packet.finished() {
-            self.out_packets.sixlowpan_out_packet.reset();
+        if self.fragmenter.finished() {
+            self.fragmenter.reset();
         }
 
-        if self.out_packets.sixlowpan_out_packet.is_empty() {
+        if self.fragmenter.is_empty() {
             return false;
         }
 
-        let pkt = &self.out_packets.sixlowpan_out_packet;
+        let pkt = &self.fragmenter;
         if pkt.packet_len > pkt.sent_bytes {
             if let Some(tx_token) = device.transmit(self.inner.now) {
-                self.inner.dispatch_ieee802154_out_packet(
-                    tx_token,
-                    &mut self.out_packets.sixlowpan_out_packet,
-                );
+                self.inner
+                    .dispatch_ieee802154_frag(tx_token, &mut self.fragmenter);
                 return true;
             }
         }
@@ -1509,7 +1464,7 @@ impl InterfaceInner {
         &mut self,
         tx_token: Tx,
         packet: EthernetPacket,
-        _out_packet: Option<&mut OutPackets>,
+        frag: &mut Fragmenter,
     ) -> Result<(), DispatchError>
     where
         Tx: TxToken,
@@ -1532,7 +1487,7 @@ impl InterfaceInner {
                     arp_repr.emit(&mut packet);
                 })
             }
-            EthernetPacket::Ip(packet) => self.dispatch_ip(tx_token, packet, _out_packet),
+            EthernetPacket::Ip(packet) => self.dispatch_ip(tx_token, packet, frag),
         }
     }
 
@@ -1580,6 +1535,7 @@ impl InterfaceInner {
         tx_token: Tx,
         src_addr: &IpAddress,
         dst_addr: &IpAddress,
+        fragmenter: &mut Fragmenter,
     ) -> Result<(HardwareAddress, Tx), DispatchError>
     where
         Tx: TxToken,
@@ -1698,7 +1654,7 @@ impl InterfaceInner {
                     solicit,
                 ));
 
-                if let Err(e) = self.dispatch_ip(tx_token, packet, None) {
+                if let Err(e) = self.dispatch_ip(tx_token, packet, fragmenter) {
                     net_debug!("Failed to dispatch NDISC solicit: {:?}", e);
                     return Err(DispatchError::NeighborPending);
                 }
@@ -1724,7 +1680,7 @@ impl InterfaceInner {
         &mut self,
         tx_token: Tx,
         packet: IpPacket,
-        _out_packet: Option<&mut OutPackets>,
+        frag: &mut Fragmenter,
     ) -> Result<(), DispatchError> {
         let ip_repr = packet.ip_repr();
         assert!(!ip_repr.dst_addr().is_unspecified());
@@ -1733,11 +1689,15 @@ impl InterfaceInner {
 
         #[cfg(feature = "medium-ieee802154")]
         if matches!(self.caps.medium, Medium::Ieee802154) {
-            let (addr, tx_token) =
-                self.lookup_hardware_addr(tx_token, &ip_repr.src_addr(), &ip_repr.dst_addr())?;
+            let (addr, tx_token) = self.lookup_hardware_addr(
+                tx_token,
+                &ip_repr.src_addr(),
+                &ip_repr.dst_addr(),
+                frag,
+            )?;
             let addr = addr.ieee802154_or_panic();
 
-            self.dispatch_ieee802154(addr, tx_token, packet, _out_packet);
+            self.dispatch_ieee802154(addr, tx_token, packet, frag);
             return Ok(());
         }
 
@@ -1765,6 +1725,7 @@ impl InterfaceInner {
                     tx_token,
                     &ip_repr.src_addr(),
                     &ip_repr.dst_addr(),
+                    frag,
                 )? {
                     (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
                     #[cfg(feature = "medium-ieee802154")]
@@ -1812,15 +1773,13 @@ impl InterfaceInner {
                     {
                         net_debug!("start fragmentation");
 
-                        let pkt = &mut _out_packet.unwrap().ipv4_out_packet;
-
                         // Calculate how much we will send now (including the Ethernet header).
                         let tx_len = self.caps.max_transmission_unit;
 
                         let ip_header_len = repr.buffer_len();
                         let first_frag_ip_len = self.caps.ip_mtu();
 
-                        if pkt.buffer.len() < first_frag_ip_len {
+                        if frag.buffer.len() < first_frag_ip_len {
                             net_debug!(
                                 "Fragmentation buffer is too small, at least {} needed. Dropping",
                                 first_frag_ip_len
@@ -1830,26 +1789,26 @@ impl InterfaceInner {
 
                         #[cfg(feature = "medium-ethernet")]
                         {
-                            pkt.dst_hardware_addr = dst_hardware_addr;
+                            frag.ipv4.dst_hardware_addr = dst_hardware_addr;
                         }
 
                         // Save the total packet len (without the Ethernet header, but with the first
                         // IP header).
-                        pkt.packet_len = total_ip_len;
+                        frag.packet_len = total_ip_len;
 
                         // Save the IP header for other fragments.
-                        pkt.repr = repr;
+                        frag.ipv4.repr = repr;
 
                         // Save how much bytes we will send now.
-                        pkt.sent_bytes = first_frag_ip_len;
+                        frag.sent_bytes = first_frag_ip_len;
 
                         // Modify the IP header
                         repr.payload_len = first_frag_ip_len - repr.buffer_len();
 
                         // Emit the IP header to the buffer.
-                        emit_ip(&ip_repr, &mut pkt.buffer);
-                        let mut ipv4_packet = Ipv4Packet::new_unchecked(&mut pkt.buffer[..]);
-                        pkt.ident = ipv4_id;
+                        emit_ip(&ip_repr, &mut frag.buffer);
+                        let mut ipv4_packet = Ipv4Packet::new_unchecked(&mut frag.buffer[..]);
+                        frag.ipv4.ident = ipv4_id;
                         ipv4_packet.set_ident(ipv4_id);
                         ipv4_packet.set_more_frags(true);
                         ipv4_packet.set_dont_frag(false);
@@ -1868,11 +1827,11 @@ impl InterfaceInner {
                             }
 
                             // Change the offset for the next packet.
-                            pkt.frag_offset = (first_frag_ip_len - ip_header_len) as u16;
+                            frag.ipv4.frag_offset = (first_frag_ip_len - ip_header_len) as u16;
 
                             // Copy the IP header and the payload.
                             tx_buffer[..first_frag_ip_len]
-                                .copy_from_slice(&pkt.buffer[..first_frag_ip_len]);
+                                .copy_from_slice(&frag.buffer[..first_frag_ip_len]);
 
                             Ok(())
                         })

+ 26 - 35
src/iface/interface/sixlowpan.rs

@@ -1,12 +1,4 @@
-use super::check;
-use super::FragmentsBuffer;
-use super::InterfaceInner;
-use super::IpPacket;
-use super::OutPackets;
-use super::SocketSet;
-
-#[cfg(feature = "proto-sixlowpan-fragmentation")]
-use super::SixlowpanOutPacket;
+use super::*;
 
 use crate::phy::ChecksumCapabilities;
 use crate::phy::TxToken;
@@ -98,7 +90,6 @@ impl InterfaceInner {
         f: &'output mut FragmentsBuffer,
     ) -> Option<&'output [u8]> {
         use crate::iface::fragmentation::{AssemblerError, AssemblerFullError};
-        use crate::iface::interface::FragKey;
 
         // We have a fragment header, which means we cannot process the 6LoWPAN packet,
         // unless we have a complete one after processing this fragment.
@@ -275,7 +266,7 @@ impl InterfaceInner {
         ll_dst_a: Ieee802154Address,
         tx_token: Tx,
         packet: IpPacket,
-        _out_packet: Option<&mut OutPackets>,
+        frag: &mut Fragmenter,
     ) {
         // We first need to convert the IPv6 packet to a 6LoWPAN compressed packet.
         // Whenever this packet is to big to fit in the IEEE802.15.4 packet, then we need to
@@ -365,14 +356,14 @@ impl InterfaceInner {
             #[cfg(feature = "proto-sixlowpan-fragmentation")]
             {
                 // The packet does not fit in one Ieee802154 frame, so we need fragmentation.
-                // We do this by emitting everything in the `out_packet.buffer` from the interface.
+                // We do this by emitting everything in the `frag.buffer` from the interface.
                 // After emitting everything into that buffer, we send the first fragment heere.
-                // When `poll` is called again, we check if out_packet was fully sent, otherwise we
-                // call `dispatch_ieee802154_out_packet`, which will transmit the other fragments.
+                // When `poll` is called again, we check if frag was fully sent, otherwise we
+                // call `dispatch_ieee802154_frag`, which will transmit the other fragments.
 
-                // `dispatch_ieee802154_out_packet` requires some information about the total packet size,
+                // `dispatch_ieee802154_frag` requires some information about the total packet size,
                 // the link local source and destination address...
-                let pkt = &mut _out_packet.unwrap().sixlowpan_out_packet;
+                let pkt = frag;
 
                 if pkt.buffer.len() < total_size {
                     net_debug!(
@@ -382,8 +373,8 @@ impl InterfaceInner {
                     return;
                 }
 
-                pkt.ll_dst_addr = ll_dst_a;
-                pkt.ll_src_addr = ll_src_a;
+                pkt.sixlowpan.ll_dst_addr = ll_dst_a;
+                pkt.sixlowpan.ll_src_addr = ll_src_a;
 
                 let mut iphc_packet =
                     SixlowpanIphcPacket::new_unchecked(&mut pkt.buffer[..iphc_repr.buffer_len()]);
@@ -436,20 +427,20 @@ impl InterfaceInner {
 
                 // The datagram size that we need to set in the first fragment header is equal to the
                 // IPv6 payload length + 40.
-                pkt.datagram_size = (packet.ip_repr().payload_len() + 40) as u16;
+                pkt.sixlowpan.datagram_size = (packet.ip_repr().payload_len() + 40) as u16;
 
                 // We generate a random tag.
                 let tag = self.get_sixlowpan_fragment_tag();
                 // We save the tag for the other fragments that will be created when calling `poll`
                 // multiple times.
-                pkt.datagram_tag = tag;
+                pkt.sixlowpan.datagram_tag = tag;
 
                 let frag1 = SixlowpanFragRepr::FirstFragment {
-                    size: pkt.datagram_size,
+                    size: pkt.sixlowpan.datagram_size,
                     tag,
                 };
                 let fragn = SixlowpanFragRepr::Fragment {
-                    size: pkt.datagram_size,
+                    size: pkt.sixlowpan.datagram_size,
                     tag,
                     offset: 0,
                 };
@@ -465,10 +456,10 @@ impl InterfaceInner {
                 let frag1_size =
                     (125 - ieee_len - frag1.buffer_len() + header_diff) / 8 * 8 - (header_diff);
 
-                pkt.fragn_size = (125 - ieee_len - fragn.buffer_len()) / 8 * 8;
+                pkt.sixlowpan.fragn_size = (125 - ieee_len - fragn.buffer_len()) / 8 * 8;
 
                 pkt.sent_bytes = frag1_size;
-                pkt.datagram_offset = frag1_size + header_diff;
+                pkt.sixlowpan.datagram_offset = frag1_size + header_diff;
 
                 tx_token.consume(ieee_len + frag1.buffer_len() + frag1_size, |mut tx_buf| {
                     // Add the IEEE header.
@@ -553,10 +544,10 @@ impl InterfaceInner {
         feature = "medium-ieee802154",
         feature = "proto-sixlowpan-fragmentation"
     ))]
-    pub(super) fn dispatch_ieee802154_out_packet<Tx: TxToken>(
+    pub(super) fn dispatch_ieee802154_frag<Tx: TxToken>(
         &mut self,
         tx_token: Tx,
-        pkt: &mut SixlowpanOutPacket,
+        frag: &mut Fragmenter,
     ) {
         // Create the IEEE802.15.4 header.
         let ieee_repr = Ieee802154Repr {
@@ -568,20 +559,20 @@ impl InterfaceInner {
             pan_id_compression: true,
             frame_version: Ieee802154FrameVersion::Ieee802154_2003,
             dst_pan_id: self.pan_id,
-            dst_addr: Some(pkt.ll_dst_addr),
+            dst_addr: Some(frag.sixlowpan.ll_dst_addr),
             src_pan_id: self.pan_id,
-            src_addr: Some(pkt.ll_src_addr),
+            src_addr: Some(frag.sixlowpan.ll_src_addr),
         };
 
         // Create the FRAG_N header.
         let fragn = SixlowpanFragRepr::Fragment {
-            size: pkt.datagram_size,
-            tag: pkt.datagram_tag,
-            offset: (pkt.datagram_offset / 8) as u8,
+            size: frag.sixlowpan.datagram_size,
+            tag: frag.sixlowpan.datagram_tag,
+            offset: (frag.sixlowpan.datagram_offset / 8) as u8,
         };
 
         let ieee_len = ieee_repr.buffer_len();
-        let frag_size = (pkt.packet_len - pkt.sent_bytes).min(pkt.fragn_size);
+        let frag_size = (frag.packet_len - frag.sent_bytes).min(frag.sixlowpan.fragn_size);
 
         tx_token.consume(
             ieee_repr.buffer_len() + fragn.buffer_len() + frag_size,
@@ -596,10 +587,10 @@ impl InterfaceInner {
                 tx_buf = &mut tx_buf[fragn.buffer_len()..];
 
                 // Add the buffer part
-                tx_buf[..frag_size].copy_from_slice(&pkt.buffer[pkt.sent_bytes..][..frag_size]);
+                tx_buf[..frag_size].copy_from_slice(&frag.buffer[frag.sent_bytes..][..frag_size]);
 
-                pkt.sent_bytes += frag_size;
-                pkt.datagram_offset += frag_size;
+                frag.sent_bytes += frag_size;
+                frag.sixlowpan.datagram_offset += frag_size;
             },
         );
     }

+ 10 - 6
src/iface/interface/tests.rs

@@ -749,7 +749,8 @@ fn test_handle_valid_arp_request() {
         iface.inner.lookup_hardware_addr(
             MockTxToken,
             &IpAddress::Ipv4(local_ip_addr),
-            &IpAddress::Ipv4(remote_ip_addr)
+            &IpAddress::Ipv4(remote_ip_addr),
+            &mut iface.fragmenter,
         ),
         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
     );
@@ -821,7 +822,8 @@ fn test_handle_valid_ndisc_request() {
         iface.inner.lookup_hardware_addr(
             MockTxToken,
             &IpAddress::Ipv6(local_ip_addr),
-            &IpAddress::Ipv6(remote_ip_addr)
+            &IpAddress::Ipv6(remote_ip_addr),
+            &mut iface.fragmenter,
         ),
         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
     );
@@ -865,7 +867,8 @@ fn test_handle_other_arp_request() {
         iface.inner.lookup_hardware_addr(
             MockTxToken,
             &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
-            &IpAddress::Ipv4(remote_ip_addr)
+            &IpAddress::Ipv4(remote_ip_addr),
+            &mut iface.fragmenter,
         ),
         Err(DispatchError::NeighborPending)
     );
@@ -923,7 +926,8 @@ fn test_arp_flush_after_update_ip() {
         iface.inner.lookup_hardware_addr(
             MockTxToken,
             &IpAddress::Ipv4(local_ip_addr),
-            &IpAddress::Ipv4(remote_ip_addr)
+            &IpAddress::Ipv4(remote_ip_addr),
+            &mut iface.fragmenter,
         ),
         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
     );
@@ -1527,7 +1531,7 @@ fn test_echo_request_sixlowpan_128_bytes() {
         Ieee802154Address::default(),
         tx_token,
         result.unwrap(),
-        Some(&mut iface.out_packets),
+        &mut iface.fragmenter,
     );
 
     assert_eq!(
@@ -1677,7 +1681,7 @@ fn test_sixlowpan_udp_with_fragmentation() {
             },
             udp_data,
         )),
-        Some(&mut iface.out_packets),
+        &mut iface.fragmenter,
     );
 
     iface.poll(Instant::now(), &mut device, &mut sockets);