Skip to content

Commit c294ce5

Browse files
committed
Move 6LoWPAN frag handling to own function
1 parent 82faba2 commit c294ce5

File tree

1 file changed

+116
-99
lines changed

1 file changed

+116
-99
lines changed

src/iface/interface.rs

Lines changed: 116 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,105 +1806,9 @@ impl<'a> InterfaceInner<'a> {
18061806
}
18071807
#[cfg(feature = "proto-sixlowpan-fragmentation")]
18081808
SixlowpanPacket::FragmentHeader => {
1809-
let (fragments, timeout) = _fragments.unwrap();
1810-
1811-
// We have a fragment header, which means we cannot process the 6LoWPAN packet,
1812-
// unless we have a complete one after processing this fragment.
1813-
let frag = check!(SixlowpanFragPacket::new_checked(payload));
1814-
1815-
// The key specifies to which 6LoWPAN fragment it belongs too.
1816-
// It is based on the link layer addresses, the tag and the size.
1817-
let key = frag.get_key(ieee802154_repr);
1818-
1819-
// The offset of this fragment in increments of 8 octets.
1820-
let offset = frag.datagram_offset() as usize * 8;
1821-
1822-
if frag.is_first_fragment() {
1823-
// The first fragment contains the total size of the IPv6 packet.
1824-
// However, we received a packet that is compressed following the 6LoWPAN
1825-
// standard. This means we need to convert the IPv6 packet size to a 6LoWPAN
1826-
// packet size. The packet size can be different because of first the
1827-
// compression of the IP header and when UDP is used (because the UDP header
1828-
// can also be compressed). Other headers are not compressed by 6LoWPAN.
1829-
1830-
let iphc = check!(SixlowpanIphcPacket::new_checked(frag.payload()));
1831-
let iphc_repr = check!(SixlowpanIphcRepr::parse(
1832-
&iphc,
1833-
ieee802154_repr.src_addr,
1834-
ieee802154_repr.dst_addr,
1835-
self.sixlowpan_address_context
1836-
));
1837-
1838-
// The uncompressed header size always starts with 40, since this is the size
1839-
// of a IPv6 header.
1840-
let mut uncompressed_header_size = 40;
1841-
let mut compressed_header_size = iphc.header_len();
1842-
1843-
// We need to check if we have an UDP packet, since this header can also be
1844-
// compressed by 6LoWPAN. We currently don't support extension headers yet.
1845-
match iphc_repr.next_header {
1846-
SixlowpanNextHeader::Compressed => {
1847-
match check!(SixlowpanNhcPacket::dispatch(iphc.payload())) {
1848-
SixlowpanNhcPacket::ExtHeader => {
1849-
net_debug!("6LoWPAN: extension headers not supported");
1850-
return None;
1851-
}
1852-
SixlowpanNhcPacket::UdpHeader => {
1853-
let udp_packet =
1854-
check!(SixlowpanUdpNhcPacket::new_checked(iphc.payload()));
1855-
1856-
uncompressed_header_size += 8;
1857-
compressed_header_size +=
1858-
1 + udp_packet.ports_size() + udp_packet.checksum_size();
1859-
}
1860-
}
1861-
}
1862-
SixlowpanNextHeader::Uncompressed(_) => (),
1863-
}
1864-
1865-
// We reserve a spot in the packet assembler set and add the required
1866-
// information to the packet assembler.
1867-
// This information is the total size of the packet when it is fully assmbled.
1868-
// We also pass the header size, since this is needed when other fragments
1869-
// (other than the first one) are added.
1870-
let frag_slot = match fragments.reserve_with_key(&key) {
1871-
Ok(frag) => frag,
1872-
Err(Error::PacketAssemblerSetFull) => {
1873-
net_debug!("No available packet assembler for fragmented packet");
1874-
return Default::default();
1875-
}
1876-
e => check!(e),
1877-
};
1878-
1879-
check!(frag_slot.start(
1880-
Some(
1881-
frag.datagram_size() as usize - uncompressed_header_size
1882-
+ compressed_header_size
1883-
),
1884-
self.now + timeout,
1885-
-((uncompressed_header_size - compressed_header_size) as isize),
1886-
));
1887-
}
1888-
1889-
let frags = check!(fragments.get_packet_assembler_mut(&key));
1890-
1891-
net_trace!("6LoWPAN: received packet fragment");
1892-
1893-
// Add the fragment to the packet assembler.
1894-
match frags.add(frag.payload(), offset) {
1895-
Ok(true) => {
1896-
net_trace!("6LoWPAN: fragmented packet now complete");
1897-
check!(fragments.get_assembled_packet(&key))
1898-
}
1899-
Ok(false) => {
1900-
return None;
1901-
}
1902-
Err(Error::PacketAssemblerOverlap) => {
1903-
net_trace!("6LoWPAN: overlap in packet");
1904-
frags.mark_discarded();
1905-
return None;
1906-
}
1907-
Err(_) => return None,
1809+
match self.process_sixlowpan_fragment(ieee802154_repr, payload, _fragments) {
1810+
Some(payload) => payload,
1811+
None => return None,
19081812
}
19091813
}
19101814
SixlowpanPacket::IphcHeader => payload.as_ref(),
@@ -1983,6 +1887,119 @@ impl<'a> InterfaceInner<'a> {
19831887
}
19841888
}
19851889

1890+
#[cfg(feature = "proto-sixlowpan-fragmentation")]
1891+
fn process_sixlowpan_fragment<'output, 'payload: 'output, T: AsRef<[u8]> + ?Sized>(
1892+
&mut self,
1893+
ieee802154_repr: &Ieee802154Repr,
1894+
payload: &'payload T,
1895+
fragments: Option<(
1896+
&'output mut PacketAssemblerSet<'a, SixlowpanFragKey>,
1897+
Duration,
1898+
)>,
1899+
) -> Option<&'output [u8]> {
1900+
let (fragments, timeout) = fragments.unwrap();
1901+
1902+
// We have a fragment header, which means we cannot process the 6LoWPAN packet,
1903+
// unless we have a complete one after processing this fragment.
1904+
let frag = check!(SixlowpanFragPacket::new_checked(payload));
1905+
1906+
// The key specifies to which 6LoWPAN fragment it belongs too.
1907+
// It is based on the link layer addresses, the tag and the size.
1908+
let key = frag.get_key(ieee802154_repr);
1909+
1910+
// The offset of this fragment in increments of 8 octets.
1911+
let offset = frag.datagram_offset() as usize * 8;
1912+
1913+
if frag.is_first_fragment() {
1914+
// The first fragment contains the total size of the IPv6 packet.
1915+
// However, we received a packet that is compressed following the 6LoWPAN
1916+
// standard. This means we need to convert the IPv6 packet size to a 6LoWPAN
1917+
// packet size. The packet size can be different because of first the
1918+
// compression of the IP header and when UDP is used (because the UDP header
1919+
// can also be compressed). Other headers are not compressed by 6LoWPAN.
1920+
1921+
let iphc = check!(SixlowpanIphcPacket::new_checked(frag.payload()));
1922+
let iphc_repr = check!(SixlowpanIphcRepr::parse(
1923+
&iphc,
1924+
ieee802154_repr.src_addr,
1925+
ieee802154_repr.dst_addr,
1926+
self.sixlowpan_address_context,
1927+
));
1928+
1929+
// The uncompressed header size always starts with 40, since this is the size
1930+
// of a IPv6 header.
1931+
let mut uncompressed_header_size = 40;
1932+
let mut compressed_header_size = iphc.header_len();
1933+
1934+
// We need to check if we have an UDP packet, since this header can also be
1935+
// compressed by 6LoWPAN. We currently don't support extension headers yet.
1936+
match iphc_repr.next_header {
1937+
SixlowpanNextHeader::Compressed => {
1938+
match check!(SixlowpanNhcPacket::dispatch(iphc.payload())) {
1939+
SixlowpanNhcPacket::ExtHeader => {
1940+
net_debug!("6LoWPAN: extension headers not supported");
1941+
return None;
1942+
}
1943+
SixlowpanNhcPacket::UdpHeader => {
1944+
let udp_packet =
1945+
check!(SixlowpanUdpNhcPacket::new_checked(iphc.payload()));
1946+
1947+
uncompressed_header_size += 8;
1948+
compressed_header_size +=
1949+
1 + udp_packet.ports_size() + udp_packet.checksum_size();
1950+
}
1951+
}
1952+
}
1953+
SixlowpanNextHeader::Uncompressed(_) => (),
1954+
}
1955+
1956+
// We reserve a spot in the packet assembler set and add the required
1957+
// information to the packet assembler.
1958+
// This information is the total size of the packet when it is fully assmbled.
1959+
// We also pass the header size, since this is needed when other fragments
1960+
// (other than the first one) are added.
1961+
let frag_slot = match fragments.reserve_with_key(&key) {
1962+
Ok(frag) => frag,
1963+
Err(Error::PacketAssemblerSetFull) => {
1964+
net_debug!("No available packet assembler for fragmented packet");
1965+
return Default::default();
1966+
}
1967+
e => check!(e),
1968+
};
1969+
1970+
check!(frag_slot.start(
1971+
Some(
1972+
frag.datagram_size() as usize - uncompressed_header_size
1973+
+ compressed_header_size
1974+
),
1975+
self.now + timeout,
1976+
-((uncompressed_header_size - compressed_header_size) as isize),
1977+
));
1978+
}
1979+
1980+
let frags = check!(fragments.get_packet_assembler_mut(&key));
1981+
1982+
net_trace!("6LoWPAN: received packet fragment");
1983+
1984+
// Add the fragment to the packet assembler.
1985+
match frags.add(frag.payload(), offset) {
1986+
Ok(true) => {
1987+
net_trace!("6LoWPAN: fragmented packet now complete");
1988+
match fragments.get_assembled_packet(&key) {
1989+
Ok(packet) => Some(packet),
1990+
_ => unreachable!(),
1991+
}
1992+
}
1993+
Ok(false) => None,
1994+
Err(Error::PacketAssemblerOverlap) => {
1995+
net_trace!("6LoWPAN: overlap in packet");
1996+
frags.mark_discarded();
1997+
None
1998+
}
1999+
Err(_) => None,
2000+
}
2001+
}
2002+
19862003
#[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
19872004
fn process_arp<'frame, T: AsRef<[u8]>>(
19882005
&mut self,

0 commit comments

Comments
 (0)