|  | @@ -1,5 +1,6 @@
 | 
											
												
													
														|  |  use super::*;
 |  |  use super::*;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +use crate::iface::ip_packet::Ipv6Packet;
 | 
											
												
													
														|  |  use crate::phy::ChecksumCapabilities;
 |  |  use crate::phy::ChecksumCapabilities;
 | 
											
												
													
														|  |  use crate::wire::{Ipv6Packet as Ipv6PacketWire, *};
 |  |  use crate::wire::{Ipv6Packet as Ipv6PacketWire, *};
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -33,9 +34,10 @@ impl InterfaceInner {
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              SixlowpanPacket::IphcHeader => {
 |  |              SixlowpanPacket::IphcHeader => {
 | 
											
												
													
														|  | -                match self.decompress_sixlowpan(
 |  | 
 | 
											
												
													
														|  | 
 |  | +                match Self::sixlowpan_to_ipv6(
 | 
											
												
													
														|  | 
 |  | +                    &self.sixlowpan_address_context,
 | 
											
												
													
														|  |                      ieee802154_repr,
 |  |                      ieee802154_repr,
 | 
											
												
													
														|  | -                    payload.as_ref(),
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    payload,
 | 
											
												
													
														|  |                      None,
 |  |                      None,
 | 
											
												
													
														|  |                      &mut f.decompress_buf,
 |  |                      &mut f.decompress_buf,
 | 
											
												
													
														|  |                  ) {
 |  |                  ) {
 | 
											
										
											
												
													
														|  | @@ -101,8 +103,14 @@ impl InterfaceInner {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              // Decompress headers+payload into the assembler.
 |  |              // Decompress headers+payload into the assembler.
 | 
											
												
													
														|  |              if let Err(e) = frag_slot.add_with(0, |buffer| {
 |  |              if let Err(e) = frag_slot.add_with(0, |buffer| {
 | 
											
												
													
														|  | -                self.decompress_sixlowpan(ieee802154_repr, frag.payload(), Some(total_size), buffer)
 |  | 
 | 
											
												
													
														|  | -                    .map_err(|_| AssemblerError)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                Self::sixlowpan_to_ipv6(
 | 
											
												
													
														|  | 
 |  | +                    &self.sixlowpan_address_context,
 | 
											
												
													
														|  | 
 |  | +                    ieee802154_repr,
 | 
											
												
													
														|  | 
 |  | +                    frag.payload(),
 | 
											
												
													
														|  | 
 |  | +                    Some(total_size),
 | 
											
												
													
														|  | 
 |  | +                    buffer,
 | 
											
												
													
														|  | 
 |  | +                )
 | 
											
												
													
														|  | 
 |  | +                .map_err(|_| AssemblerError)
 | 
											
												
													
														|  |              }) {
 |  |              }) {
 | 
											
												
													
														|  |                  net_debug!("fragmentation error: {:?}", e);
 |  |                  net_debug!("fragmentation error: {:?}", e);
 | 
											
												
													
														|  |                  return None;
 |  |                  return None;
 | 
											
										
											
												
													
														|  | @@ -124,8 +132,8 @@ impl InterfaceInner {
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn decompress_sixlowpan(
 |  | 
 | 
											
												
													
														|  | -        &self,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn sixlowpan_to_ipv6(
 | 
											
												
													
														|  | 
 |  | +        address_context: &[SixlowpanAddressContext],
 | 
											
												
													
														|  |          ieee802154_repr: &Ieee802154Repr,
 |  |          ieee802154_repr: &Ieee802154Repr,
 | 
											
												
													
														|  |          iphc_payload: &[u8],
 |  |          iphc_payload: &[u8],
 | 
											
												
													
														|  |          total_size: Option<usize>,
 |  |          total_size: Option<usize>,
 | 
											
										
											
												
													
														|  | @@ -136,20 +144,40 @@ impl InterfaceInner {
 | 
											
												
													
														|  |              &iphc,
 |  |              &iphc,
 | 
											
												
													
														|  |              ieee802154_repr.src_addr,
 |  |              ieee802154_repr.src_addr,
 | 
											
												
													
														|  |              ieee802154_repr.dst_addr,
 |  |              ieee802154_repr.dst_addr,
 | 
											
												
													
														|  | -            &self.sixlowpan_address_context,
 |  | 
 | 
											
												
													
														|  | 
 |  | +            address_context,
 | 
											
												
													
														|  |          )?;
 |  |          )?;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        let mut decompressed_size = 40 + iphc.payload().len();
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        let next_header = match iphc_repr.next_header {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let first_next_header = match iphc_repr.next_header {
 | 
											
												
													
														|  |              SixlowpanNextHeader::Compressed => {
 |  |              SixlowpanNextHeader::Compressed => {
 | 
											
												
													
														|  |                  match SixlowpanNhcPacket::dispatch(iphc.payload())? {
 |  |                  match SixlowpanNhcPacket::dispatch(iphc.payload())? {
 | 
											
												
													
														|  |                      SixlowpanNhcPacket::ExtHeader => {
 |  |                      SixlowpanNhcPacket::ExtHeader => {
 | 
											
												
													
														|  | -                        net_debug!("Extension headers are currently not supported for 6LoWPAN");
 |  | 
 | 
											
												
													
														|  | -                        IpProtocol::Unknown(0)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        SixlowpanExtHeaderPacket::new_checked(iphc.payload())?
 | 
											
												
													
														|  | 
 |  | +                            .extension_header_id()
 | 
											
												
													
														|  | 
 |  | +                            .into()
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                    SixlowpanNhcPacket::UdpHeader => IpProtocol::Udp,
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            SixlowpanNextHeader::Uncompressed(proto) => proto,
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut decompressed_size = 40 + iphc.payload().len();
 | 
											
												
													
														|  | 
 |  | +        let mut next_header = Some(iphc_repr.next_header);
 | 
											
												
													
														|  | 
 |  | +        let mut data = iphc.payload();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        while let Some(nh) = next_header {
 | 
											
												
													
														|  | 
 |  | +            match nh {
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Compressed => match SixlowpanNhcPacket::dispatch(data)? {
 | 
											
												
													
														|  | 
 |  | +                    SixlowpanNhcPacket::ExtHeader => {
 | 
											
												
													
														|  | 
 |  | +                        let ext_hdr = SixlowpanExtHeaderPacket::new_checked(data)?;
 | 
											
												
													
														|  | 
 |  | +                        let ext_repr = SixlowpanExtHeaderRepr::parse(&ext_hdr)?;
 | 
											
												
													
														|  | 
 |  | +                        decompressed_size += 2;
 | 
											
												
													
														|  | 
 |  | +                        decompressed_size -= ext_repr.buffer_len();
 | 
											
												
													
														|  | 
 |  | +                        next_header = Some(ext_repr.next_header);
 | 
											
												
													
														|  | 
 |  | +                        data = &data[ext_repr.buffer_len() + ext_repr.length as usize..];
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |                      SixlowpanNhcPacket::UdpHeader => {
 |  |                      SixlowpanNhcPacket::UdpHeader => {
 | 
											
												
													
														|  | -                        let udp_packet = SixlowpanUdpNhcPacket::new_checked(iphc.payload())?;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        let udp_packet = SixlowpanUdpNhcPacket::new_checked(data)?;
 | 
											
												
													
														|  |                          let udp_repr = SixlowpanUdpNhcRepr::parse(
 |  |                          let udp_repr = SixlowpanUdpNhcRepr::parse(
 | 
											
												
													
														|  |                              &udp_packet,
 |  |                              &udp_packet,
 | 
											
												
													
														|  |                              &iphc_repr.src_addr,
 |  |                              &iphc_repr.src_addr,
 | 
											
										
											
												
													
														|  | @@ -159,12 +187,20 @@ impl InterfaceInner {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                          decompressed_size += 8;
 |  |                          decompressed_size += 8;
 | 
											
												
													
														|  |                          decompressed_size -= udp_repr.header_len();
 |  |                          decompressed_size -= udp_repr.header_len();
 | 
											
												
													
														|  | -                        IpProtocol::Udp
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | 
 |  | +                },
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Uncompressed(proto) => match proto {
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Tcp => break,
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Udp => break,
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Icmpv6 => break,
 | 
											
												
													
														|  | 
 |  | +                    proto => {
 | 
											
												
													
														|  | 
 |  | +                        net_debug!("unable to decompress Uncompressed({})", proto);
 | 
											
												
													
														|  | 
 |  | +                        return Err(Error);
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                },
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  | -            SixlowpanNextHeader::Uncompressed(proto) => proto,
 |  | 
 | 
											
												
													
														|  | -        };
 |  | 
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          if buffer.len() < decompressed_size {
 |  |          if buffer.len() < decompressed_size {
 | 
											
												
													
														|  |              net_debug!("sixlowpan decompress: buffer too short");
 |  |              net_debug!("sixlowpan decompress: buffer too short");
 | 
											
										
											
												
													
														|  | @@ -178,27 +214,68 @@ impl InterfaceInner {
 | 
											
												
													
														|  |              decompressed_size
 |  |              decompressed_size
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +        let mut rest_size = total_size;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |          let ipv6_repr = Ipv6Repr {
 |  |          let ipv6_repr = Ipv6Repr {
 | 
											
												
													
														|  |              src_addr: iphc_repr.src_addr,
 |  |              src_addr: iphc_repr.src_addr,
 | 
											
												
													
														|  |              dst_addr: iphc_repr.dst_addr,
 |  |              dst_addr: iphc_repr.dst_addr,
 | 
											
												
													
														|  | -            next_header,
 |  | 
 | 
											
												
													
														|  | 
 |  | +            next_header: first_next_header,
 | 
											
												
													
														|  |              payload_len: total_size - 40,
 |  |              payload_len: total_size - 40,
 | 
											
												
													
														|  |              hop_limit: iphc_repr.hop_limit,
 |  |              hop_limit: iphc_repr.hop_limit,
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  | 
 |  | +        rest_size -= 40;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          // Emit the decompressed IPHC header (decompressed to an IPv6 header).
 |  |          // Emit the decompressed IPHC header (decompressed to an IPv6 header).
 | 
											
												
													
														|  |          let mut ipv6_packet = Ipv6PacketWire::new_unchecked(&mut buffer[..ipv6_repr.buffer_len()]);
 |  |          let mut ipv6_packet = Ipv6PacketWire::new_unchecked(&mut buffer[..ipv6_repr.buffer_len()]);
 | 
											
												
													
														|  |          ipv6_repr.emit(&mut ipv6_packet);
 |  |          ipv6_repr.emit(&mut ipv6_packet);
 | 
											
												
													
														|  | -        let buffer = &mut buffer[ipv6_repr.buffer_len()..];
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let mut buffer = &mut buffer[ipv6_repr.buffer_len()..];
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        match iphc_repr.next_header {
 |  | 
 | 
											
												
													
														|  | -            SixlowpanNextHeader::Compressed => {
 |  | 
 | 
											
												
													
														|  | -                match SixlowpanNhcPacket::dispatch(iphc.payload())? {
 |  | 
 | 
											
												
													
														|  | -                    SixlowpanNhcPacket::ExtHeader => todo!(),
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let mut next_header = Some(iphc_repr.next_header);
 | 
											
												
													
														|  | 
 |  | +        let mut data = iphc.payload();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        while let Some(nh) = next_header {
 | 
											
												
													
														|  | 
 |  | +            match nh {
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Compressed => match SixlowpanNhcPacket::dispatch(data)? {
 | 
											
												
													
														|  | 
 |  | +                    SixlowpanNhcPacket::ExtHeader => {
 | 
											
												
													
														|  | 
 |  | +                        let ext_hdr = SixlowpanExtHeaderPacket::new_checked(data)?;
 | 
											
												
													
														|  | 
 |  | +                        let ext_repr = SixlowpanExtHeaderRepr::parse(&ext_hdr)?;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                        let nh = match ext_repr.next_header {
 | 
											
												
													
														|  | 
 |  | +                            SixlowpanNextHeader::Compressed => {
 | 
											
												
													
														|  | 
 |  | +                                let d = &data[ext_repr.length as usize + ext_repr.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +                                match SixlowpanNhcPacket::dispatch(d)? {
 | 
											
												
													
														|  | 
 |  | +                                    SixlowpanNhcPacket::ExtHeader => {
 | 
											
												
													
														|  | 
 |  | +                                        SixlowpanExtHeaderPacket::new_checked(d)?
 | 
											
												
													
														|  | 
 |  | +                                            .extension_header_id()
 | 
											
												
													
														|  | 
 |  | +                                            .into()
 | 
											
												
													
														|  | 
 |  | +                                    }
 | 
											
												
													
														|  | 
 |  | +                                    SixlowpanNhcPacket::UdpHeader => IpProtocol::Udp,
 | 
											
												
													
														|  | 
 |  | +                                }
 | 
											
												
													
														|  | 
 |  | +                            }
 | 
											
												
													
														|  | 
 |  | +                            SixlowpanNextHeader::Uncompressed(proto) => proto,
 | 
											
												
													
														|  | 
 |  | +                        };
 | 
											
												
													
														|  | 
 |  | +                        next_header = Some(ext_repr.next_header);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                        let ipv6_ext_hdr = Ipv6ExtHeaderRepr {
 | 
											
												
													
														|  | 
 |  | +                            next_header: nh,
 | 
											
												
													
														|  | 
 |  | +                            length: ext_repr.length / 8,
 | 
											
												
													
														|  | 
 |  | +                            data: &ext_hdr.payload()[..ext_repr.length as usize],
 | 
											
												
													
														|  | 
 |  | +                        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                        ipv6_ext_hdr.emit(&mut Ipv6ExtHeader::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                            &mut buffer[..ipv6_ext_hdr.header_len()],
 | 
											
												
													
														|  | 
 |  | +                        ));
 | 
											
												
													
														|  | 
 |  | +                        buffer[ipv6_ext_hdr.header_len()..][..ipv6_ext_hdr.data.len()]
 | 
											
												
													
														|  | 
 |  | +                            .copy_from_slice(ipv6_ext_hdr.data);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                        buffer = &mut buffer[ipv6_ext_hdr.header_len() + ipv6_ext_hdr.data.len()..];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                        rest_size -= ipv6_ext_hdr.header_len() + ipv6_ext_hdr.data.len();
 | 
											
												
													
														|  | 
 |  | +                        data = &data[ext_repr.buffer_len() + ext_repr.length as usize..];
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  |                      SixlowpanNhcPacket::UdpHeader => {
 |  |                      SixlowpanNhcPacket::UdpHeader => {
 | 
											
												
													
														|  | -                        // We need to uncompress the UDP packet and emit it to the
 |  | 
 | 
											
												
													
														|  | -                        // buffer.
 |  | 
 | 
											
												
													
														|  | -                        let udp_packet = SixlowpanUdpNhcPacket::new_checked(iphc.payload())?;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        let udp_packet = SixlowpanUdpNhcPacket::new_checked(data)?;
 | 
											
												
													
														|  | 
 |  | +                        let payload = udp_packet.payload();
 | 
											
												
													
														|  |                          let udp_repr = SixlowpanUdpNhcRepr::parse(
 |  |                          let udp_repr = SixlowpanUdpNhcRepr::parse(
 | 
											
												
													
														|  |                              &udp_packet,
 |  |                              &udp_packet,
 | 
											
												
													
														|  |                              &iphc_repr.src_addr,
 |  |                              &iphc_repr.src_addr,
 | 
											
										
											
												
													
														|  | @@ -206,22 +283,33 @@ impl InterfaceInner {
 | 
											
												
													
														|  |                              &ChecksumCapabilities::ignored(),
 |  |                              &ChecksumCapabilities::ignored(),
 | 
											
												
													
														|  |                          )?;
 |  |                          )?;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                        let mut udp = UdpPacket::new_unchecked(
 |  | 
 | 
											
												
													
														|  | -                            &mut buffer[..udp_repr.0.header_len() + iphc.payload().len()
 |  | 
 | 
											
												
													
														|  | -                                - udp_repr.header_len()],
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                        udp_repr.0.emit_header(&mut udp, ipv6_repr.payload_len - 8);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        let mut udp = UdpPacket::new_unchecked(&mut buffer[..payload.len() + 8]);
 | 
											
												
													
														|  | 
 |  | +                        udp_repr
 | 
											
												
													
														|  | 
 |  | +                            .0
 | 
											
												
													
														|  | 
 |  | +                            .emit_header(&mut udp, rest_size - udp_repr.0.header_len());
 | 
											
												
													
														|  | 
 |  | +                        buffer[8..][..payload.len()].copy_from_slice(payload);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                        buffer[8..].copy_from_slice(&iphc.payload()[udp_repr.header_len()..]);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            SixlowpanNextHeader::Uncompressed(_) => {
 |  | 
 | 
											
												
													
														|  | -                // For uncompressed headers we just copy the slice.
 |  | 
 | 
											
												
													
														|  | -                let len = iphc.payload().len();
 |  | 
 | 
											
												
													
														|  | -                buffer[..len].copy_from_slice(iphc.payload());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                },
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Uncompressed(proto) => match proto {
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::HopByHop => unreachable!(),
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Tcp => {
 | 
											
												
													
														|  | 
 |  | +                        buffer.copy_from_slice(data);
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Udp => {
 | 
											
												
													
														|  | 
 |  | +                        buffer.copy_from_slice(data);
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                    IpProtocol::Icmpv6 => {
 | 
											
												
													
														|  | 
 |  | +                        buffer.copy_from_slice(data);
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                    _ => unreachable!(),
 | 
											
												
													
														|  | 
 |  | +                },
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  | -        };
 |  | 
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          Ok(decompressed_size)
 |  |          Ok(decompressed_size)
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
										
											
												
													
														|  | @@ -234,69 +322,20 @@ impl InterfaceInner {
 | 
											
												
													
														|  |          ieee_repr: Ieee802154Repr,
 |  |          ieee_repr: Ieee802154Repr,
 | 
											
												
													
														|  |          frag: &mut Fragmenter,
 |  |          frag: &mut Fragmenter,
 | 
											
												
													
														|  |      ) {
 |  |      ) {
 | 
											
												
													
														|  | -        let ip_repr = packet.ip_repr();
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        let (src_addr, dst_addr) = match (ip_repr.src_addr(), ip_repr.dst_addr()) {
 |  | 
 | 
											
												
													
														|  | -            (IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => (src_addr, dst_addr),
 |  | 
 | 
											
												
													
														|  | -            #[allow(unreachable_patterns)]
 |  | 
 | 
											
												
													
														|  | -            _ => {
 |  | 
 | 
											
												
													
														|  | -                unreachable!()
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let packet = match packet {
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv4")]
 | 
											
												
													
														|  | 
 |  | +            IpPacket::Ipv4(_) => unreachable!(),
 | 
											
												
													
														|  | 
 |  | +            IpPacket::Ipv6(packet) => packet,
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        // Create the 6LoWPAN IPHC header.
 |  | 
 | 
											
												
													
														|  | -        let iphc_repr = SixlowpanIphcRepr {
 |  | 
 | 
											
												
													
														|  | -            src_addr,
 |  | 
 | 
											
												
													
														|  | -            ll_src_addr: ieee_repr.src_addr,
 |  | 
 | 
											
												
													
														|  | -            dst_addr,
 |  | 
 | 
											
												
													
														|  | -            ll_dst_addr: ieee_repr.dst_addr,
 |  | 
 | 
											
												
													
														|  | -            next_header: match &packet.payload() {
 |  | 
 | 
											
												
													
														|  | -                IpPayload::Icmpv6(..) => SixlowpanNextHeader::Uncompressed(IpProtocol::Icmpv6),
 |  | 
 | 
											
												
													
														|  | -                #[cfg(feature = "socket-tcp")]
 |  | 
 | 
											
												
													
														|  | -                IpPayload::Tcp(..) => SixlowpanNextHeader::Uncompressed(IpProtocol::Tcp),
 |  | 
 | 
											
												
													
														|  | -                #[cfg(feature = "socket-udp")]
 |  | 
 | 
											
												
													
														|  | -                IpPayload::Udp(..) => SixlowpanNextHeader::Compressed,
 |  | 
 | 
											
												
													
														|  | -                #[allow(unreachable_patterns)]
 |  | 
 | 
											
												
													
														|  | -                _ => {
 |  | 
 | 
											
												
													
														|  | -                    net_debug!("dispatch_ieee802154: dropping, unhandled protocol.");
 |  | 
 | 
											
												
													
														|  | -                    return;
 |  | 
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -            },
 |  | 
 | 
											
												
													
														|  | -            hop_limit: ip_repr.hop_limit(),
 |  | 
 | 
											
												
													
														|  | -            ecn: None,
 |  | 
 | 
											
												
													
														|  | -            dscp: None,
 |  | 
 | 
											
												
													
														|  | -            flow_label: None,
 |  | 
 | 
											
												
													
														|  | -        };
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        // Now we calculate the total size of the packet.
 |  | 
 | 
											
												
													
														|  | -        // We need to know this, such that we know when to do the fragmentation.
 |  | 
 | 
											
												
													
														|  | -        let mut total_size = 0;
 |  | 
 | 
											
												
													
														|  | -        total_size += iphc_repr.buffer_len();
 |  | 
 | 
											
												
													
														|  | -        let mut _compressed_headers_len = iphc_repr.buffer_len();
 |  | 
 | 
											
												
													
														|  | -        let mut _uncompressed_headers_len = ip_repr.header_len();
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -        match packet.payload() {
 |  | 
 | 
											
												
													
														|  | -            #[cfg(feature = "socket-udp")]
 |  | 
 | 
											
												
													
														|  | -            IpPayload::Udp(udpv6_repr, payload) => {
 |  | 
 | 
											
												
													
														|  | -                let udp_repr = SixlowpanUdpNhcRepr(*udpv6_repr);
 |  | 
 | 
											
												
													
														|  | -                _compressed_headers_len += udp_repr.header_len();
 |  | 
 | 
											
												
													
														|  | -                _uncompressed_headers_len += udpv6_repr.header_len();
 |  | 
 | 
											
												
													
														|  | -                total_size += udp_repr.header_len() + payload.len();
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            #[cfg(feature = "socket-tcp")]
 |  | 
 | 
											
												
													
														|  | -            IpPayload::Tcp(tcp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                total_size += tcp_repr.buffer_len();
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            #[cfg(feature = "proto-ipv6")]
 |  | 
 | 
											
												
													
														|  | -            IpPayload::Icmpv6(icmp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                total_size += icmp_repr.buffer_len();
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            #[allow(unreachable_patterns)]
 |  | 
 | 
											
												
													
														|  | -            _ => unreachable!(),
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | 
 |  | +        // First we calculate the size we are going to need. If the size is bigger than the MTU,
 | 
											
												
													
														|  | 
 |  | +        // then we use fragmentation.
 | 
											
												
													
														|  | 
 |  | +        let (total_size, compressed_size, uncompressed_size) =
 | 
											
												
													
														|  | 
 |  | +            Self::compressed_packet_size(&packet, &ieee_repr);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          let ieee_len = ieee_repr.buffer_len();
 |  |          let ieee_len = ieee_repr.buffer_len();
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +        // TODO(thvdveld): use the MTU of the device.
 | 
											
												
													
														|  |          if total_size + ieee_len > 125 {
 |  |          if total_size + ieee_len > 125 {
 | 
											
												
													
														|  |              #[cfg(feature = "proto-sixlowpan-fragmentation")]
 |  |              #[cfg(feature = "proto-sixlowpan-fragmentation")]
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
										
											
												
													
														|  | @@ -308,8 +347,8 @@ impl InterfaceInner {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  // `dispatch_ieee802154_frag` 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...
 |  |                  // the link local source and destination address...
 | 
											
												
													
														|  | -                let pkt = frag;
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +                let pkt = frag;
 | 
											
												
													
														|  |                  if pkt.buffer.len() < total_size {
 |  |                  if pkt.buffer.len() < total_size {
 | 
											
												
													
														|  |                      net_debug!(
 |  |                      net_debug!(
 | 
											
												
													
														|  |                          "dispatch_ieee802154: dropping, \
 |  |                          "dispatch_ieee802154: dropping, \
 | 
											
										
											
												
													
														|  | @@ -319,63 +358,23 @@ impl InterfaceInner {
 | 
											
												
													
														|  |                      return;
 |  |                      return;
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                pkt.sixlowpan.ll_dst_addr = ieee_repr.dst_addr.unwrap();
 |  | 
 | 
											
												
													
														|  | -                pkt.sixlowpan.ll_src_addr = ieee_repr.src_addr.unwrap();
 |  | 
 | 
											
												
													
														|  | 
 |  | +                let payload_length = packet.header.payload_len;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                let mut iphc_packet =
 |  | 
 | 
											
												
													
														|  | -                    SixlowpanIphcPacket::new_unchecked(&mut pkt.buffer[..iphc_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                iphc_repr.emit(&mut iphc_packet);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                let b = &mut pkt.buffer[iphc_repr.buffer_len()..];
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                match packet.payload() {
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "socket-udp")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Udp(udpv6_repr, payload) => {
 |  | 
 | 
											
												
													
														|  | -                        let udp_repr = SixlowpanUdpNhcRepr(*udpv6_repr);
 |  | 
 | 
											
												
													
														|  | -                        let mut udp_packet = SixlowpanUdpNhcPacket::new_unchecked(
 |  | 
 | 
											
												
													
														|  | -                            &mut b[..udp_repr.header_len() + payload.len()],
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                        udp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &mut udp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr,
 |  | 
 | 
											
												
													
														|  | -                            payload.len(),
 |  | 
 | 
											
												
													
														|  | -                            |buf| buf.copy_from_slice(payload),
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "socket-tcp")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Tcp(tcp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                        let mut tcp_packet =
 |  | 
 | 
											
												
													
														|  | -                            TcpPacket::new_unchecked(&mut b[..tcp_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                        tcp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &mut tcp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &self.caps.checksum,
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "proto-ipv6")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Icmpv6(icmp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                        let mut icmp_packet =
 |  | 
 | 
											
												
													
														|  | -                            Icmpv6Packet::new_unchecked(&mut b[..icmp_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                        icmp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &mut icmp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &self.caps.checksum,
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[allow(unreachable_patterns)]
 |  | 
 | 
											
												
													
														|  | -                    _ => unreachable!(),
 |  | 
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | 
 |  | +                Self::ipv6_to_sixlowpan(
 | 
											
												
													
														|  | 
 |  | +                    &self.checksum_caps(),
 | 
											
												
													
														|  | 
 |  | +                    packet,
 | 
											
												
													
														|  | 
 |  | +                    &ieee_repr,
 | 
											
												
													
														|  | 
 |  | +                    &mut pkt.buffer[..],
 | 
											
												
													
														|  | 
 |  | +                );
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +                pkt.sixlowpan.ll_dst_addr = ieee_repr.dst_addr.unwrap();
 | 
											
												
													
														|  | 
 |  | +                pkt.sixlowpan.ll_src_addr = ieee_repr.src_addr.unwrap();
 | 
											
												
													
														|  |                  pkt.packet_len = total_size;
 |  |                  pkt.packet_len = total_size;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  // The datagram size that we need to set in the first fragment header is equal to the
 |  |                  // The datagram size that we need to set in the first fragment header is equal to the
 | 
											
												
													
														|  |                  // IPv6 payload length + 40.
 |  |                  // IPv6 payload length + 40.
 | 
											
												
													
														|  | -                pkt.sixlowpan.datagram_size = (packet.ip_repr().payload_len() + 40) as u16;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                pkt.sixlowpan.datagram_size = (payload_length + 40) as u16;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                // We generate a random tag.
 |  | 
 | 
											
												
													
														|  |                  let tag = self.get_sixlowpan_fragment_tag();
 |  |                  let tag = self.get_sixlowpan_fragment_tag();
 | 
											
												
													
														|  |                  // We save the tag for the other fragments that will be created when calling `poll`
 |  |                  // We save the tag for the other fragments that will be created when calling `poll`
 | 
											
												
													
														|  |                  // multiple times.
 |  |                  // multiple times.
 | 
											
										
											
												
													
														|  | @@ -398,15 +397,15 @@ impl InterfaceInner {
 | 
											
												
													
														|  |                  //
 |  |                  //
 | 
											
												
													
														|  |                  // [RFC 4944 § 5.3]: https://datatracker.ietf.org/doc/html/rfc4944#section-5.3
 |  |                  // [RFC 4944 § 5.3]: https://datatracker.ietf.org/doc/html/rfc4944#section-5.3
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                let header_diff = _uncompressed_headers_len - _compressed_headers_len;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                let header_diff = uncompressed_size - compressed_size;
 | 
											
												
													
														|  |                  let frag1_size =
 |  |                  let frag1_size =
 | 
											
												
													
														|  | -                    (125 - ieee_len - frag1.buffer_len() + header_diff) / 8 * 8 - (header_diff);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    (125 - ieee_len - frag1.buffer_len() + header_diff) / 8 * 8 - header_diff;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  pkt.sixlowpan.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.sent_bytes = frag1_size;
 | 
											
												
													
														|  |                  pkt.sixlowpan.datagram_offset = frag1_size + header_diff;
 |  |                  pkt.sixlowpan.datagram_offset = frag1_size + header_diff;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +                tx_token.set_meta(meta);
 | 
											
												
													
														|  |                  tx_token.consume(ieee_len + frag1.buffer_len() + frag1_size, |mut tx_buf| {
 |  |                  tx_token.consume(ieee_len + frag1.buffer_len() + frag1_size, |mut tx_buf| {
 | 
											
												
													
														|  |                      // Add the IEEE header.
 |  |                      // Add the IEEE header.
 | 
											
												
													
														|  |                      let mut ieee_packet = Ieee802154Frame::new_unchecked(&mut tx_buf[..ieee_len]);
 |  |                      let mut ieee_packet = Ieee802154Frame::new_unchecked(&mut tx_buf[..ieee_len]);
 | 
											
										
											
												
													
														|  | @@ -439,55 +438,241 @@ impl InterfaceInner {
 | 
											
												
													
														|  |                  ieee_repr.emit(&mut ieee_packet);
 |  |                  ieee_repr.emit(&mut ieee_packet);
 | 
											
												
													
														|  |                  tx_buf = &mut tx_buf[ieee_len..];
 |  |                  tx_buf = &mut tx_buf[ieee_len..];
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -                let mut iphc_packet =
 |  | 
 | 
											
												
													
														|  | -                    SixlowpanIphcPacket::new_unchecked(&mut tx_buf[..iphc_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                iphc_repr.emit(&mut iphc_packet);
 |  | 
 | 
											
												
													
														|  | -                tx_buf = &mut tx_buf[iphc_repr.buffer_len()..];
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -                match packet.payload() {
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "socket-udp")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Udp(udpv6_repr, payload) => {
 |  | 
 | 
											
												
													
														|  | -                        let udp_repr = SixlowpanUdpNhcRepr(*udpv6_repr);
 |  | 
 | 
											
												
													
														|  | -                        let mut udp_packet = SixlowpanUdpNhcPacket::new_unchecked(
 |  | 
 | 
											
												
													
														|  | -                            &mut tx_buf[..udp_repr.header_len() + payload.len()],
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                        udp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &mut udp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr,
 |  | 
 | 
											
												
													
														|  | -                            payload.len(),
 |  | 
 | 
											
												
													
														|  | -                            |buf| buf.copy_from_slice(payload),
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "socket-tcp")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Tcp(tcp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                        let mut tcp_packet =
 |  | 
 | 
											
												
													
														|  | -                            TcpPacket::new_unchecked(&mut tx_buf[..tcp_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                        tcp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &mut tcp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &self.caps.checksum,
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[cfg(feature = "proto-ipv6")]
 |  | 
 | 
											
												
													
														|  | -                    IpPayload::Icmpv6(icmp_repr) => {
 |  | 
 | 
											
												
													
														|  | -                        let mut icmp_packet =
 |  | 
 | 
											
												
													
														|  | -                            Icmpv6Packet::new_unchecked(&mut tx_buf[..icmp_repr.buffer_len()]);
 |  | 
 | 
											
												
													
														|  | -                        icmp_repr.emit(
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.src_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &iphc_repr.dst_addr.into(),
 |  | 
 | 
											
												
													
														|  | -                            &mut icmp_packet,
 |  | 
 | 
											
												
													
														|  | -                            &self.caps.checksum,
 |  | 
 | 
											
												
													
														|  | -                        );
 |  | 
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    #[allow(unreachable_patterns)]
 |  | 
 | 
											
												
													
														|  | -                    _ => unreachable!(),
 |  | 
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | 
 |  | +                Self::ipv6_to_sixlowpan(&self.checksum_caps(), packet, &ieee_repr, tx_buf);
 | 
											
												
													
														|  |              });
 |  |              });
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    fn ipv6_to_sixlowpan(
 | 
											
												
													
														|  | 
 |  | +        checksum_caps: &ChecksumCapabilities,
 | 
											
												
													
														|  | 
 |  | +        mut packet: Ipv6Packet,
 | 
											
												
													
														|  | 
 |  | +        ieee_repr: &Ieee802154Repr,
 | 
											
												
													
														|  | 
 |  | +        mut buffer: &mut [u8],
 | 
											
												
													
														|  | 
 |  | +    ) {
 | 
											
												
													
														|  | 
 |  | +        let last_header = packet.payload.as_sixlowpan_next_header();
 | 
											
												
													
														|  | 
 |  | +        let next_header = last_header;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +        let next_header = if packet.hop_by_hop.is_some() {
 | 
											
												
													
														|  | 
 |  | +            SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            next_header
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +        let next_header = if packet.routing.is_some() {
 | 
											
												
													
														|  | 
 |  | +            SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            next_header
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let iphc_repr = SixlowpanIphcRepr {
 | 
											
												
													
														|  | 
 |  | +            src_addr: packet.header.src_addr,
 | 
											
												
													
														|  | 
 |  | +            ll_src_addr: ieee_repr.src_addr,
 | 
											
												
													
														|  | 
 |  | +            dst_addr: packet.header.dst_addr,
 | 
											
												
													
														|  | 
 |  | +            ll_dst_addr: ieee_repr.dst_addr,
 | 
											
												
													
														|  | 
 |  | +            next_header,
 | 
											
												
													
														|  | 
 |  | +            hop_limit: packet.header.hop_limit,
 | 
											
												
													
														|  | 
 |  | +            ecn: None,
 | 
											
												
													
														|  | 
 |  | +            dscp: None,
 | 
											
												
													
														|  | 
 |  | +            flow_label: None,
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        iphc_repr.emit(&mut SixlowpanIphcPacket::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +            &mut buffer[..iphc_repr.buffer_len()],
 | 
											
												
													
														|  | 
 |  | +        ));
 | 
											
												
													
														|  | 
 |  | +        buffer = &mut buffer[iphc_repr.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // Emit the Hop-by-Hop header
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +        if let Some(hbh) = packet.hop_by_hop {
 | 
											
												
													
														|  | 
 |  | +            #[allow(unused)]
 | 
											
												
													
														|  | 
 |  | +            let next_header = last_header;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +            let next_header = if packet.routing.is_some() {
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                last_header
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            let ext_hdr = SixlowpanExtHeaderRepr {
 | 
											
												
													
														|  | 
 |  | +                ext_header_id: SixlowpanExtHeaderId::HopByHopHeader,
 | 
											
												
													
														|  | 
 |  | +                next_header,
 | 
											
												
													
														|  | 
 |  | +                length: hbh.options.iter().map(|o| o.buffer_len()).sum::<usize>() as u8,
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +            ext_hdr.emit(&mut SixlowpanExtHeaderPacket::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                &mut buffer[..ext_hdr.buffer_len()],
 | 
											
												
													
														|  | 
 |  | +            ));
 | 
											
												
													
														|  | 
 |  | +            buffer = &mut buffer[ext_hdr.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            for opt in &hbh.options {
 | 
											
												
													
														|  | 
 |  | +                opt.emit(&mut Ipv6Option::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                    &mut buffer[..opt.buffer_len()],
 | 
											
												
													
														|  | 
 |  | +                ));
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                buffer = &mut buffer[opt.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // Emit the Routing header
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +        if let Some(routing) = &packet.routing {
 | 
											
												
													
														|  | 
 |  | +            let ext_hdr = SixlowpanExtHeaderRepr {
 | 
											
												
													
														|  | 
 |  | +                ext_header_id: SixlowpanExtHeaderId::RoutingHeader,
 | 
											
												
													
														|  | 
 |  | +                next_header,
 | 
											
												
													
														|  | 
 |  | +                length: routing.buffer_len() as u8,
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +            ext_hdr.emit(&mut SixlowpanExtHeaderPacket::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                &mut buffer[..ext_hdr.buffer_len()],
 | 
											
												
													
														|  | 
 |  | +            ));
 | 
											
												
													
														|  | 
 |  | +            buffer = &mut buffer[ext_hdr.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            routing.emit(&mut Ipv6RoutingHeader::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                &mut buffer[..routing.buffer_len()],
 | 
											
												
													
														|  | 
 |  | +            ));
 | 
											
												
													
														|  | 
 |  | +            buffer = &mut buffer[routing.buffer_len()..];
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        match &mut packet.payload {
 | 
											
												
													
														|  | 
 |  | +            IpPayload::Icmpv6(icmp_repr) => {
 | 
											
												
													
														|  | 
 |  | +                icmp_repr.emit(
 | 
											
												
													
														|  | 
 |  | +                    &packet.header.src_addr.into(),
 | 
											
												
													
														|  | 
 |  | +                    &packet.header.dst_addr.into(),
 | 
											
												
													
														|  | 
 |  | +                    &mut Icmpv6Packet::new_unchecked(&mut buffer[..icmp_repr.buffer_len()]),
 | 
											
												
													
														|  | 
 |  | +                    checksum_caps,
 | 
											
												
													
														|  | 
 |  | +                );
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
 | 
											
												
													
														|  | 
 |  | +            IpPayload::Udp(udp_repr, payload) => {
 | 
											
												
													
														|  | 
 |  | +                let udp_repr = SixlowpanUdpNhcRepr(*udp_repr);
 | 
											
												
													
														|  | 
 |  | +                udp_repr.emit(
 | 
											
												
													
														|  | 
 |  | +                    &mut SixlowpanUdpNhcPacket::new_unchecked(
 | 
											
												
													
														|  | 
 |  | +                        &mut buffer[..udp_repr.header_len() + payload.len()],
 | 
											
												
													
														|  | 
 |  | +                    ),
 | 
											
												
													
														|  | 
 |  | +                    &iphc_repr.src_addr,
 | 
											
												
													
														|  | 
 |  | +                    &iphc_repr.dst_addr,
 | 
											
												
													
														|  | 
 |  | +                    payload.len(),
 | 
											
												
													
														|  | 
 |  | +                    |buf| buf.copy_from_slice(payload),
 | 
											
												
													
														|  | 
 |  | +                    checksum_caps,
 | 
											
												
													
														|  | 
 |  | +                );
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "socket-tcp")]
 | 
											
												
													
														|  | 
 |  | +            IpPayload::Tcp(tcp_repr) => {
 | 
											
												
													
														|  | 
 |  | +                tcp_repr.emit(
 | 
											
												
													
														|  | 
 |  | +                    &mut TcpPacket::new_unchecked(&mut buffer[..tcp_repr.buffer_len()]),
 | 
											
												
													
														|  | 
 |  | +                    &packet.header.src_addr.into(),
 | 
											
												
													
														|  | 
 |  | +                    &packet.header.dst_addr.into(),
 | 
											
												
													
														|  | 
 |  | +                    checksum_caps,
 | 
											
												
													
														|  | 
 |  | +                );
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "socket-raw")]
 | 
											
												
													
														|  | 
 |  | +            IpPayload::Raw(_raw) => todo!(),
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            #[allow(unreachable_patterns)]
 | 
											
												
													
														|  | 
 |  | +            _ => unreachable!(),
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /// Calculates three sizes:
 | 
											
												
													
														|  | 
 |  | +    ///  - total size: the size of a compressed IPv6 packet
 | 
											
												
													
														|  | 
 |  | +    ///  - compressed header size: the size of the compressed headers
 | 
											
												
													
														|  | 
 |  | +    ///  - uncompressed header size: the size of the headers that are not compressed
 | 
											
												
													
														|  | 
 |  | +    ///  They are returned as a tuple in the same order.
 | 
											
												
													
														|  | 
 |  | +    fn compressed_packet_size(
 | 
											
												
													
														|  | 
 |  | +        packet: &Ipv6Packet,
 | 
											
												
													
														|  | 
 |  | +        ieee_repr: &Ieee802154Repr,
 | 
											
												
													
														|  | 
 |  | +    ) -> (usize, usize, usize) {
 | 
											
												
													
														|  | 
 |  | +        let last_header = packet.payload.as_sixlowpan_next_header();
 | 
											
												
													
														|  | 
 |  | +        let next_header = last_header;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +        let next_header = if packet.hop_by_hop.is_some() {
 | 
											
												
													
														|  | 
 |  | +            SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            next_header
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +        let next_header = if packet.routing.is_some() {
 | 
											
												
													
														|  | 
 |  | +            SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            next_header
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let iphc = SixlowpanIphcRepr {
 | 
											
												
													
														|  | 
 |  | +            src_addr: packet.header.src_addr,
 | 
											
												
													
														|  | 
 |  | +            ll_src_addr: ieee_repr.src_addr,
 | 
											
												
													
														|  | 
 |  | +            dst_addr: packet.header.dst_addr,
 | 
											
												
													
														|  | 
 |  | +            ll_dst_addr: ieee_repr.dst_addr,
 | 
											
												
													
														|  | 
 |  | +            next_header,
 | 
											
												
													
														|  | 
 |  | +            hop_limit: packet.header.hop_limit,
 | 
											
												
													
														|  | 
 |  | +            ecn: None,
 | 
											
												
													
														|  | 
 |  | +            dscp: None,
 | 
											
												
													
														|  | 
 |  | +            flow_label: None,
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut total_size = iphc.buffer_len();
 | 
											
												
													
														|  | 
 |  | +        let mut compressed_hdr_size = iphc.buffer_len();
 | 
											
												
													
														|  | 
 |  | +        let mut uncompressed_hdr_size = packet.header.buffer_len();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // Add the hop-by-hop to the sizes.
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +        if let Some(hbh) = &packet.hop_by_hop {
 | 
											
												
													
														|  | 
 |  | +            #[allow(unused)]
 | 
											
												
													
														|  | 
 |  | +            let next_header = last_header;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +            let next_header = if packet.routing.is_some() {
 | 
											
												
													
														|  | 
 |  | +                SixlowpanNextHeader::Compressed
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                last_header
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            let options_size = hbh.options.iter().map(|o| o.buffer_len()).sum::<usize>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            let ext_hdr = SixlowpanExtHeaderRepr {
 | 
											
												
													
														|  | 
 |  | +                ext_header_id: SixlowpanExtHeaderId::HopByHopHeader,
 | 
											
												
													
														|  | 
 |  | +                next_header,
 | 
											
												
													
														|  | 
 |  | +                length: hbh.buffer_len() as u8 + options_size as u8,
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            total_size += ext_hdr.buffer_len() + options_size;
 | 
											
												
													
														|  | 
 |  | +            compressed_hdr_size += ext_hdr.buffer_len() + options_size;
 | 
											
												
													
														|  | 
 |  | +            uncompressed_hdr_size += hbh.buffer_len() + options_size;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        // Add the routing header to the sizes.
 | 
											
												
													
														|  | 
 |  | +        #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +        if let Some(routing) = &packet.routing {
 | 
											
												
													
														|  | 
 |  | +            let ext_hdr = SixlowpanExtHeaderRepr {
 | 
											
												
													
														|  | 
 |  | +                ext_header_id: SixlowpanExtHeaderId::RoutingHeader,
 | 
											
												
													
														|  | 
 |  | +                next_header,
 | 
											
												
													
														|  | 
 |  | +                length: routing.buffer_len() as u8,
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +            total_size += ext_hdr.buffer_len() + routing.buffer_len();
 | 
											
												
													
														|  | 
 |  | +            compressed_hdr_size += ext_hdr.buffer_len() + routing.buffer_len();
 | 
											
												
													
														|  | 
 |  | +            uncompressed_hdr_size += routing.buffer_len();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        match packet.payload {
 | 
											
												
													
														|  | 
 |  | +            #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
 | 
											
												
													
														|  | 
 |  | +            IpPayload::Udp(udp_hdr, payload) => {
 | 
											
												
													
														|  | 
 |  | +                uncompressed_hdr_size += udp_hdr.header_len();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                let udp_hdr = SixlowpanUdpNhcRepr(udp_hdr);
 | 
											
												
													
														|  | 
 |  | +                compressed_hdr_size += udp_hdr.header_len();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                total_size += udp_hdr.header_len() + payload.len();
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            _ => {
 | 
											
												
													
														|  | 
 |  | +                total_size += packet.header.payload_len;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        (total_size, compressed_hdr_size, uncompressed_hdr_size)
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      #[cfg(feature = "proto-sixlowpan-fragmentation")]
 |  |      #[cfg(feature = "proto-sixlowpan-fragmentation")]
 | 
											
												
													
														|  |      pub(super) fn dispatch_sixlowpan_frag<Tx: TxToken>(
 |  |      pub(super) fn dispatch_sixlowpan_frag<Tx: TxToken>(
 | 
											
												
													
														|  |          &mut self,
 |  |          &mut self,
 | 
											
										
											
												
													
														|  | @@ -526,3 +711,204 @@ impl InterfaceInner {
 | 
											
												
													
														|  |          );
 |  |          );
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +#[cfg(test)]
 | 
											
												
													
														|  | 
 |  | +#[cfg(all(feature = "proto-rpl", feature = "proto-ipv6-hbh"))]
 | 
											
												
													
														|  | 
 |  | +mod tests {
 | 
											
												
													
														|  | 
 |  | +    use super::*;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    static SIXLOWPAN_COMPRESSED_RPL_DAO: [u8; 99] = [
 | 
											
												
													
														|  | 
 |  | +        0x61, 0xdc, 0x45, 0xcd, 0xab, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x7e, 0xf7, 0x00, 0xe0, 0x3a, 0x06, 0x63, 0x04, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x1e, 0x08, 0x00, 0x9b, 0x02, 0x3e, 0x63, 0x1e, 0x40, 0x00, 0xf1, 0xfd, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x05, 0x12, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x80, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x03, 0x00, 0x03,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x03, 0x06, 0x14, 0x00, 0x00, 0x00, 0x1e, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
 | 
											
												
													
														|  | 
 |  | +    ];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    static SIXLOWPAN_UNCOMPRESSED_RPL_DAO: [u8; 114] = [
 | 
											
												
													
														|  | 
 |  | +        0x60, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x40, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x02, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x3a, 0x00, 0x63, 0x04, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x1e, 0x08, 0x00, 0x9b, 0x02, 0x3e, 0x63, 0x1e, 0x40, 0x00, 0xf1, 0xfd, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x05, 0x12, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x80, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x03, 0x00, 0x03,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x03, 0x06, 0x14, 0x00, 0x00, 0x00, 0x1e, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
											
												
													
														|  | 
 |  | +        0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
 | 
											
												
													
														|  | 
 |  | +    ];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    #[test]
 | 
											
												
													
														|  | 
 |  | +    fn test_sixlowpan_decompress_hop_by_hop_with_icmpv6() {
 | 
											
												
													
														|  | 
 |  | +        let address_context = [SixlowpanAddressContext([
 | 
											
												
													
														|  | 
 |  | +            0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
											
												
													
														|  | 
 |  | +        ])];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let ieee_frame = Ieee802154Frame::new_checked(&SIXLOWPAN_COMPRESSED_RPL_DAO).unwrap();
 | 
											
												
													
														|  | 
 |  | +        let ieee_repr = Ieee802154Repr::parse(&ieee_frame).unwrap();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut buffer = [0u8; 256];
 | 
											
												
													
														|  | 
 |  | +        let len = InterfaceInner::sixlowpan_to_ipv6(
 | 
											
												
													
														|  | 
 |  | +            &address_context,
 | 
											
												
													
														|  | 
 |  | +            &ieee_repr,
 | 
											
												
													
														|  | 
 |  | +            ieee_frame.payload().unwrap(),
 | 
											
												
													
														|  | 
 |  | +            None,
 | 
											
												
													
														|  | 
 |  | +            &mut buffer[..],
 | 
											
												
													
														|  | 
 |  | +        )
 | 
											
												
													
														|  | 
 |  | +        .unwrap();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        assert_eq!(&buffer[..len], &SIXLOWPAN_UNCOMPRESSED_RPL_DAO);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    #[test]
 | 
											
												
													
														|  | 
 |  | +    fn test_sixlowpan_compress_hop_by_hop_with_icmpv6() {
 | 
											
												
													
														|  | 
 |  | +        let ieee_repr = Ieee802154Repr {
 | 
											
												
													
														|  | 
 |  | +            frame_type: Ieee802154FrameType::Data,
 | 
											
												
													
														|  | 
 |  | +            security_enabled: false,
 | 
											
												
													
														|  | 
 |  | +            frame_pending: false,
 | 
											
												
													
														|  | 
 |  | +            ack_request: true,
 | 
											
												
													
														|  | 
 |  | +            sequence_number: Some(69),
 | 
											
												
													
														|  | 
 |  | +            pan_id_compression: true,
 | 
											
												
													
														|  | 
 |  | +            frame_version: Ieee802154FrameVersion::Ieee802154_2006,
 | 
											
												
													
														|  | 
 |  | +            dst_pan_id: Some(Ieee802154Pan(43981)),
 | 
											
												
													
														|  | 
 |  | +            dst_addr: Some(Ieee802154Address::Extended([0, 1, 0, 1, 0, 1, 0, 1])),
 | 
											
												
													
														|  | 
 |  | +            src_pan_id: None,
 | 
											
												
													
														|  | 
 |  | +            src_addr: Some(Ieee802154Address::Extended([0, 3, 0, 3, 0, 3, 0, 3])),
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut ip_packet = Ipv6Packet {
 | 
											
												
													
														|  | 
 |  | +            header: Ipv6Repr {
 | 
											
												
													
														|  | 
 |  | +                src_addr: Ipv6Address::from_bytes(&[
 | 
											
												
													
														|  | 
 |  | +                    253, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 3, 0, 3, 0, 3,
 | 
											
												
													
														|  | 
 |  | +                ]),
 | 
											
												
													
														|  | 
 |  | +                dst_addr: Ipv6Address::from_bytes(&[
 | 
											
												
													
														|  | 
 |  | +                    253, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1,
 | 
											
												
													
														|  | 
 |  | +                ]),
 | 
											
												
													
														|  | 
 |  | +                next_header: IpProtocol::Icmpv6,
 | 
											
												
													
														|  | 
 |  | +                payload_len: 66,
 | 
											
												
													
														|  | 
 |  | +                hop_limit: 64,
 | 
											
												
													
														|  | 
 |  | +            },
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +            hop_by_hop: None,
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-fragmentation")]
 | 
											
												
													
														|  | 
 |  | +            fragment: None,
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +            routing: None,
 | 
											
												
													
														|  | 
 |  | +            payload: IpPayload::Icmpv6(Icmpv6Repr::Rpl(RplRepr::DestinationAdvertisementObject {
 | 
											
												
													
														|  | 
 |  | +                rpl_instance_id: RplInstanceId::Global(30),
 | 
											
												
													
														|  | 
 |  | +                expect_ack: false,
 | 
											
												
													
														|  | 
 |  | +                sequence: 241,
 | 
											
												
													
														|  | 
 |  | +                dodag_id: Some(Ipv6Address::from_bytes(&[
 | 
											
												
													
														|  | 
 |  | +                    253, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1,
 | 
											
												
													
														|  | 
 |  | +                ])),
 | 
											
												
													
														|  | 
 |  | +                options: &[],
 | 
											
												
													
														|  | 
 |  | +            })),
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let (total_size, _, _) = InterfaceInner::compressed_packet_size(&mut ip_packet, &ieee_repr);
 | 
											
												
													
														|  | 
 |  | +        let mut buffer = vec![0u8; total_size];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        InterfaceInner::ipv6_to_sixlowpan(
 | 
											
												
													
														|  | 
 |  | +            &ChecksumCapabilities::default(),
 | 
											
												
													
														|  | 
 |  | +            ip_packet,
 | 
											
												
													
														|  | 
 |  | +            &ieee_repr,
 | 
											
												
													
														|  | 
 |  | +            &mut buffer[..total_size],
 | 
											
												
													
														|  | 
 |  | +        );
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let result = [
 | 
											
												
													
														|  | 
 |  | +            0x7e, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x3, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1,
 | 
											
												
													
														|  | 
 |  | +            0xe0, 0x3a, 0x6, 0x63, 0x4, 0x0, 0x1e, 0x3, 0x0, 0x9b, 0x2, 0x3e, 0x63, 0x1e, 0x40,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0xf1, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x1, 0x5, 0x12, 0x0, 0x80, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x3,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0x3, 0x0, 0x3, 0x6, 0x14, 0x0, 0x0, 0x0, 0x1e, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1,
 | 
											
												
													
														|  | 
 |  | +        ];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        assert_eq!(&result, &result);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    #[test]
 | 
											
												
													
														|  | 
 |  | +    fn test_sixlowpan_compress_hop_by_hop_with_udp() {
 | 
											
												
													
														|  | 
 |  | +        let ieee_repr = Ieee802154Repr {
 | 
											
												
													
														|  | 
 |  | +            frame_type: Ieee802154FrameType::Data,
 | 
											
												
													
														|  | 
 |  | +            security_enabled: false,
 | 
											
												
													
														|  | 
 |  | +            frame_pending: false,
 | 
											
												
													
														|  | 
 |  | +            ack_request: true,
 | 
											
												
													
														|  | 
 |  | +            sequence_number: Some(69),
 | 
											
												
													
														|  | 
 |  | +            pan_id_compression: true,
 | 
											
												
													
														|  | 
 |  | +            frame_version: Ieee802154FrameVersion::Ieee802154_2006,
 | 
											
												
													
														|  | 
 |  | +            dst_pan_id: Some(Ieee802154Pan(43981)),
 | 
											
												
													
														|  | 
 |  | +            dst_addr: Some(Ieee802154Address::Extended([0, 1, 0, 1, 0, 1, 0, 1])),
 | 
											
												
													
														|  | 
 |  | +            src_pan_id: None,
 | 
											
												
													
														|  | 
 |  | +            src_addr: Some(Ieee802154Address::Extended([0, 3, 0, 3, 0, 3, 0, 3])),
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let addr = Ipv6Address::from_bytes(&[253, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 3, 0, 3, 0, 3]);
 | 
											
												
													
														|  | 
 |  | +        let parent_address =
 | 
											
												
													
														|  | 
 |  | +            Ipv6Address::from_bytes(&[253, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1]);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut hbh_options = heapless::Vec::new();
 | 
											
												
													
														|  | 
 |  | +        hbh_options
 | 
											
												
													
														|  | 
 |  | +            .push(Ipv6OptionRepr::Rpl(RplHopByHopRepr {
 | 
											
												
													
														|  | 
 |  | +                down: false,
 | 
											
												
													
														|  | 
 |  | +                rank_error: false,
 | 
											
												
													
														|  | 
 |  | +                forwarding_error: false,
 | 
											
												
													
														|  | 
 |  | +                instance_id: RplInstanceId::from(0x1e),
 | 
											
												
													
														|  | 
 |  | +                sender_rank: 0x300,
 | 
											
												
													
														|  | 
 |  | +            }))
 | 
											
												
													
														|  | 
 |  | +            .unwrap();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let mut ip_packet = Ipv6Packet {
 | 
											
												
													
														|  | 
 |  | +            header: Ipv6Repr {
 | 
											
												
													
														|  | 
 |  | +                src_addr: addr,
 | 
											
												
													
														|  | 
 |  | +                dst_addr: parent_address,
 | 
											
												
													
														|  | 
 |  | +                next_header: IpProtocol::Icmpv6,
 | 
											
												
													
														|  | 
 |  | +                payload_len: 66,
 | 
											
												
													
														|  | 
 |  | +                hop_limit: 64,
 | 
											
												
													
														|  | 
 |  | +            },
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-hbh")]
 | 
											
												
													
														|  | 
 |  | +            hop_by_hop: Some(Ipv6HopByHopRepr {
 | 
											
												
													
														|  | 
 |  | +                options: hbh_options,
 | 
											
												
													
														|  | 
 |  | +            }),
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-fragmentation")]
 | 
											
												
													
														|  | 
 |  | +            fragment: None,
 | 
											
												
													
														|  | 
 |  | +            #[cfg(feature = "proto-ipv6-routing")]
 | 
											
												
													
														|  | 
 |  | +            routing: None,
 | 
											
												
													
														|  | 
 |  | +            payload: IpPayload::Icmpv6(Icmpv6Repr::Rpl(RplRepr::DestinationAdvertisementObject {
 | 
											
												
													
														|  | 
 |  | +                rpl_instance_id: RplInstanceId::Global(30),
 | 
											
												
													
														|  | 
 |  | +                expect_ack: false,
 | 
											
												
													
														|  | 
 |  | +                sequence: 241,
 | 
											
												
													
														|  | 
 |  | +                dodag_id: Some(Ipv6Address::from_bytes(&[
 | 
											
												
													
														|  | 
 |  | +                    253, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1,
 | 
											
												
													
														|  | 
 |  | +                ])),
 | 
											
												
													
														|  | 
 |  | +                options: &[
 | 
											
												
													
														|  | 
 |  | +                    5, 18, 0, 128, 253, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 3, 0, 3, 0, 3, 6, 20, 0, 0,
 | 
											
												
													
														|  | 
 |  | +                    0, 30, 253, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1,
 | 
											
												
													
														|  | 
 |  | +                ],
 | 
											
												
													
														|  | 
 |  | +            })),
 | 
											
												
													
														|  | 
 |  | +        };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let (total_size, _, _) = InterfaceInner::compressed_packet_size(&mut ip_packet, &ieee_repr);
 | 
											
												
													
														|  | 
 |  | +        let mut buffer = vec![0u8; total_size];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        InterfaceInner::ipv6_to_sixlowpan(
 | 
											
												
													
														|  | 
 |  | +            &ChecksumCapabilities::default(),
 | 
											
												
													
														|  | 
 |  | +            ip_packet,
 | 
											
												
													
														|  | 
 |  | +            &ieee_repr,
 | 
											
												
													
														|  | 
 |  | +            &mut buffer[..total_size],
 | 
											
												
													
														|  | 
 |  | +        );
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        let result = [
 | 
											
												
													
														|  | 
 |  | +            0x7e, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x3, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1,
 | 
											
												
													
														|  | 
 |  | +            0xe0, 0x3a, 0x6, 0x63, 0x4, 0x0, 0x1e, 0x3, 0x0, 0x9b, 0x2, 0x3e, 0x63, 0x1e, 0x40,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0xf1, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x1, 0x5, 0x12, 0x0, 0x80, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x3,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0x3, 0x0, 0x3, 0x6, 0x14, 0x0, 0x0, 0x0, 0x1e, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
											
												
													
														|  | 
 |  | +            0x0, 0x2, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1,
 | 
											
												
													
														|  | 
 |  | +        ];
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        assert_eq!(&buffer[..total_size], &result);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 |