From: Mohsin Kazmi Date: Thu, 26 Jun 2025 10:14:18 +0000 (+0000) Subject: gso: fix ip fragment support for gso packet X-Git-Tag: v26.02-rc0~201 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F36%2F43336%2F3;p=vpp.git gso: fix ip fragment support for gso packet Type: fix GSO packets must be fragmented if the egress interface does not support GSO offload and its MTU is smaller than the combined size of the GSO chunk and protocol headers. Signed-off-by: Mohsin Kazmi Change-Id: I94dff39c475a6ba31b1d8f4517e84be3ab506607 --- diff --git a/src/vnet/buffer.h b/src/vnet/buffer.h index ae899158639..c9005b70daf 100644 --- a/src/vnet/buffer.h +++ b/src/vnet/buffer.h @@ -530,10 +530,15 @@ STATIC_ASSERT (sizeof (vnet_buffer_opaque2_t) == STRUCT_SIZE_OF (vlib_buffer_t, opaque2), "VNET buffer opaque2 meta-data too large for vlib_buffer"); -#define gso_mtu_sz(b) (vnet_buffer2(b)->gso_size + \ - vnet_buffer2(b)->gso_l4_hdr_sz + \ - vnet_buffer(b)->l4_hdr_offset - \ - vnet_buffer (b)->l3_hdr_offset) +#define gso_mtu_tunnel_size(b) \ + ((vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_TNL_MASK) ? \ + vnet_buffer (b)->l3_hdr_offset - vnet_buffer2 (b)->outer_l3_hdr_offset : \ + 0) + +#define gso_mtu_sz(b) \ + (vnet_buffer2 (b)->gso_size + vnet_buffer2 (b)->gso_l4_hdr_sz + \ + vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset + \ + gso_mtu_tunnel_size (b)) format_function_t format_vnet_buffer_no_chain; format_function_t format_vnet_buffer; diff --git a/src/vnet/gso/node.c b/src/vnet/gso/node.c index c4f4b74cd92..1fabe44d2ab 100644 --- a/src/vnet/gso/node.c +++ b/src/vnet/gso/node.c @@ -135,10 +135,10 @@ tso_segment_vxlan_tunnel_headers_fixup (vlib_main_t *vm, vlib_buffer_t *b) ip4->length = clib_host_to_net_u16 ( b->current_length - (outer_l3_hdr_offset - b->current_data)); ip4->checksum = ip4_header_checksum (ip4); + udp->length = clib_host_to_net_u16 ( + b->current_length - (outer_l4_hdr_offset - b->current_data)); if (vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_OUTER_UDP_CKSUM) { - udp->length = clib_host_to_net_u16 ( - b->current_length - (outer_l4_hdr_offset - b->current_data)); // udp checksum is 0, in udp tunnel udp->checksum = 0; } @@ -151,11 +151,11 @@ tso_segment_vxlan_tunnel_headers_fixup (vlib_main_t *vm, vlib_buffer_t *b) { ip6->payload_length = clib_host_to_net_u16 ( b->current_length - (outer_l4_hdr_offset - b->current_data)); + udp->length = ip6->payload_length; if (vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_OUTER_UDP_CKSUM) { int bogus; - udp->length = ip6->payload_length; // udp checksum is 0, in udp tunnel udp->checksum = 0; udp->checksum = diff --git a/src/vnet/ip/ip_frag.c b/src/vnet/ip/ip_frag.c index 729aa677d48..aa7a031c909 100644 --- a/src/vnet/ip/ip_frag.c +++ b/src/vnet/ip/ip_frag.c @@ -103,9 +103,10 @@ ip4_frag_do_fragment (vlib_main_t * vm, u32 from_bi, u16 mtu, if (from_b->flags & VNET_BUFFER_F_OFFLOAD) { - ASSERT ((from_b->flags & VNET_BUFFER_F_GSO) == 0); vnet_calc_checksums_inline (vm, from_b, 1 /* is_v4 */, 0 /* is_v6 */); vnet_calc_outer_checksums_inline (vm, from_b); + /* Packet is going to be fragmented, so remove GSO flag */ + from_b->flags &= ~VNET_BUFFER_F_GSO; } org_from_packet = vlib_buffer_get_current (from_b); @@ -385,9 +386,10 @@ ip6_frag_do_fragment (vlib_main_t * vm, u32 from_bi, u16 mtu, if (from_b->flags & VNET_BUFFER_F_OFFLOAD) { - ASSERT ((from_b->flags & VNET_BUFFER_F_GSO) == 0); vnet_calc_checksums_inline (vm, from_b, 0 /* is_v4 */, 1 /* is_v6 */); vnet_calc_outer_checksums_inline (vm, from_b); + /* Packet is going to be fragmented, so remove GSO flag */ + from_b->flags &= ~VNET_BUFFER_F_GSO; } org_from_packet = vlib_buffer_get_current (from_b); diff --git a/test/test_gso.py b/test/test_gso.py index c3822b01faa..63b42c95309 100644 --- a/test/test_gso.py +++ b/test/test_gso.py @@ -14,7 +14,7 @@ from scapy.packet import Raw from scapy.layers.l2 import GRE from scapy.layers.inet6 import IPv6, Ether, IP, ICMPv6PacketTooBig from scapy.layers.inet6 import ipv6nh, IPerror6 -from scapy.layers.inet import TCP, ICMP +from scapy.layers.inet import TCP, ICMP, UDP, defragment from scapy.layers.vxlan import VXLAN from scapy.layers.ipsec import ESP @@ -49,12 +49,16 @@ class TestGSO(VppTestCase): def setUpClass(self): super(TestGSO, self).setUpClass() res = self.create_pg_interfaces(range(2)) - res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460) - self.create_pg_interfaces(range(4, 5), 1, 8940) + res_gso1 = self.create_pg_interfaces(range(2, 3), 1, 1460) + res_gso2 = self.create_pg_interfaces(range(3, 4), 1, 1440) + self.pg_interfaces = self.create_pg_interfaces(range(4, 5), 1, 8940) self.pg_interfaces.append(res[0]) self.pg_interfaces.append(res[1]) - self.pg_interfaces.append(res_gso[0]) - self.pg_interfaces.append(res_gso[1]) + self.pg_interfaces.append(res_gso1[0]) + self.pg_interfaces.append(res_gso2[0]) + self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0]) + self.vapi.sw_interface_set_mtu(self.pg2.sw_if_index, [1500, 0, 0, 0]) + self.vapi.sw_interface_set_mtu(self.pg3.sw_if_index, [1500, 0, 0, 0]) @classmethod def tearDownClass(self): @@ -85,13 +89,34 @@ class TestGSO(VppTestCase): vni=self.single_tunnel_bd, ) - self.ipip4 = VppIpIpTunInterface( + self.single_tunnel_bd2 = 20 + self.vxlan3 = VppVxlanTunnel( + self, + src=self.pg1.local_ip4, + dst=self.pg1.remote_ip4, + vni=self.single_tunnel_bd2, + ) + self.vxlan4 = VppVxlanTunnel( + self, + src=self.pg1.local_ip6, + dst=self.pg1.remote_ip6, + vni=self.single_tunnel_bd2, + ) + + self.ipip4_0 = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip4, self.pg0.remote_ip4 ) - self.ipip6 = VppIpIpTunInterface( + self.ipip6_0 = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip6, self.pg0.remote_ip6 ) + self.ipip4_1 = VppIpIpTunInterface( + self, self.pg1, self.pg1.local_ip4, self.pg1.remote_ip4 + ) + self.ipip6_1 = VppIpIpTunInterface( + self, self.pg1, self.pg1.local_ip6, self.pg1.remote_ip6 + ) + self.gre4 = VppGreInterface(self, self.pg0.local_ip4, self.pg0.remote_ip4) self.gre6 = VppGreInterface(self, self.pg0.local_ip6, self.pg0.remote_ip6) @@ -103,6 +128,13 @@ class TestGSO(VppTestCase): i.unconfig_ip6() i.admin_down() + def get_mtu(self, sw_if_index): + rv = self.vapi.sw_interface_dump(sw_if_index=sw_if_index) + for i in rv: + if i.sw_if_index == sw_if_index: + return i.mtu[0] + return 0 + def test_gso(self): """GSO test""" # @@ -194,19 +226,19 @@ class TestGSO(VppTestCase): # ipv6 # p61 = ( - Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) - / IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) + Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) + / IPv6(src=self.pg3.remote_ip6, dst=self.pg2.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b"\xa5" * 65200) ) - rxs = self.send_and_expect(self.pg2, 100 * [p61], self.pg3, 100) + rxs = self.send_and_expect(self.pg3, 100 * [p61], self.pg2, 100) for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg3.local_mac) - self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6) + self.assertEqual(rx[Ether].src, self.pg2.local_mac) + self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) + self.assertEqual(rx[IPv6].src, self.pg3.remote_ip6) + self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) @@ -290,6 +322,7 @@ class TestGSO(VppTestCase): self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assertTrue((rx[IP].flags == "MF") or (rx[IP].frag != 0)) self.assert_ip_checksum_valid(rx) size += rx[IP].len - 20 size -= 20 * 5 # TCP header @@ -322,12 +355,11 @@ class TestGSO(VppTestCase): self.assertEqual(rx[IPerror6].plen - 20, 65200) # - # Send jumbo frame with gso enabled only on input interface with 9K MTU - # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO + # Send jumbo frame with gso enabled only on input interface with 9K MTU. + # GSO packet will be chunked. MSS is 8960. GSO # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) - self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0]) p44 = ( Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) @@ -372,6 +404,39 @@ class TestGSO(VppTestCase): size += payload_len self.assertEqual(size, 65200 * 5) + # + # Send jumbo frame with gso enabled only on input interface with 9K MTU. + # DF bit is unset. GSO packet will be fragmented. + # + self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [8000, 0, 0, 0]) + + rxs = self.send_and_expect(self.pg4, 5 * [p44], self.pg1, 165) + size = 0 + for rx in rxs: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IP].src, self.pg4.remote_ip4) + self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assert_ip_checksum_valid(rx) + self.assertTrue((rx[IP].flags == "MF") or (rx[IP].frag != 0)) + size += rx[IP].len - 20 # len - 20 (IP4) + size -= 20 * 5 # TCP header + self.assertEqual(size, 65200 * 5) + + rxs = self.send_and_expect_some(self.pg4, 5 * [p64], self.pg4, 5) + for rx in rxs: + self.assertEqual(rx[Ether].src, self.pg4.local_mac) + self.assertEqual(rx[Ether].dst, self.pg4.remote_mac) + self.assertEqual(rx[IPv6].src, self.pg4.local_ip6) + self.assertEqual(rx[IPv6].dst, self.pg4.remote_ip6) + self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header + self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6") + self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 8000) + self.assertEqual(rx[IPerror6].src, self.pg4.remote_ip6) + self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6) + self.assertEqual(rx[IPerror6].plen - 20, 65200) + + self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0]) self.vapi.feature_gso_enable_disable( sw_if_index=self.pg0.sw_if_index, enable_disable=0 ) @@ -384,7 +449,6 @@ class TestGSO(VppTestCase): ) def test_gso_vxlan(self): """GSO VXLAN test""" - self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2 @@ -555,9 +619,81 @@ class TestGSO(VppTestCase): sw_if_index=self.pg0.sw_if_index, enable_disable=0 ) + # + # IPv4/IPv4 - VXLAN - Fragmented test + # Send jumbo frame with gso enabled only on input interface and + # create VXLAN VTEP on VPP pg1, and put vxlan_tunnel and pg2 + # into BD. + # Packets will be fragmented as + # gso_size (1460) + headers size (50 vxlan encap + 20 inner IPv4 + 20 TCP) + # is larger than MTU of the output interface (1500). + # + + self.vxlan3.add_vpp_config() + self.vapi.sw_interface_set_l2_bridge( + rx_sw_if_index=self.vxlan3.sw_if_index, bd_id=self.single_tunnel_bd2 + ) + self.vapi.sw_interface_set_l2_bridge( + rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd2 + ) + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=1 + ) + + p67 = ( + Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) + / IP(src=self.pg2.remote_ip4, dst="172.16.3.3") + / TCP(sport=1234, dport=1234) + / Raw(b"\xa5" * 65200) + ) + + rxs = self.send_and_expect(self.pg2, 5 * [p67], self.pg1, 225) + size = 0 + for rx in rxs: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IP].src, self.pg1.local_ip4) + self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assert_ip_checksum_valid(rx) + self.assertTrue((rx[IP].flags == "MF") or (rx[IP].frag != 0)) + size += rx[IP].len - 20 # outer IP len + size -= ( + 8 + 8 + 14 + 20 + 20 + ) * 5 # UDP header + VXLAN header + Ethernet header + inner IP header + TCP header + self.assertEqual(size, 65200 * 5) + + assembled_pkt = defragment(rxs) + for rx in assembled_pkt: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IP].src, self.pg1.local_ip4) + self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assertEqual( + rx[IP].len, 65290 + ) # 65200 + 50 (VXLAN encap) + 20 (IP) + 20 (TCP) + self.assertEqual( + rx[UDP].len, 65270 + ) # 65200 + 50 (VXLAN encap) - 20 (outer IP) + 20 (IP) + 20 (TCP) + self.assert_ip_checksum_valid(rx) + self.assert_udp_checksum_valid(rx, ignore_zero_checksum=True) + self.assertEqual(rx[VXLAN].vni, 20) + inner = rx[VXLAN].payload + self.assertEqual(inner[Ether].src, self.pg2.remote_mac) + self.assertEqual(inner[Ether].dst, self.pg2.local_mac) + self.assertEqual(inner[IP].src, self.pg2.remote_ip4) + self.assertEqual(inner[IP].dst, "172.16.3.3") + self.assert_ip_checksum_valid(inner) + self.assert_tcp_checksum_valid(inner) + self.assertEqual(inner[IP].len - 20 - 20, 65200) + + self.vxlan3.remove_vpp_config() + + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=0 + ) + def test_gso_ipip(self): """GSO IPIP test""" - self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. @@ -569,11 +705,11 @@ class TestGSO(VppTestCase): # # enable ipip4 # - self.ipip4.add_vpp_config() + self.ipip4_0.add_vpp_config() # Set interface up and enable IP on it - self.ipip4.admin_up() - self.ipip4.set_unnumbered(self.pg0.sw_if_index) + self.ipip4_0.admin_up() + self.ipip4_0.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip4_tunnel = VppIpRoute( @@ -583,7 +719,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "0.0.0.0", - self.ipip4.sw_if_index, + self.ipip4_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], @@ -627,7 +763,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "::", - self.ipip4.sw_if_index, + self.ipip4_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], @@ -671,7 +807,7 @@ class TestGSO(VppTestCase): sw_if_index=self.pg0.sw_if_index, enable_disable=0 ) self.vapi.feature_gso_enable_disable( - sw_if_index=self.ipip4.sw_if_index, enable_disable=1 + sw_if_index=self.ipip4_0.sw_if_index, enable_disable=1 ) rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225) @@ -698,11 +834,11 @@ class TestGSO(VppTestCase): # disable ipip4 # self.vapi.feature_gso_enable_disable( - sw_if_index=self.ipip4.sw_if_index, enable_disable=0 + sw_if_index=self.ipip4_0.sw_if_index, enable_disable=0 ) self.ip4_via_ip4_tunnel.remove_vpp_config() self.ip6_via_ip4_tunnel.remove_vpp_config() - self.ipip4.remove_vpp_config() + self.ipip4_0.remove_vpp_config() # # enable ipip6 @@ -710,11 +846,11 @@ class TestGSO(VppTestCase): self.vapi.feature_gso_enable_disable( sw_if_index=self.pg0.sw_if_index, enable_disable=1 ) - self.ipip6.add_vpp_config() + self.ipip6_0.add_vpp_config() # Set interface up and enable IP on it - self.ipip6.admin_up() - self.ipip6.set_unnumbered(self.pg0.sw_if_index) + self.ipip6_0.admin_up() + self.ipip6_0.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip6_tunnel = VppIpRoute( @@ -724,7 +860,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "0.0.0.0", - self.ipip6.sw_if_index, + self.ipip6_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], @@ -767,7 +903,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "::", - self.ipip6.sw_if_index, + self.ipip6_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], @@ -807,12 +943,135 @@ class TestGSO(VppTestCase): # self.ip4_via_ip6_tunnel.remove_vpp_config() self.ip6_via_ip6_tunnel.remove_vpp_config() - self.ipip6.remove_vpp_config() + self.ipip6_0.remove_vpp_config() self.vapi.feature_gso_enable_disable( sw_if_index=self.pg0.sw_if_index, enable_disable=0 ) + # + # IPIP - Fragmented test + # enable ipip4 + # + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=1 + ) + self.ipip4_1.add_vpp_config() + + # Set interface up and enable IP on it + self.ipip4_1.admin_up() + self.ipip4_1.set_unnumbered(self.pg1.sw_if_index) + + # Add IPv4 routes via tunnel interface + self.ip4_via_ip4_tunnel_1 = VppIpRoute( + self, + "172.16.10.0", + 24, + [ + VppRoutePath( + "0.0.0.0", + self.ipip4_1.sw_if_index, + proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, + ) + ], + ) + self.ip4_via_ip4_tunnel_1.add_vpp_config() + + p47_1 = ( + Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) + / IP(src=self.pg2.remote_ip4, dst="172.16.10.3") + / TCP(sport=1234, dport=1234) + / Raw(b"\xa5" * 65200) + ) + + rxs = self.send_and_expect(self.pg2, 5 * [p47_1], self.pg1, 225) + size = 0 + for rx in rxs: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IP].src, self.pg1.local_ip4) + self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assert_ip_checksum_valid(rx) + self.assertTrue((rx[IP].flags == "MF") or (rx[IP].frag != 0)) + size += rx[IP].len - 20 # outer IP len + size -= (20 + 20) * 5 # inner IP header + TCP header + self.assertEqual(size, 65200 * 5) + + assembled_pkt = defragment(rxs) + for rx in assembled_pkt: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IP].src, self.pg1.local_ip4) + self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) + self.assertEqual( + rx[IP].len, 65260 + ) # 65200 + 20 (outer IP) + 20 (inner IP) + 20 (TCP) + self.assert_ip_checksum_valid(rx) + inner = rx[IP].payload + self.assertEqual(inner[IP].src, self.pg2.remote_ip4) + self.assertEqual(inner[IP].dst, "172.16.10.3") + self.assert_ip_checksum_valid(inner) + self.assert_tcp_checksum_valid(inner) + self.assertEqual(inner[IP].len - 20 - 20, 65200) + + self.ip4_via_ip4_tunnel_1.remove_vpp_config() + self.ipip4_1.remove_vpp_config() + + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=0 + ) + + # + # enable ipip6 + # + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=1 + ) + self.ipip6_1.add_vpp_config() + # Set interface up and enable IP on it + self.ipip6_1.admin_up() + self.ipip6_1.set_unnumbered(self.pg1.sw_if_index) + # Add IPv6 routes via tunnel interface + self.ip6_via_ip6_tunnel_1 = VppIpRoute( + self, + "fd01:10::", + 64, + [ + VppRoutePath( + "::", + self.ipip6_1.sw_if_index, + proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, + ) + ], + ) + self.ip6_via_ip6_tunnel_1.add_vpp_config() + + p68_1 = ( + Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) + / IPv6(src=self.pg3.remote_ip6, dst="fd01:10::3") + / TCP(sport=1234, dport=1234) + / Raw(b"\xa5" * 65200) + ) + + rxs = self.send_and_expect(self.pg3, 5 * [p68_1], self.pg1, 230) + size = 0 + for rx in rxs: + self.assertEqual(rx[Ether].src, self.pg1.local_mac) + self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) + self.assertEqual(rx[IPv6].src, self.pg1.local_ip6) + self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) + self.assertEqual(ipv6nh[rx[IPv6].nh], "Fragment Header") + size += rx[IPv6].plen - 8 # remove fragment header size + size -= (40 + 20) * 5 # inner IPv6 header + TCP header + self.assertEqual(size, 65200 * 5) + + self.ip6_via_ip6_tunnel_1.remove_vpp_config() + self.ipip6_1.remove_vpp_config() + + self.vapi.feature_gso_enable_disable( + sw_if_index=self.pg1.sw_if_index, enable_disable=0 + ) + def test_gso_gre(self): """GSO GRE test""" # @@ -1019,9 +1278,9 @@ class TestGSO(VppTestCase): # # enable ipip4 # - self.ipip4.add_vpp_config() + self.ipip4_0.add_vpp_config() self.vapi.feature_gso_enable_disable( - sw_if_index=self.ipip4.sw_if_index, enable_disable=1 + sw_if_index=self.ipip4_0.sw_if_index, enable_disable=1 ) # Add IPv4 routes via tunnel interface @@ -1032,7 +1291,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "0.0.0.0", - self.ipip4.sw_if_index, + self.ipip4_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], @@ -1042,7 +1301,7 @@ class TestGSO(VppTestCase): # IPSec config self.ipv4_params = IPsecIPv4Params() self.encryption_type = ESP - config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4) + config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4_0) self.tun_sa_in_v4 = VppIpsecSA( self, @@ -1069,14 +1328,14 @@ class TestGSO(VppTestCase): self.tun_sa_out_v4.add_vpp_config() self.tun_protect_v4 = VppIpsecTunProtect( - self, self.ipip4, self.tun_sa_out_v4, [self.tun_sa_in_v4] + self, self.ipip4_0, self.tun_sa_out_v4, [self.tun_sa_in_v4] ) self.tun_protect_v4.add_vpp_config() # Set interface up and enable IP on it - self.ipip4.admin_up() - self.ipip4.set_unnumbered(self.pg0.sw_if_index) + self.ipip4_0.admin_up() + self.ipip4_0.set_unnumbered(self.pg0.sw_if_index) # # IPv4/IPv4 - IPSEC @@ -1110,7 +1369,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "::", - self.ipip4.sw_if_index, + self.ipip4_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], @@ -1149,20 +1408,20 @@ class TestGSO(VppTestCase): # # disable ipip4 # - self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, enable_disable=0) + self.vapi.feature_gso_enable_disable(self.ipip4_0.sw_if_index, enable_disable=0) self.ip4_via_ip4_tunnel.remove_vpp_config() self.ip6_via_ip4_tunnel.remove_vpp_config() - self.ipip4.remove_vpp_config() + self.ipip4_0.remove_vpp_config() # # enable ipip6 # - self.ipip6.add_vpp_config() - self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index, enable_disable=1) + self.ipip6_0.add_vpp_config() + self.vapi.feature_gso_enable_disable(self.ipip6_0.sw_if_index, enable_disable=1) # Set interface up and enable IP on it - self.ipip6.admin_up() - self.ipip6.set_unnumbered(self.pg0.sw_if_index) + self.ipip6_0.admin_up() + self.ipip6_0.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip6_tunnel = VppIpRoute( @@ -1172,7 +1431,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "0.0.0.0", - self.ipip6.sw_if_index, + self.ipip6_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], @@ -1182,7 +1441,7 @@ class TestGSO(VppTestCase): # IPSec config self.ipv6_params = IPsecIPv6Params() self.encryption_type = ESP - config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6) + config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6_0) self.tun_sa_in_v6 = VppIpsecSA( self, self.ipv6_params.scapy_tun_sa_id, @@ -1208,7 +1467,7 @@ class TestGSO(VppTestCase): self.tun_sa_out_v6.add_vpp_config() self.tun_protect_v6 = VppIpsecTunProtect( - self, self.ipip6, self.tun_sa_out_v6, [self.tun_sa_in_v6] + self, self.ipip6_0, self.tun_sa_out_v6, [self.tun_sa_in_v6] ) self.tun_protect_v6.add_vpp_config() @@ -1245,7 +1504,7 @@ class TestGSO(VppTestCase): [ VppRoutePath( "::", - self.ipip6.sw_if_index, + self.ipip6_0.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], @@ -1287,7 +1546,7 @@ class TestGSO(VppTestCase): # self.ip4_via_ip6_tunnel.remove_vpp_config() self.ip6_via_ip6_tunnel.remove_vpp_config() - self.ipip6.remove_vpp_config() + self.ipip6_0.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)