Browse Source

Merge pull request #1008 from Jc0x7D3/main

Fix the error of specific length IP packets not being fragmented
Dario Nieuwenhuis 5 months ago
parent
commit
3e61c909fd
3 changed files with 78 additions and 2 deletions
  1. 1 1
      src/iface/interface/mod.rs
  2. 76 0
      src/iface/interface/tests/ipv4.rs
  3. 1 1
      src/lib.rs

+ 1 - 1
src/iface/interface/mod.rs

@@ -1201,7 +1201,7 @@ impl InterfaceInner {
             #[cfg(feature = "proto-ipv4")]
             IpRepr::Ipv4(repr) => {
                 // If we have an IPv4 packet, then we need to check if we need to fragment it.
-                if total_ip_len > self.caps.max_transmission_unit {
+                if total_ip_len > self.caps.ip_mtu() {
                     #[cfg(feature = "proto-ipv4-fragmentation")]
                     {
                         net_debug!("start fragmentation");

+ 76 - 0
src/iface/interface/tests/ipv4.rs

@@ -759,6 +759,82 @@ fn test_handle_igmp(#[case] medium: Medium) {
     }
 }
 
+#[rstest]
+#[case(Medium::Ip)]
+#[cfg(all(feature = "proto-ipv4-fragmentation", feature = "medium-ip"))]
+#[case(Medium::Ethernet)]
+#[cfg(all(feature = "proto-ipv4-fragmentation", feature = "medium-ethernet"))]
+fn test_packet_len(#[case] medium: Medium) {
+    use crate::config::FRAGMENTATION_BUFFER_SIZE;
+
+    let (mut iface, _, _) = setup(medium);
+
+    struct TestTxToken {
+        max_transmission_unit: usize,
+    }
+
+    impl TxToken for TestTxToken {
+        fn consume<R, F>(self, len: usize, f: F) -> R
+        where
+            F: FnOnce(&mut [u8]) -> R,
+        {
+            net_debug!("TxToken get len: {}", len);
+            assert!(len <= self.max_transmission_unit);
+            let mut junk = [0; 1536];
+            f(&mut junk[..len])
+        }
+    }
+
+    iface.inner.neighbor_cache.fill(
+        IpAddress::Ipv4(Ipv4Address::new(127, 0, 0, 1)),
+        HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
+            0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+        ])),
+        Instant::ZERO,
+    );
+
+    for ip_packet_len in [
+        100,
+        iface.inner.ip_mtu(),
+        iface.inner.ip_mtu() + 1,
+        FRAGMENTATION_BUFFER_SIZE,
+    ] {
+        net_debug!("ip_packet_len: {}", ip_packet_len);
+
+        let mut ip_repr = Ipv4Repr {
+            src_addr: Ipv4Address::new(127, 0, 0, 1),
+            dst_addr: Ipv4Address::new(127, 0, 0, 1),
+            next_header: IpProtocol::Udp,
+            payload_len: 0,
+            hop_limit: 64,
+        };
+        let udp_repr = UdpRepr {
+            src_port: 12345,
+            dst_port: 54321,
+        };
+
+        let ip_packet_payload_len = ip_packet_len - ip_repr.buffer_len();
+        let udp_packet_payload_len = ip_packet_payload_len - udp_repr.header_len();
+        ip_repr.payload_len = ip_packet_payload_len;
+
+        let udp_packet_payload = vec![1; udp_packet_payload_len];
+        let ip_payload = IpPayload::Udp(udp_repr, &udp_packet_payload);
+        let ip_packet = Packet::new_ipv4(ip_repr, ip_payload);
+
+        assert_eq!(
+            iface.inner.dispatch_ip(
+                TestTxToken {
+                    max_transmission_unit: iface.inner.caps.max_transmission_unit
+                },
+                PacketMeta::default(),
+                ip_packet,
+                &mut iface.fragmenter,
+            ),
+            Ok(())
+        );
+    }
+}
+
 #[rstest]
 #[case(Medium::Ip)]
 #[cfg(all(feature = "socket-raw", feature = "medium-ip"))]

+ 1 - 1
src/lib.rs

@@ -136,7 +136,7 @@ pub mod config {
     pub const DNS_MAX_NAME_SIZE: usize = 255;
     pub const DNS_MAX_RESULT_COUNT: usize = 1;
     pub const DNS_MAX_SERVER_COUNT: usize = 1;
-    pub const FRAGMENTATION_BUFFER_SIZE: usize = 1500;
+    pub const FRAGMENTATION_BUFFER_SIZE: usize = 4096;
     pub const IFACE_MAX_ADDR_COUNT: usize = 8;
     pub const IFACE_MAX_MULTICAST_GROUP_COUNT: usize = 4;
     pub const IFACE_MAX_ROUTE_COUNT: usize = 4;