ipsec: fix SA names consistency in tests
[vpp.git] / test / test_gso.py
1 #!/usr/bin/env python3
2 """GSO functional tests"""
3
4 #
5 # Add tests for:
6 # - GSO
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
10 #
11 import unittest
12
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
20
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
31
32 from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect
33 from template_ipsec import (
34     IPsecIPv4Params,
35     IPsecIPv6Params,
36     mk_scapy_crypt_key,
37     config_tun_params,
38 )
39
40 """ Test_gso is a subclass of VPPTestCase classes.
41     GSO tests.
42 """
43
44
45 class TestGSO(VppTestCase):
46     """GSO Test Case"""
47
48     def __init__(self, *args):
49         VppTestCase.__init__(self, *args)
50
51     @classmethod
52     def setUpClass(self):
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])
61
62     @classmethod
63     def tearDownClass(self):
64         super(TestGSO, self).tearDownClass()
65
66     def setUp(self):
67         super(TestGSO, self).setUp()
68         for i in self.pg_interfaces:
69             i.admin_up()
70             i.config_ip4()
71             i.config_ip6()
72             i.disable_ipv6_ra()
73             i.resolve_arp()
74             i.resolve_ndp()
75
76         self.single_tunnel_bd = 10
77         self.vxlan = VppVxlanTunnel(
78             self,
79             src=self.pg0.local_ip4,
80             dst=self.pg0.remote_ip4,
81             vni=self.single_tunnel_bd,
82         )
83
84         self.vxlan2 = VppVxlanTunnel(
85             self,
86             src=self.pg0.local_ip6,
87             dst=self.pg0.remote_ip6,
88             vni=self.single_tunnel_bd,
89         )
90
91         self.ipip4 = VppIpIpTunInterface(
92             self, self.pg0, self.pg0.local_ip4, self.pg0.remote_ip4
93         )
94         self.ipip6 = VppIpIpTunInterface(
95             self, self.pg0, self.pg0.local_ip6, self.pg0.remote_ip6
96         )
97
98     def tearDown(self):
99         super(TestGSO, self).tearDown()
100         if not self.vpp_dead:
101             for i in self.pg_interfaces:
102                 i.unconfig_ip4()
103                 i.unconfig_ip6()
104                 i.admin_down()
105
106     def test_gso(self):
107         """GSO test"""
108         #
109         # Send jumbo frame with gso disabled and DF bit is set
110         #
111         p4 = (
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)
116         )
117
118         rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
119
120         for rx in rxs:
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"
127
128         #
129         # Send checksum offload frames
130         #
131         p40 = (
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)
136         )
137
138         rxs = self.send_and_expect(self.pg2, 100 * [p40], self.pg0)
139
140         for rx in rxs:
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]))
149
150         p60 = (
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)
155         )
156
157         rxs = self.send_and_expect(self.pg2, 100 * [p60], self.pg0)
158
159         for rx in rxs:
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]))
167
168         #
169         # Send jumbo frame with gso enabled and DF bit is set
170         # input and output interfaces support GSO
171         #
172         self.vapi.feature_gso_enable_disable(
173             sw_if_index=self.pg3.sw_if_index, enable_disable=1
174         )
175         p41 = (
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)
180         )
181
182         rxs = self.send_and_expect(self.pg2, 100 * [p41], self.pg3, 100)
183
184         for rx in rxs:
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)
192
193         #
194         # ipv6
195         #
196         p61 = (
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)
201         )
202
203         rxs = self.send_and_expect(self.pg2, 100 * [p61], self.pg3, 100)
204
205         for rx in rxs:
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)
213
214         #
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
217         # data payload
218         #
219         self.vapi.feature_gso_enable_disable(
220             sw_if_index=self.pg0.sw_if_index, enable_disable=1
221         )
222         p42 = (
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)
227         )
228
229         rxs = self.send_and_expect(self.pg2, 5 * [p42], self.pg0, 225)
230         size = 0
231         for rx in rxs:
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]))
242             size += payload_len
243         self.assertEqual(size, 65200 * 5)
244
245         #
246         # ipv6
247         #
248         p62 = (
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)
253         )
254
255         rxs = self.send_and_expect(self.pg2, 5 * [p62], self.pg0, 225)
256         size = 0
257         for rx in rxs:
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]))
267             size += payload_len
268         self.assertEqual(size, 65200 * 5)
269
270         #
271         # Send jumbo frame with gso enabled only on input interface
272         # and DF bit is unset. GSO packet will be fragmented.
273         #
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
277         )
278
279         p43 = (
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)
284         )
285
286         rxs = self.send_and_expect(self.pg2, 5 * [p43], self.pg1, 5 * 119)
287         size = 0
288         for rx in rxs:
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)
297
298         #
299         # IPv6
300         # Send jumbo frame with gso enabled only on input interface.
301         # ICMPv6 Packet Too Big will be sent back to sender.
302         #
303         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
304         p63 = (
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)
309         )
310
311         rxs = self.send_and_expect_some(self.pg2, 5 * [p63], self.pg2, 5)
312         for rx in rxs:
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)
323
324         #
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
328         #
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])
331         p44 = (
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)
336         )
337
338         rxs = self.send_and_expect(self.pg4, 5 * [p44], self.pg1, 165)
339         size = 0
340         for rx in rxs:
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]))
349             size += payload_len
350         self.assertEqual(size, 65200 * 5)
351
352         #
353         # IPv6
354         #
355         p64 = (
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)
360         )
361
362         rxs = self.send_and_expect(self.pg4, 5 * [p64], self.pg1, 170)
363         size = 0
364         for rx in rxs:
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]))
372             size += payload_len
373         self.assertEqual(size, 65200 * 5)
374
375         self.vapi.feature_gso_enable_disable(
376             sw_if_index=self.pg0.sw_if_index, enable_disable=0
377         )
378         self.vapi.feature_gso_enable_disable(
379             sw_if_index=self.pg1.sw_if_index, enable_disable=0
380         )
381
382     def test_gso_vxlan(self):
383         """GSO VXLAN test"""
384         self.logger.info(self.vapi.cli("sh int addr"))
385         #
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
388         # into BD.
389         #
390
391         #
392         # enable ipv4/vxlan
393         #
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
397         )
398         self.vapi.sw_interface_set_l2_bridge(
399             rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd
400         )
401         self.vapi.feature_gso_enable_disable(
402             sw_if_index=self.pg0.sw_if_index, enable_disable=1
403         )
404
405         #
406         # IPv4/IPv4 - VXLAN
407         #
408         p45 = (
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)
413         )
414
415         rxs = self.send_and_expect(self.pg2, 5 * [p45], self.pg0, 225)
416         size = 0
417         for rx in rxs:
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]))
435             size += payload_len
436         self.assertEqual(size, 65200 * 5)
437
438         #
439         # IPv4/IPv6 - VXLAN
440         #
441         p65 = (
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)
446         )
447
448         rxs = self.send_and_expect(self.pg2, 5 * [p65], self.pg0, 225)
449         size = 0
450         for rx in rxs:
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]))
467             size += payload_len
468         self.assertEqual(size, 65200 * 5)
469
470         #
471         # disable ipv4/vxlan
472         #
473         self.vxlan.remove_vpp_config()
474
475         #
476         # enable ipv6/vxlan
477         #
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
481         )
482
483         #
484         # IPv6/IPv4 - VXLAN
485         #
486         p46 = (
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)
491         )
492
493         rxs = self.send_and_expect(self.pg2, 5 * [p46], self.pg0, 225)
494         size = 0
495         for rx in rxs:
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]))
512             size += payload_len
513         self.assertEqual(size, 65200 * 5)
514
515         #
516         # IPv6/IPv6 - VXLAN
517         #
518         p66 = (
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)
523         )
524
525         rxs = self.send_and_expect(self.pg2, 5 * [p66], self.pg0, 225)
526         size = 0
527         for rx in rxs:
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]))
543             size += payload_len
544         self.assertEqual(size, 65200 * 5)
545
546         #
547         # disable ipv4/vxlan
548         #
549         self.vxlan2.remove_vpp_config()
550
551         self.vapi.feature_gso_enable_disable(
552             sw_if_index=self.pg0.sw_if_index, enable_disable=0
553         )
554
555     def test_gso_ipip(self):
556         """GSO IPIP test"""
557         self.logger.info(self.vapi.cli("sh int addr"))
558         #
559         # Send jumbo frame with gso enabled only on input interface and
560         # create IPIP tunnel on VPP pg0.
561         #
562         self.vapi.feature_gso_enable_disable(
563             sw_if_index=self.pg0.sw_if_index, enable_disable=1
564         )
565
566         #
567         # enable ipip4
568         #
569         self.ipip4.add_vpp_config()
570
571         # Set interface up and enable IP on it
572         self.ipip4.admin_up()
573         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
574
575         # Add IPv4 routes via tunnel interface
576         self.ip4_via_ip4_tunnel = VppIpRoute(
577             self,
578             "172.16.10.0",
579             24,
580             [
581                 VppRoutePath(
582                     "0.0.0.0",
583                     self.ipip4.sw_if_index,
584                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
585                 )
586             ],
587         )
588         self.ip4_via_ip4_tunnel.add_vpp_config()
589
590         #
591         # IPv4/IPv4 - IPIP
592         #
593         p47 = (
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)
598         )
599
600         rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225)
601         size = 0
602         for rx in rxs:
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]))
617             size += payload_len
618         self.assertEqual(size, 65200 * 5)
619
620         self.ip6_via_ip4_tunnel = VppIpRoute(
621             self,
622             "fd01:10::",
623             64,
624             [
625                 VppRoutePath(
626                     "::",
627                     self.ipip4.sw_if_index,
628                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
629                 )
630             ],
631         )
632         self.ip6_via_ip4_tunnel.add_vpp_config()
633         #
634         # IPv4/IPv6 - IPIP
635         #
636         p67 = (
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)
641         )
642
643         rxs = self.send_and_expect(self.pg2, 5 * [p67], self.pg0, 225)
644         size = 0
645         for rx in rxs:
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]))
659             size += payload_len
660         self.assertEqual(size, 65200 * 5)
661
662         #
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
666         #
667         self.vapi.feature_gso_enable_disable(
668             sw_if_index=self.pg0.sw_if_index, enable_disable=0
669         )
670         self.vapi.feature_gso_enable_disable(
671             sw_if_index=self.ipip4.sw_if_index, enable_disable=1
672         )
673
674         rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225)
675         size = 0
676         for rx in rxs:
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]))
691             size += payload_len
692         self.assertEqual(size, 65200 * 5)
693
694         #
695         # disable ipip4
696         #
697         self.vapi.feature_gso_enable_disable(
698             sw_if_index=self.ipip4.sw_if_index, enable_disable=0
699         )
700         self.ip4_via_ip4_tunnel.remove_vpp_config()
701         self.ip6_via_ip4_tunnel.remove_vpp_config()
702         self.ipip4.remove_vpp_config()
703
704         #
705         # enable ipip6
706         #
707         self.vapi.feature_gso_enable_disable(
708             sw_if_index=self.pg0.sw_if_index, enable_disable=1
709         )
710         self.ipip6.add_vpp_config()
711
712         # Set interface up and enable IP on it
713         self.ipip6.admin_up()
714         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
715
716         # Add IPv4 routes via tunnel interface
717         self.ip4_via_ip6_tunnel = VppIpRoute(
718             self,
719             "172.16.10.0",
720             24,
721             [
722                 VppRoutePath(
723                     "0.0.0.0",
724                     self.ipip6.sw_if_index,
725                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
726                 )
727             ],
728         )
729         self.ip4_via_ip6_tunnel.add_vpp_config()
730
731         #
732         # IPv6/IPv4 - IPIP
733         #
734         p48 = (
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)
739         )
740
741         rxs = self.send_and_expect(self.pg2, 5 * [p48], self.pg0, 225)
742         size = 0
743         for rx in rxs:
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]))
757             size += payload_len
758         self.assertEqual(size, 65200 * 5)
759
760         self.ip6_via_ip6_tunnel = VppIpRoute(
761             self,
762             "fd01:10::",
763             64,
764             [
765                 VppRoutePath(
766                     "::",
767                     self.ipip6.sw_if_index,
768                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
769                 )
770             ],
771         )
772         self.ip6_via_ip6_tunnel.add_vpp_config()
773
774         #
775         # IPv6/IPv6 - IPIP
776         #
777         p68 = (
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)
782         )
783
784         rxs = self.send_and_expect(self.pg2, 5 * [p68], self.pg0, 225)
785         size = 0
786         for rx in rxs:
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]))
799             size += payload_len
800         self.assertEqual(size, 65200 * 5)
801
802         #
803         # disable ipip6
804         #
805         self.ip4_via_ip6_tunnel.remove_vpp_config()
806         self.ip6_via_ip6_tunnel.remove_vpp_config()
807         self.ipip6.remove_vpp_config()
808
809         self.vapi.feature_gso_enable_disable(
810             sw_if_index=self.pg0.sw_if_index, enable_disable=0
811         )
812
813     def test_gso_ipsec(self):
814         """GSO IPSEC test"""
815         #
816         # Send jumbo frame with gso enabled only on input interface and
817         # create IPIP tunnel on VPP pg0.
818         #
819
820         #
821         # enable ipip4
822         #
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
826         )
827
828         # Add IPv4 routes via tunnel interface
829         self.ip4_via_ip4_tunnel = VppIpRoute(
830             self,
831             "172.16.10.0",
832             24,
833             [
834                 VppRoutePath(
835                     "0.0.0.0",
836                     self.ipip4.sw_if_index,
837                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
838                 )
839             ],
840         )
841         self.ip4_via_ip4_tunnel.add_vpp_config()
842
843         # IPSec config
844         self.ipv4_params = IPsecIPv4Params()
845         self.encryption_type = ESP
846         config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4)
847
848         self.tun_sa_in_v4 = VppIpsecSA(
849             self,
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,
857         )
858         self.tun_sa_in_v4.add_vpp_config()
859
860         self.tun_sa_out_v4 = VppIpsecSA(
861             self,
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,
869         )
870         self.tun_sa_out_v4.add_vpp_config()
871
872         self.tun_protect_v4 = VppIpsecTunProtect(
873             self, self.ipip4, self.tun_sa_out_v4, [self.tun_sa_in_v4]
874         )
875
876         self.tun_protect_v4.add_vpp_config()
877
878         # Set interface up and enable IP on it
879         self.ipip4.admin_up()
880         self.ipip4.set_unnumbered(self.pg0.sw_if_index)
881
882         #
883         # IPv4/IPv4 - IPSEC
884         #
885         ipsec44 = (
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)
890         )
891
892         rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45)
893         size = 0
894         for rx in rxs:
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)
906
907         self.ip6_via_ip4_tunnel = VppIpRoute(
908             self,
909             "fd01:10::",
910             64,
911             [
912                 VppRoutePath(
913                     "::",
914                     self.ipip4.sw_if_index,
915                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
916                 )
917             ],
918         )
919         self.ip6_via_ip4_tunnel.add_vpp_config()
920         #
921         # IPv4/IPv6 - IPSEC
922         #
923         ipsec46 = (
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)
928         )
929
930         rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45)
931         size = 0
932         for rx in rxs:
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)
944
945         # disable IPSec
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()
949
950         #
951         # disable ipip4
952         #
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()
957
958         #
959         # enable ipip6
960         #
961         self.ipip6.add_vpp_config()
962         self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index, enable_disable=1)
963
964         # Set interface up and enable IP on it
965         self.ipip6.admin_up()
966         self.ipip6.set_unnumbered(self.pg0.sw_if_index)
967
968         # Add IPv4 routes via tunnel interface
969         self.ip4_via_ip6_tunnel = VppIpRoute(
970             self,
971             "172.16.10.0",
972             24,
973             [
974                 VppRoutePath(
975                     "0.0.0.0",
976                     self.ipip6.sw_if_index,
977                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
978                 )
979             ],
980         )
981         self.ip4_via_ip6_tunnel.add_vpp_config()
982
983         # IPSec 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(
988             self,
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,
996         )
997         self.tun_sa_in_v6.add_vpp_config()
998
999         self.tun_sa_out_v6 = VppIpsecSA(
1000             self,
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,
1008         )
1009         self.tun_sa_out_v6.add_vpp_config()
1010
1011         self.tun_protect_v6 = VppIpsecTunProtect(
1012             self, self.ipip6, self.tun_sa_out_v6, [self.tun_sa_in_v6]
1013         )
1014
1015         self.tun_protect_v6.add_vpp_config()
1016
1017         #
1018         # IPv6/IPv4 - IPSEC
1019         #
1020         ipsec64 = (
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)
1025         )
1026
1027         rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45)
1028         size = 0
1029         for rx in rxs:
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)
1041
1042         self.ip6_via_ip6_tunnel = VppIpRoute(
1043             self,
1044             "fd01:10::",
1045             64,
1046             [
1047                 VppRoutePath(
1048                     "::",
1049                     self.ipip6.sw_if_index,
1050                     proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1051                 )
1052             ],
1053         )
1054         self.ip6_via_ip6_tunnel.add_vpp_config()
1055
1056         #
1057         # IPv6/IPv6 - IPSEC
1058         #
1059         ipsec66 = (
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)
1064         )
1065
1066         rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45)
1067         size = 0
1068         for rx in rxs:
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)
1080
1081         # disable IPSec
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()
1085
1086         #
1087         # disable ipip6
1088         #
1089         self.ip4_via_ip6_tunnel.remove_vpp_config()
1090         self.ip6_via_ip6_tunnel.remove_vpp_config()
1091         self.ipip6.remove_vpp_config()
1092
1093         self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
1094
1095
1096 if __name__ == "__main__":
1097     unittest.main(testRunner=VppTestRunner)