2 """GSO functional tests"""
7 # - Verify that sending Jumbo frame without GSO enabled correctly
8 # - Verify that sending Jumbo frame with GSO enabled correctly
9 # - Verify that sending Jumbo frame with GSO enabled only on ingress interface
13 from scapy.packet import Raw
14 from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig
15 from scapy.layers.inet6 import ipv6nh, IPerror6
16 from scapy.layers.inet import TCP, ICMP
17 from scapy.layers.vxlan import VXLAN
18 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
19 from scapy.layers.ipsec import SecurityAssociation, ESP
21 from vpp_papi import VppEnum
22 from framework import VppTestCase, VppTestRunner
23 from vpp_object import VppObject
24 from vpp_interface import VppInterface
25 from vpp_ip import DpoProto
26 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
27 from vpp_ipip_tun_interface import VppIpIpTunInterface
28 from vpp_vxlan_tunnel import VppVxlanTunnel
29 from socket import AF_INET, AF_INET6, inet_pton
30 from util import reassemble4
32 from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect
33 from template_ipsec import (
40 """ Test_gso is a subclass of VPPTestCase classes.
45 class TestGSO(VppTestCase):
48 def __init__(self, *args):
49 VppTestCase.__init__(self, *args)
53 super(TestGSO, self).setUpClass()
54 res = self.create_pg_interfaces(range(2))
55 res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460)
56 self.create_pg_interfaces(range(4, 5), 1, 8940)
57 self.pg_interfaces.append(res[0])
58 self.pg_interfaces.append(res[1])
59 self.pg_interfaces.append(res_gso[0])
60 self.pg_interfaces.append(res_gso[1])
63 def tearDownClass(self):
64 super(TestGSO, self).tearDownClass()
67 super(TestGSO, self).setUp()
68 for i in self.pg_interfaces:
76 self.single_tunnel_bd = 10
77 self.vxlan = VppVxlanTunnel(
79 src=self.pg0.local_ip4,
80 dst=self.pg0.remote_ip4,
81 vni=self.single_tunnel_bd,
84 self.vxlan2 = VppVxlanTunnel(
86 src=self.pg0.local_ip6,
87 dst=self.pg0.remote_ip6,
88 vni=self.single_tunnel_bd,
91 self.ipip4 = VppIpIpTunInterface(
92 self, self.pg0, self.pg0.local_ip4, self.pg0.remote_ip4
94 self.ipip6 = VppIpIpTunInterface(
95 self, self.pg0, self.pg0.local_ip6, self.pg0.remote_ip6
99 super(TestGSO, self).tearDown()
100 if not self.vpp_dead:
101 for i in self.pg_interfaces:
109 # Send jumbo frame with gso disabled and DF bit is set
112 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
113 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags="DF")
114 / TCP(sport=1234, dport=1234)
115 / Raw(b"\xa5" * 65200)
118 rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
121 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
122 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
123 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
124 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
125 self.assertEqual(rx[ICMP].type, 3) # "dest-unreach"
126 self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed"
129 # Send checksum offload frames
132 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
133 / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags="DF")
134 / TCP(sport=1234, dport=1234)
135 / Raw(b"\xa5" * 1460)
138 rxs = self.send_and_expect(self.pg2, 100 * [p40], self.pg0)
141 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
142 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
143 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
144 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
145 payload_len = rx[IP].len - 20 - 20
146 self.assert_ip_checksum_valid(rx)
147 self.assert_tcp_checksum_valid(rx)
148 self.assertEqual(payload_len, len(rx[Raw]))
151 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
152 / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6)
153 / TCP(sport=1234, dport=1234)
154 / Raw(b"\xa5" * 1440)
157 rxs = self.send_and_expect(self.pg2, 100 * [p60], self.pg0)
160 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
161 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
162 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
163 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
164 payload_len = rx[IPv6].plen - 20
165 self.assert_tcp_checksum_valid(rx)
166 self.assertEqual(payload_len, len(rx[Raw]))
169 # Send jumbo frame with gso enabled and DF bit is set
170 # input and output interfaces support GSO
172 self.vapi.feature_gso_enable_disable(
173 sw_if_index=self.pg3.sw_if_index, enable_disable=1
176 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
177 / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, flags="DF")
178 / TCP(sport=1234, dport=1234)
179 / Raw(b"\xa5" * 65200)
182 rxs = self.send_and_expect(self.pg2, 100 * [p41], self.pg3, 100)
185 self.assertEqual(rx[Ether].src, self.pg3.local_mac)
186 self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
187 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
188 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
189 self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP)
190 self.assertEqual(rx[TCP].sport, 1234)
191 self.assertEqual(rx[TCP].dport, 1234)
197 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
198 / IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6)
199 / TCP(sport=1234, dport=1234)
200 / Raw(b"\xa5" * 65200)
203 rxs = self.send_and_expect(self.pg2, 100 * [p61], self.pg3, 100)
206 self.assertEqual(rx[Ether].src, self.pg3.local_mac)
207 self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
208 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
209 self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
210 self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP)
211 self.assertEqual(rx[TCP].sport, 1234)
212 self.assertEqual(rx[TCP].dport, 1234)
215 # Send jumbo frame with gso enabled only on input interface
216 # and DF bit is set. GSO packet will be chunked into gso_size
219 self.vapi.feature_gso_enable_disable(
220 sw_if_index=self.pg0.sw_if_index, enable_disable=1
223 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
224 / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags="DF")
225 / TCP(sport=1234, dport=1234)
226 / Raw(b"\xa5" * 65200)
229 rxs = self.send_and_expect(self.pg2, 5 * [p42], self.pg0, 225)
232 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
233 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
234 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
235 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
236 payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
237 self.assert_ip_checksum_valid(rx)
238 self.assert_tcp_checksum_valid(rx)
239 self.assertEqual(rx[TCP].sport, 1234)
240 self.assertEqual(rx[TCP].dport, 1234)
241 self.assertEqual(payload_len, len(rx[Raw]))
243 self.assertEqual(size, 65200 * 5)
249 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
250 / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6)
251 / TCP(sport=1234, dport=1234)
252 / Raw(b"\xa5" * 65200)
255 rxs = self.send_and_expect(self.pg2, 5 * [p62], self.pg0, 225)
258 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
259 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
260 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
261 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
262 payload_len = rx[IPv6].plen - 20
263 self.assert_tcp_checksum_valid(rx)
264 self.assertEqual(rx[TCP].sport, 1234)
265 self.assertEqual(rx[TCP].dport, 1234)
266 self.assertEqual(payload_len, len(rx[Raw]))
268 self.assertEqual(size, 65200 * 5)
271 # Send jumbo frame with gso enabled only on input interface
272 # and DF bit is unset. GSO packet will be fragmented.
274 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
275 self.vapi.feature_gso_enable_disable(
276 sw_if_index=self.pg1.sw_if_index, enable_disable=1
280 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
281 / IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4)
282 / TCP(sport=1234, dport=1234)
283 / Raw(b"\xa5" * 65200)
286 rxs = self.send_and_expect(self.pg2, 5 * [p43], self.pg1, 5 * 119)
289 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
290 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
291 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
292 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
293 self.assert_ip_checksum_valid(rx)
294 size += rx[IP].len - 20
295 size -= 20 * 5 # TCP header
296 self.assertEqual(size, 65200 * 5)
300 # Send jumbo frame with gso enabled only on input interface.
301 # ICMPv6 Packet Too Big will be sent back to sender.
303 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
305 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
306 / IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6)
307 / TCP(sport=1234, dport=1234)
308 / Raw(b"\xa5" * 65200)
311 rxs = self.send_and_expect_some(self.pg2, 5 * [p63], self.pg2, 5)
313 self.assertEqual(rx[Ether].src, self.pg2.local_mac)
314 self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
315 self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
316 self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
317 self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header
318 self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
319 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
320 self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
321 self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
322 self.assertEqual(rx[IPerror6].plen - 20, 65200)
325 # Send jumbo frame with gso enabled only on input interface with 9K MTU
326 # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
327 # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
329 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
330 self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
332 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
333 / IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4)
334 / TCP(sport=1234, dport=1234)
335 / Raw(b"\xa5" * 65200)
338 rxs = self.send_and_expect(self.pg4, 5 * [p44], self.pg1, 165)
341 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
342 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
343 self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
344 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
345 payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
346 self.assert_ip_checksum_valid(rx)
347 self.assert_tcp_checksum_valid(rx)
348 self.assertEqual(payload_len, len(rx[Raw]))
350 self.assertEqual(size, 65200 * 5)
356 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
357 / IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6)
358 / TCP(sport=1234, dport=1234)
359 / Raw(b"\xa5" * 65200)
362 rxs = self.send_and_expect(self.pg4, 5 * [p64], self.pg1, 170)
365 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
366 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
367 self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
368 self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
369 payload_len = rx[IPv6].plen - 20
370 self.assert_tcp_checksum_valid(rx)
371 self.assertEqual(payload_len, len(rx[Raw]))
373 self.assertEqual(size, 65200 * 5)
375 self.vapi.feature_gso_enable_disable(
376 sw_if_index=self.pg0.sw_if_index, enable_disable=0
378 self.vapi.feature_gso_enable_disable(
379 sw_if_index=self.pg1.sw_if_index, enable_disable=0
382 def test_gso_vxlan(self):
384 self.logger.info(self.vapi.cli("sh int addr"))
386 # Send jumbo frame with gso enabled only on input interface and
387 # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
394 self.vxlan.add_vpp_config()
395 self.vapi.sw_interface_set_l2_bridge(
396 rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd
398 self.vapi.sw_interface_set_l2_bridge(
399 rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd
401 self.vapi.feature_gso_enable_disable(
402 sw_if_index=self.pg0.sw_if_index, enable_disable=1
409 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
410 / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags="DF")
411 / TCP(sport=1234, dport=1234)
412 / Raw(b"\xa5" * 65200)
415 rxs = self.send_and_expect(self.pg2, 5 * [p45], self.pg0, 225)
418 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
419 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
420 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
421 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
422 self.assert_ip_checksum_valid(rx)
423 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
424 self.assertEqual(rx[VXLAN].vni, 10)
425 inner = rx[VXLAN].payload
426 self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
427 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
428 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
429 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
430 self.assertEqual(inner[IP].dst, "172.16.3.3")
431 self.assert_ip_checksum_valid(inner)
432 self.assert_tcp_checksum_valid(inner)
433 payload_len = inner[IP].len - 20 - 20
434 self.assertEqual(payload_len, len(inner[Raw]))
436 self.assertEqual(size, 65200 * 5)
442 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
443 / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3")
444 / TCP(sport=1234, dport=1234)
445 / Raw(b"\xa5" * 65200)
448 rxs = self.send_and_expect(self.pg2, 5 * [p65], self.pg0, 225)
451 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
452 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
453 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
454 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
455 self.assert_ip_checksum_valid(rx)
456 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
457 self.assertEqual(rx[VXLAN].vni, 10)
458 inner = rx[VXLAN].payload
459 self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
460 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
461 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
462 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
463 self.assertEqual(inner[IPv6].dst, "fd01:3::3")
464 self.assert_tcp_checksum_valid(inner)
465 payload_len = inner[IPv6].plen - 20
466 self.assertEqual(payload_len, len(inner[Raw]))
468 self.assertEqual(size, 65200 * 5)
473 self.vxlan.remove_vpp_config()
478 self.vxlan2.add_vpp_config()
479 self.vapi.sw_interface_set_l2_bridge(
480 rx_sw_if_index=self.vxlan2.sw_if_index, bd_id=self.single_tunnel_bd
487 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
488 / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags="DF")
489 / TCP(sport=1234, dport=1234)
490 / Raw(b"\xa5" * 65200)
493 rxs = self.send_and_expect(self.pg2, 5 * [p46], self.pg0, 225)
496 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
497 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
498 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
499 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
500 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
501 self.assertEqual(rx[VXLAN].vni, 10)
502 inner = rx[VXLAN].payload
503 self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
504 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
505 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
506 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
507 self.assertEqual(inner[IP].dst, "172.16.3.3")
508 self.assert_ip_checksum_valid(inner)
509 self.assert_tcp_checksum_valid(inner)
510 payload_len = inner[IP].len - 20 - 20
511 self.assertEqual(payload_len, len(inner[Raw]))
513 self.assertEqual(size, 65200 * 5)
519 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
520 / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3")
521 / TCP(sport=1234, dport=1234)
522 / Raw(b"\xa5" * 65200)
525 rxs = self.send_and_expect(self.pg2, 5 * [p66], self.pg0, 225)
528 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
529 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
530 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
531 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
532 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
533 self.assertEqual(rx[VXLAN].vni, 10)
534 inner = rx[VXLAN].payload
535 self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
536 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
537 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
538 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
539 self.assertEqual(inner[IPv6].dst, "fd01:3::3")
540 self.assert_tcp_checksum_valid(inner)
541 payload_len = inner[IPv6].plen - 20
542 self.assertEqual(payload_len, len(inner[Raw]))
544 self.assertEqual(size, 65200 * 5)
549 self.vxlan2.remove_vpp_config()
551 self.vapi.feature_gso_enable_disable(
552 sw_if_index=self.pg0.sw_if_index, enable_disable=0
555 def test_gso_ipip(self):
557 self.logger.info(self.vapi.cli("sh int addr"))
559 # Send jumbo frame with gso enabled only on input interface and
560 # create IPIP tunnel on VPP pg0.
562 self.vapi.feature_gso_enable_disable(
563 sw_if_index=self.pg0.sw_if_index, enable_disable=1
569 self.ipip4.add_vpp_config()
571 # Set interface up and enable IP on it
572 self.ipip4.admin_up()
573 self.ipip4.set_unnumbered(self.pg0.sw_if_index)
575 # Add IPv4 routes via tunnel interface
576 self.ip4_via_ip4_tunnel = VppIpRoute(
583 self.ipip4.sw_if_index,
584 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
588 self.ip4_via_ip4_tunnel.add_vpp_config()
594 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
595 / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
596 / TCP(sport=1234, dport=1234)
597 / Raw(b"\xa5" * 65200)
600 rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225)
603 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
604 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
605 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
606 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
607 self.assert_ip_checksum_valid(rx)
608 self.assertEqual(rx[IP].proto, 4) # ipencap
609 inner = rx[IP].payload
610 self.assertEqual(rx[IP].len - 20, len(inner))
611 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
612 self.assertEqual(inner[IP].dst, "172.16.10.3")
613 self.assert_ip_checksum_valid(inner)
614 self.assert_tcp_checksum_valid(inner)
615 payload_len = inner[IP].len - 20 - 20
616 self.assertEqual(payload_len, len(inner[Raw]))
618 self.assertEqual(size, 65200 * 5)
620 self.ip6_via_ip4_tunnel = VppIpRoute(
627 self.ipip4.sw_if_index,
628 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
632 self.ip6_via_ip4_tunnel.add_vpp_config()
637 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
638 / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
639 / TCP(sport=1234, dport=1234)
640 / Raw(b"\xa5" * 65200)
643 rxs = self.send_and_expect(self.pg2, 5 * [p67], self.pg0, 225)
646 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
647 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
648 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
649 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
650 self.assert_ip_checksum_valid(rx)
651 self.assertEqual(rx[IP].proto, 41) # ipv6
652 inner = rx[IP].payload
653 self.assertEqual(rx[IP].len - 20, len(inner))
654 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
655 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
656 self.assert_tcp_checksum_valid(inner)
657 payload_len = inner[IPv6].plen - 20
658 self.assertEqual(payload_len, len(inner[Raw]))
660 self.assertEqual(size, 65200 * 5)
663 # Send jumbo frame with gso enabled only on input interface and
664 # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
665 # tunnel - IPSec use case
667 self.vapi.feature_gso_enable_disable(
668 sw_if_index=self.pg0.sw_if_index, enable_disable=0
670 self.vapi.feature_gso_enable_disable(
671 sw_if_index=self.ipip4.sw_if_index, enable_disable=1
674 rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225)
677 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
678 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
679 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
680 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
681 self.assert_ip_checksum_valid(rx)
682 self.assertEqual(rx[IP].proto, 4) # ipencap
683 inner = rx[IP].payload
684 self.assertEqual(rx[IP].len - 20, len(inner))
685 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
686 self.assertEqual(inner[IP].dst, "172.16.10.3")
687 self.assert_ip_checksum_valid(inner)
688 self.assert_tcp_checksum_valid(inner)
689 payload_len = inner[IP].len - 20 - 20
690 self.assertEqual(payload_len, len(inner[Raw]))
692 self.assertEqual(size, 65200 * 5)
697 self.vapi.feature_gso_enable_disable(
698 sw_if_index=self.ipip4.sw_if_index, enable_disable=0
700 self.ip4_via_ip4_tunnel.remove_vpp_config()
701 self.ip6_via_ip4_tunnel.remove_vpp_config()
702 self.ipip4.remove_vpp_config()
707 self.vapi.feature_gso_enable_disable(
708 sw_if_index=self.pg0.sw_if_index, enable_disable=1
710 self.ipip6.add_vpp_config()
712 # Set interface up and enable IP on it
713 self.ipip6.admin_up()
714 self.ipip6.set_unnumbered(self.pg0.sw_if_index)
716 # Add IPv4 routes via tunnel interface
717 self.ip4_via_ip6_tunnel = VppIpRoute(
724 self.ipip6.sw_if_index,
725 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
729 self.ip4_via_ip6_tunnel.add_vpp_config()
735 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
736 / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
737 / TCP(sport=1234, dport=1234)
738 / Raw(b"\xa5" * 65200)
741 rxs = self.send_and_expect(self.pg2, 5 * [p48], self.pg0, 225)
744 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
745 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
746 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
747 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
748 self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
749 inner = rx[IPv6].payload
750 self.assertEqual(rx[IPv6].plen, len(inner))
751 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
752 self.assertEqual(inner[IP].dst, "172.16.10.3")
753 self.assert_ip_checksum_valid(inner)
754 self.assert_tcp_checksum_valid(inner)
755 payload_len = inner[IP].len - 20 - 20
756 self.assertEqual(payload_len, len(inner[Raw]))
758 self.assertEqual(size, 65200 * 5)
760 self.ip6_via_ip6_tunnel = VppIpRoute(
767 self.ipip6.sw_if_index,
768 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
772 self.ip6_via_ip6_tunnel.add_vpp_config()
778 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
779 / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
780 / TCP(sport=1234, dport=1234)
781 / Raw(b"\xa5" * 65200)
784 rxs = self.send_and_expect(self.pg2, 5 * [p68], self.pg0, 225)
787 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
788 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
789 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
790 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
791 self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
792 inner = rx[IPv6].payload
793 self.assertEqual(rx[IPv6].plen, len(inner))
794 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
795 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
796 self.assert_tcp_checksum_valid(inner)
797 payload_len = inner[IPv6].plen - 20
798 self.assertEqual(payload_len, len(inner[Raw]))
800 self.assertEqual(size, 65200 * 5)
805 self.ip4_via_ip6_tunnel.remove_vpp_config()
806 self.ip6_via_ip6_tunnel.remove_vpp_config()
807 self.ipip6.remove_vpp_config()
809 self.vapi.feature_gso_enable_disable(
810 sw_if_index=self.pg0.sw_if_index, enable_disable=0
813 def test_gso_ipsec(self):
816 # Send jumbo frame with gso enabled only on input interface and
817 # create IPIP tunnel on VPP pg0.
823 self.ipip4.add_vpp_config()
824 self.vapi.feature_gso_enable_disable(
825 sw_if_index=self.ipip4.sw_if_index, enable_disable=1
828 # Add IPv4 routes via tunnel interface
829 self.ip4_via_ip4_tunnel = VppIpRoute(
836 self.ipip4.sw_if_index,
837 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
841 self.ip4_via_ip4_tunnel.add_vpp_config()
844 self.ipv4_params = IPsecIPv4Params()
845 self.encryption_type = ESP
846 config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4)
848 self.tun_sa_in_v4 = VppIpsecSA(
850 self.ipv4_params.scapy_tun_sa_id,
851 self.ipv4_params.scapy_tun_spi,
852 self.ipv4_params.auth_algo_vpp_id,
853 self.ipv4_params.auth_key,
854 self.ipv4_params.crypt_algo_vpp_id,
855 self.ipv4_params.crypt_key,
856 VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP,
858 self.tun_sa_in_v4.add_vpp_config()
860 self.tun_sa_out_v4 = VppIpsecSA(
862 self.ipv4_params.vpp_tun_sa_id,
863 self.ipv4_params.vpp_tun_spi,
864 self.ipv4_params.auth_algo_vpp_id,
865 self.ipv4_params.auth_key,
866 self.ipv4_params.crypt_algo_vpp_id,
867 self.ipv4_params.crypt_key,
868 VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP,
870 self.tun_sa_out_v4.add_vpp_config()
872 self.tun_protect_v4 = VppIpsecTunProtect(
873 self, self.ipip4, self.tun_sa_out_v4, [self.tun_sa_in_v4]
876 self.tun_protect_v4.add_vpp_config()
878 # Set interface up and enable IP on it
879 self.ipip4.admin_up()
880 self.ipip4.set_unnumbered(self.pg0.sw_if_index)
886 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
887 / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
888 / TCP(sport=1234, dport=1234)
889 / Raw(b"\xa5" * 65200)
892 rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45)
895 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
896 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
897 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
898 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
899 self.assertEqual(rx[IP].proto, 50) # ESP
900 self.assertEqual(rx[ESP].spi, self.ipv4_params.vpp_tun_spi)
901 inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
902 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
903 self.assertEqual(inner[IP].dst, "172.16.10.3")
904 size += inner[IP].len - 20 - 20
905 self.assertEqual(size, 65200)
907 self.ip6_via_ip4_tunnel = VppIpRoute(
914 self.ipip4.sw_if_index,
915 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
919 self.ip6_via_ip4_tunnel.add_vpp_config()
924 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
925 / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
926 / TCP(sport=1234, dport=1234)
927 / Raw(b"\xa5" * 65200)
930 rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45)
933 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
934 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
935 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
936 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
937 self.assertEqual(rx[IP].proto, 50) # ESP
938 self.assertEqual(rx[ESP].spi, self.ipv4_params.vpp_tun_spi)
939 inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
940 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
941 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
942 size += inner[IPv6].plen - 20
943 self.assertEqual(size, 65200)
946 self.tun_protect_v4.remove_vpp_config()
947 self.tun_sa_in_v4.remove_vpp_config()
948 self.tun_sa_out_v4.remove_vpp_config()
953 self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, enable_disable=0)
954 self.ip4_via_ip4_tunnel.remove_vpp_config()
955 self.ip6_via_ip4_tunnel.remove_vpp_config()
956 self.ipip4.remove_vpp_config()
961 self.ipip6.add_vpp_config()
962 self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index, enable_disable=1)
964 # Set interface up and enable IP on it
965 self.ipip6.admin_up()
966 self.ipip6.set_unnumbered(self.pg0.sw_if_index)
968 # Add IPv4 routes via tunnel interface
969 self.ip4_via_ip6_tunnel = VppIpRoute(
976 self.ipip6.sw_if_index,
977 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
981 self.ip4_via_ip6_tunnel.add_vpp_config()
984 self.ipv6_params = IPsecIPv6Params()
985 self.encryption_type = ESP
986 config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6)
987 self.tun_sa_in_v6 = VppIpsecSA(
989 self.ipv6_params.scapy_tun_sa_id,
990 self.ipv6_params.scapy_tun_spi,
991 self.ipv6_params.auth_algo_vpp_id,
992 self.ipv6_params.auth_key,
993 self.ipv6_params.crypt_algo_vpp_id,
994 self.ipv6_params.crypt_key,
995 VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP,
997 self.tun_sa_in_v6.add_vpp_config()
999 self.tun_sa_out_v6 = VppIpsecSA(
1001 self.ipv6_params.vpp_tun_sa_id,
1002 self.ipv6_params.vpp_tun_spi,
1003 self.ipv6_params.auth_algo_vpp_id,
1004 self.ipv6_params.auth_key,
1005 self.ipv6_params.crypt_algo_vpp_id,
1006 self.ipv6_params.crypt_key,
1007 VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP,
1009 self.tun_sa_out_v6.add_vpp_config()
1011 self.tun_protect_v6 = VppIpsecTunProtect(
1012 self, self.ipip6, self.tun_sa_out_v6, [self.tun_sa_in_v6]
1015 self.tun_protect_v6.add_vpp_config()
1021 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
1022 / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
1023 / TCP(sport=1234, dport=1234)
1024 / Raw(b"\xa5" * 65200)
1027 rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45)
1030 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1031 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1032 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
1033 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
1034 self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
1035 self.assertEqual(rx[ESP].spi, self.ipv6_params.vpp_tun_spi)
1036 inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
1037 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
1038 self.assertEqual(inner[IP].dst, "172.16.10.3")
1039 size += inner[IP].len - 20 - 20
1040 self.assertEqual(size, 65200)
1042 self.ip6_via_ip6_tunnel = VppIpRoute(
1049 self.ipip6.sw_if_index,
1050 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1054 self.ip6_via_ip6_tunnel.add_vpp_config()
1060 Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
1061 / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
1062 / TCP(sport=1234, dport=1234)
1063 / Raw(b"\xa5" * 65200)
1066 rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45)
1069 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1070 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1071 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
1072 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
1073 self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
1074 self.assertEqual(rx[ESP].spi, self.ipv6_params.vpp_tun_spi)
1075 inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
1076 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
1077 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
1078 size += inner[IPv6].plen - 20
1079 self.assertEqual(size, 65200)
1082 self.tun_protect_v6.remove_vpp_config()
1083 self.tun_sa_in_v6.remove_vpp_config()
1084 self.tun_sa_out_v6.remove_vpp_config()
1089 self.ip4_via_ip6_tunnel.remove_vpp_config()
1090 self.ip6_via_ip6_tunnel.remove_vpp_config()
1091 self.ipip6.remove_vpp_config()
1093 self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
1096 if __name__ == "__main__":
1097 unittest.main(testRunner=VppTestRunner)