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 IPsecIPv4Params, IPsecIPv6Params, \
34 mk_scapy_crypt_key, config_tun_params
36 """ Test_gso is a subclass of VPPTestCase classes.
41 class TestGSO(VppTestCase):
44 def __init__(self, *args):
45 VppTestCase.__init__(self, *args)
49 super(TestGSO, self).setUpClass()
50 res = self.create_pg_interfaces(range(2))
51 res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460)
52 self.create_pg_interfaces(range(4, 5), 1, 8940)
53 self.pg_interfaces.append(res[0])
54 self.pg_interfaces.append(res[1])
55 self.pg_interfaces.append(res_gso[0])
56 self.pg_interfaces.append(res_gso[1])
59 def tearDownClass(self):
60 super(TestGSO, self).tearDownClass()
63 super(TestGSO, self).setUp()
64 for i in self.pg_interfaces:
72 self.single_tunnel_bd = 10
73 self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4,
74 dst=self.pg0.remote_ip4,
75 vni=self.single_tunnel_bd)
77 self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6,
78 dst=self.pg0.remote_ip6,
79 vni=self.single_tunnel_bd)
81 self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4,
83 self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6,
87 super(TestGSO, self).tearDown()
89 for i in self.pg_interfaces:
97 # Send jumbo frame with gso disabled and DF bit is set
99 p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
100 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
102 TCP(sport=1234, dport=1234) /
103 Raw(b'\xa5' * 65200))
105 rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
108 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
109 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
110 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
111 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
112 self.assertEqual(rx[ICMP].type, 3) # "dest-unreach"
113 self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed"
116 # Send checksum offload frames
118 p40 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
119 IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
121 TCP(sport=1234, dport=1234) /
124 rxs = self.send_and_expect(self.pg2, 100*[p40], self.pg0)
127 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
128 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
129 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
130 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
131 payload_len = rx[IP].len - 20 - 20
132 self.assert_ip_checksum_valid(rx)
133 self.assert_tcp_checksum_valid(rx)
134 self.assertEqual(payload_len, len(rx[Raw]))
136 p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
137 IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
138 TCP(sport=1234, dport=1234) /
141 rxs = self.send_and_expect(self.pg2, 100*[p60], self.pg0)
144 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
145 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
146 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
147 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
148 payload_len = rx[IPv6].plen - 20
149 self.assert_tcp_checksum_valid(rx)
150 self.assertEqual(payload_len, len(rx[Raw]))
153 # Send jumbo frame with gso enabled and DF bit is set
154 # input and output interfaces support GSO
156 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg3.sw_if_index,
158 p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
159 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
161 TCP(sport=1234, dport=1234) /
162 Raw(b'\xa5' * 65200))
164 rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100)
167 self.assertEqual(rx[Ether].src, self.pg3.local_mac)
168 self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
169 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
170 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
171 self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP)
172 self.assertEqual(rx[TCP].sport, 1234)
173 self.assertEqual(rx[TCP].dport, 1234)
178 p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
179 IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
180 TCP(sport=1234, dport=1234) /
181 Raw(b'\xa5' * 65200))
183 rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100)
186 self.assertEqual(rx[Ether].src, self.pg3.local_mac)
187 self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
188 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
189 self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
190 self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP)
191 self.assertEqual(rx[TCP].sport, 1234)
192 self.assertEqual(rx[TCP].dport, 1234)
195 # Send jumbo frame with gso enabled only on input interface
196 # and DF bit is set. GSO packet will be chunked into gso_size
199 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
201 p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
202 IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
204 TCP(sport=1234, dport=1234) /
205 Raw(b'\xa5' * 65200))
207 rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225)
210 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
211 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
212 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
213 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
214 payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
215 self.assert_ip_checksum_valid(rx)
216 self.assert_tcp_checksum_valid(rx)
217 self.assertEqual(rx[TCP].sport, 1234)
218 self.assertEqual(rx[TCP].dport, 1234)
219 self.assertEqual(payload_len, len(rx[Raw]))
221 self.assertEqual(size, 65200*5)
226 p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
227 IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
228 TCP(sport=1234, dport=1234) /
229 Raw(b'\xa5' * 65200))
231 rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225)
234 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
235 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
236 self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
237 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
238 payload_len = rx[IPv6].plen - 20
239 self.assert_tcp_checksum_valid(rx)
240 self.assertEqual(rx[TCP].sport, 1234)
241 self.assertEqual(rx[TCP].dport, 1234)
242 self.assertEqual(payload_len, len(rx[Raw]))
244 self.assertEqual(size, 65200*5)
247 # Send jumbo frame with gso enabled only on input interface
248 # and DF bit is unset. GSO packet will be fragmented.
250 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
251 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
254 p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
255 IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
256 TCP(sport=1234, dport=1234) /
257 Raw(b'\xa5' * 65200))
259 rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119)
262 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
263 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
264 self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
265 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
266 self.assert_ip_checksum_valid(rx)
267 size += rx[IP].len - 20
268 size -= 20*5 # TCP header
269 self.assertEqual(size, 65200*5)
273 # Send jumbo frame with gso enabled only on input interface.
274 # ICMPv6 Packet Too Big will be sent back to sender.
276 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
277 p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
278 IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
279 TCP(sport=1234, dport=1234) /
280 Raw(b'\xa5' * 65200))
282 rxs = self.send_and_expect_some(self.pg2, 5*[p63], self.pg2, 5)
284 self.assertEqual(rx[Ether].src, self.pg2.local_mac)
285 self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
286 self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
287 self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
288 self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header
289 self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
290 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
291 self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
292 self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
293 self.assertEqual(rx[IPerror6].plen - 20, 65200)
296 # Send jumbo frame with gso enabled only on input interface with 9K MTU
297 # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
298 # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
300 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
301 self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
302 p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
303 IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
304 TCP(sport=1234, dport=1234) /
305 Raw(b'\xa5' * 65200))
307 rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165)
310 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
311 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
312 self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
313 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
314 payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
315 self.assert_ip_checksum_valid(rx)
316 self.assert_tcp_checksum_valid(rx)
317 self.assertEqual(payload_len, len(rx[Raw]))
319 self.assertEqual(size, 65200*5)
324 p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
325 IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
326 TCP(sport=1234, dport=1234) /
327 Raw(b'\xa5' * 65200))
329 rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170)
332 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
333 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
334 self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
335 self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
336 payload_len = rx[IPv6].plen - 20
337 self.assert_tcp_checksum_valid(rx)
338 self.assertEqual(payload_len, len(rx[Raw]))
340 self.assertEqual(size, 65200*5)
342 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
344 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
347 def test_gso_vxlan(self):
348 """ GSO VXLAN test """
349 self.logger.info(self.vapi.cli("sh int addr"))
351 # Send jumbo frame with gso enabled only on input interface and
352 # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
359 self.vxlan.add_vpp_config()
360 self.vapi.sw_interface_set_l2_bridge(
361 rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
362 self.vapi.sw_interface_set_l2_bridge(
363 rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
364 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
370 p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
371 IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
372 TCP(sport=1234, dport=1234) /
373 Raw(b'\xa5' * 65200))
375 rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225)
378 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
379 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
380 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
381 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
382 self.assert_ip_checksum_valid(rx)
383 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
384 self.assertEqual(rx[VXLAN].vni, 10)
385 inner = rx[VXLAN].payload
386 self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
387 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
388 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
389 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
390 self.assertEqual(inner[IP].dst, "172.16.3.3")
391 self.assert_ip_checksum_valid(inner)
392 self.assert_tcp_checksum_valid(inner)
393 payload_len = inner[IP].len - 20 - 20
394 self.assertEqual(payload_len, len(inner[Raw]))
396 self.assertEqual(size, 65200*5)
401 p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
402 IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
403 TCP(sport=1234, dport=1234) /
404 Raw(b'\xa5' * 65200))
406 rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225)
409 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
410 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
411 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
412 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
413 self.assert_ip_checksum_valid(rx)
414 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
415 self.assertEqual(rx[VXLAN].vni, 10)
416 inner = rx[VXLAN].payload
417 self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
418 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
419 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
420 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
421 self.assertEqual(inner[IPv6].dst, "fd01:3::3")
422 self.assert_tcp_checksum_valid(inner)
423 payload_len = inner[IPv6].plen - 20
424 self.assertEqual(payload_len, len(inner[Raw]))
426 self.assertEqual(size, 65200*5)
431 self.vxlan.remove_vpp_config()
436 self.vxlan2.add_vpp_config()
437 self.vapi.sw_interface_set_l2_bridge(
438 rx_sw_if_index=self.vxlan2.sw_if_index,
439 bd_id=self.single_tunnel_bd)
444 p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
445 IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
446 TCP(sport=1234, dport=1234) /
447 Raw(b'\xa5' * 65200))
449 rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225)
452 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
453 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
454 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
455 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
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[IPv6].plen - 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[IP].src, self.pg2.remote_ip4)
463 self.assertEqual(inner[IP].dst, "172.16.3.3")
464 self.assert_ip_checksum_valid(inner)
465 self.assert_tcp_checksum_valid(inner)
466 payload_len = inner[IP].len - 20 - 20
467 self.assertEqual(payload_len, len(inner[Raw]))
469 self.assertEqual(size, 65200*5)
474 p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
475 IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
476 TCP(sport=1234, dport=1234) /
477 Raw(b'\xa5' * 65200))
479 rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225)
482 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
483 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
484 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
485 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
486 self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
487 self.assertEqual(rx[VXLAN].vni, 10)
488 inner = rx[VXLAN].payload
489 self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
490 self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
491 self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
492 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
493 self.assertEqual(inner[IPv6].dst, "fd01:3::3")
494 self.assert_tcp_checksum_valid(inner)
495 payload_len = inner[IPv6].plen - 20
496 self.assertEqual(payload_len, len(inner[Raw]))
498 self.assertEqual(size, 65200*5)
503 self.vxlan2.remove_vpp_config()
505 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
508 def test_gso_ipip(self):
509 """ GSO IPIP test """
510 self.logger.info(self.vapi.cli("sh int addr"))
512 # Send jumbo frame with gso enabled only on input interface and
513 # create IPIP tunnel on VPP pg0.
515 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
521 self.ipip4.add_vpp_config()
523 # Set interface up and enable IP on it
524 self.ipip4.admin_up()
525 self.ipip4.set_unnumbered(self.pg0.sw_if_index)
527 # Add IPv4 routes via tunnel interface
528 self.ip4_via_ip4_tunnel = VppIpRoute(
529 self, "172.16.10.0", 24,
530 [VppRoutePath("0.0.0.0",
531 self.ipip4.sw_if_index,
532 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
533 self.ip4_via_ip4_tunnel.add_vpp_config()
538 p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
539 IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
540 TCP(sport=1234, dport=1234) /
541 Raw(b'\xa5' * 65200))
543 rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
546 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
547 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
548 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
549 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
550 self.assert_ip_checksum_valid(rx)
551 self.assertEqual(rx[IP].proto, 4) # ipencap
552 inner = rx[IP].payload
553 self.assertEqual(rx[IP].len - 20, len(inner))
554 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
555 self.assertEqual(inner[IP].dst, "172.16.10.3")
556 self.assert_ip_checksum_valid(inner)
557 self.assert_tcp_checksum_valid(inner)
558 payload_len = inner[IP].len - 20 - 20
559 self.assertEqual(payload_len, len(inner[Raw]))
561 self.assertEqual(size, 65200*5)
563 self.ip6_via_ip4_tunnel = VppIpRoute(
564 self, "fd01:10::", 64,
566 self.ipip4.sw_if_index,
567 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
568 self.ip6_via_ip4_tunnel.add_vpp_config()
572 p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
573 IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
574 TCP(sport=1234, dport=1234) /
575 Raw(b'\xa5' * 65200))
577 rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225)
580 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
581 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
582 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
583 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
584 self.assert_ip_checksum_valid(rx)
585 self.assertEqual(rx[IP].proto, 41) # ipv6
586 inner = rx[IP].payload
587 self.assertEqual(rx[IP].len - 20, len(inner))
588 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
589 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
590 self.assert_tcp_checksum_valid(inner)
591 payload_len = inner[IPv6].plen - 20
592 self.assertEqual(payload_len, len(inner[Raw]))
594 self.assertEqual(size, 65200*5)
597 # Send jumbo frame with gso enabled only on input interface and
598 # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
599 # tunnel - IPSec use case
601 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
603 self.vapi.feature_gso_enable_disable(
604 sw_if_index=self.ipip4.sw_if_index,
607 rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
610 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
611 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
612 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
613 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
614 self.assert_ip_checksum_valid(rx)
615 self.assertEqual(rx[IP].proto, 4) # ipencap
616 inner = rx[IP].payload
617 self.assertEqual(rx[IP].len - 20, len(inner))
618 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
619 self.assertEqual(inner[IP].dst, "172.16.10.3")
620 self.assert_ip_checksum_valid(inner)
621 self.assert_tcp_checksum_valid(inner)
622 payload_len = inner[IP].len - 20 - 20
623 self.assertEqual(payload_len, len(inner[Raw]))
625 self.assertEqual(size, 65200*5)
630 self.vapi.feature_gso_enable_disable(
631 sw_if_index=self.ipip4.sw_if_index,
633 self.ip4_via_ip4_tunnel.remove_vpp_config()
634 self.ip6_via_ip4_tunnel.remove_vpp_config()
635 self.ipip4.remove_vpp_config()
640 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
642 self.ipip6.add_vpp_config()
644 # Set interface up and enable IP on it
645 self.ipip6.admin_up()
646 self.ipip6.set_unnumbered(self.pg0.sw_if_index)
648 # Add IPv4 routes via tunnel interface
649 self.ip4_via_ip6_tunnel = VppIpRoute(
650 self, "172.16.10.0", 24,
651 [VppRoutePath("0.0.0.0",
652 self.ipip6.sw_if_index,
653 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
654 self.ip4_via_ip6_tunnel.add_vpp_config()
659 p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
660 IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
661 TCP(sport=1234, dport=1234) /
662 Raw(b'\xa5' * 65200))
664 rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225)
667 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
668 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
669 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
670 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
671 self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
672 inner = rx[IPv6].payload
673 self.assertEqual(rx[IPv6].plen, len(inner))
674 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
675 self.assertEqual(inner[IP].dst, "172.16.10.3")
676 self.assert_ip_checksum_valid(inner)
677 self.assert_tcp_checksum_valid(inner)
678 payload_len = inner[IP].len - 20 - 20
679 self.assertEqual(payload_len, len(inner[Raw]))
681 self.assertEqual(size, 65200*5)
683 self.ip6_via_ip6_tunnel = VppIpRoute(
684 self, "fd01:10::", 64,
686 self.ipip6.sw_if_index,
687 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
688 self.ip6_via_ip6_tunnel.add_vpp_config()
693 p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
694 IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
695 TCP(sport=1234, dport=1234) /
696 Raw(b'\xa5' * 65200))
698 rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225)
701 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
702 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
703 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
704 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
705 self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
706 inner = rx[IPv6].payload
707 self.assertEqual(rx[IPv6].plen, len(inner))
708 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
709 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
710 self.assert_tcp_checksum_valid(inner)
711 payload_len = inner[IPv6].plen - 20
712 self.assertEqual(payload_len, len(inner[Raw]))
714 self.assertEqual(size, 65200*5)
719 self.ip4_via_ip6_tunnel.remove_vpp_config()
720 self.ip6_via_ip6_tunnel.remove_vpp_config()
721 self.ipip6.remove_vpp_config()
723 self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
726 def test_gso_ipsec(self):
727 """ GSO IPSEC test """
729 # Send jumbo frame with gso enabled only on input interface and
730 # create IPIP tunnel on VPP pg0.
736 self.ipip4.add_vpp_config()
737 self.vapi.feature_gso_enable_disable(
738 sw_if_index=self.ipip4.sw_if_index, enable_disable=1)
740 # Add IPv4 routes via tunnel interface
741 self.ip4_via_ip4_tunnel = VppIpRoute(
742 self, "172.16.10.0", 24,
743 [VppRoutePath("0.0.0.0",
744 self.ipip4.sw_if_index,
745 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
746 self.ip4_via_ip4_tunnel.add_vpp_config()
749 self.ipv4_params = IPsecIPv4Params()
750 self.encryption_type = ESP
751 config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4)
753 self.tun_sa_in_v4 = VppIpsecSA(self, self.ipv4_params.vpp_tun_sa_id,
754 self.ipv4_params.vpp_tun_spi,
755 self.ipv4_params.auth_algo_vpp_id,
756 self.ipv4_params.auth_key,
757 self.ipv4_params.crypt_algo_vpp_id,
758 self.ipv4_params.crypt_key,
759 VppEnum.vl_api_ipsec_proto_t.
761 self.tun_sa_in_v4.add_vpp_config()
763 self.tun_sa_out_v4 = VppIpsecSA(self, self.ipv4_params.scapy_tun_sa_id,
764 self.ipv4_params.scapy_tun_spi,
765 self.ipv4_params.auth_algo_vpp_id,
766 self.ipv4_params.auth_key,
767 self.ipv4_params.crypt_algo_vpp_id,
768 self.ipv4_params.crypt_key,
769 VppEnum.vl_api_ipsec_proto_t.
771 self.tun_sa_out_v4.add_vpp_config()
773 self.tun_protect_v4 = VppIpsecTunProtect(self,
778 self.tun_protect_v4.add_vpp_config()
780 # Set interface up and enable IP on it
781 self.ipip4.admin_up()
782 self.ipip4.set_unnumbered(self.pg0.sw_if_index)
787 ipsec44 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
788 IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
789 TCP(sport=1234, dport=1234) /
790 Raw(b'\xa5' * 65200))
792 rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45)
795 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
796 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
797 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
798 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
799 self.assertEqual(rx[IP].proto, 50) # ESP
800 self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
801 inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
802 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
803 self.assertEqual(inner[IP].dst, "172.16.10.3")
804 size += inner[IP].len - 20 - 20
805 self.assertEqual(size, 65200)
807 self.ip6_via_ip4_tunnel = VppIpRoute(
808 self, "fd01:10::", 64,
810 self.ipip4.sw_if_index,
811 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
812 self.ip6_via_ip4_tunnel.add_vpp_config()
816 ipsec46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
817 IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
818 TCP(sport=1234, dport=1234) /
819 Raw(b'\xa5' * 65200))
821 rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45)
824 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
825 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
826 self.assertEqual(rx[IP].src, self.pg0.local_ip4)
827 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
828 self.assertEqual(rx[IP].proto, 50) # ESP
829 self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
830 inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
831 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
832 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
833 size += inner[IPv6].plen - 20
834 self.assertEqual(size, 65200)
837 self.tun_protect_v4.remove_vpp_config()
838 self.tun_sa_in_v4.remove_vpp_config()
839 self.tun_sa_out_v4.remove_vpp_config()
844 self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index,
846 self.ip4_via_ip4_tunnel.remove_vpp_config()
847 self.ip6_via_ip4_tunnel.remove_vpp_config()
848 self.ipip4.remove_vpp_config()
853 self.ipip6.add_vpp_config()
854 self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index,
857 # Set interface up and enable IP on it
858 self.ipip6.admin_up()
859 self.ipip6.set_unnumbered(self.pg0.sw_if_index)
861 # Add IPv4 routes via tunnel interface
862 self.ip4_via_ip6_tunnel = VppIpRoute(
863 self, "172.16.10.0", 24,
864 [VppRoutePath("0.0.0.0",
865 self.ipip6.sw_if_index,
866 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
867 self.ip4_via_ip6_tunnel.add_vpp_config()
870 self.ipv6_params = IPsecIPv6Params()
871 self.encryption_type = ESP
872 config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6)
873 self.tun_sa_in_v6 = VppIpsecSA(self, self.ipv6_params.vpp_tun_sa_id,
874 self.ipv6_params.vpp_tun_spi,
875 self.ipv6_params.auth_algo_vpp_id,
876 self.ipv6_params.auth_key,
877 self.ipv6_params.crypt_algo_vpp_id,
878 self.ipv6_params.crypt_key,
879 VppEnum.vl_api_ipsec_proto_t.
881 self.tun_sa_in_v6.add_vpp_config()
883 self.tun_sa_out_v6 = VppIpsecSA(self, self.ipv6_params.scapy_tun_sa_id,
884 self.ipv6_params.scapy_tun_spi,
885 self.ipv6_params.auth_algo_vpp_id,
886 self.ipv6_params.auth_key,
887 self.ipv6_params.crypt_algo_vpp_id,
888 self.ipv6_params.crypt_key,
889 VppEnum.vl_api_ipsec_proto_t.
891 self.tun_sa_out_v6.add_vpp_config()
893 self.tun_protect_v6 = VppIpsecTunProtect(self,
898 self.tun_protect_v6.add_vpp_config()
903 ipsec64 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
904 IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
905 TCP(sport=1234, dport=1234) /
906 Raw(b'\xa5' * 65200))
908 rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45)
911 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
912 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
913 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
914 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
915 self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
916 self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
917 inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
918 self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
919 self.assertEqual(inner[IP].dst, "172.16.10.3")
920 size += inner[IP].len - 20 - 20
921 self.assertEqual(size, 65200)
923 self.ip6_via_ip6_tunnel = VppIpRoute(
924 self, "fd01:10::", 64,
926 self.ipip6.sw_if_index,
927 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
928 self.ip6_via_ip6_tunnel.add_vpp_config()
933 ipsec66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
934 IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
935 TCP(sport=1234, dport=1234) /
936 Raw(b'\xa5' * 65200))
938 rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45)
941 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
942 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
943 self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
944 self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
945 self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
946 self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
947 inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
948 self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
949 self.assertEqual(inner[IPv6].dst, "fd01:10::3")
950 size += inner[IPv6].plen - 20
951 self.assertEqual(size, 65200)
954 self.tun_protect_v6.remove_vpp_config()
955 self.tun_sa_in_v6.remove_vpp_config()
956 self.tun_sa_out_v6.remove_vpp_config()
961 self.ip4_via_ip6_tunnel.remove_vpp_config()
962 self.ip6_via_ip6_tunnel.remove_vpp_config()
963 self.ipip6.remove_vpp_config()
965 self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
968 if __name__ == '__main__':
969 unittest.main(testRunner=VppTestRunner)