6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, Dot1Q, GRE
8 from scapy.layers.inet import IP, UDP
9 from scapy.layers.inet6 import IPv6
10 from scapy.volatile import RandMAC, RandIP
12 from framework import VppTestCase, VppTestRunner
13 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
14 from vpp_gre_interface import VppGreInterface, VppGre6Interface
15 from vpp_ip import DpoProto
16 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
17 from util import ppp, ppc
26 class TestGRE(VppTestCase):
31 super(TestGRE, cls).setUpClass()
34 def tearDownClass(cls):
35 super(TestGRE, cls).tearDownClass()
38 super(TestGRE, self).setUp()
40 # create 3 pg interfaces - set one in a non-default table.
41 self.create_pg_interfaces(range(3))
43 self.tbl = VppIpTable(self, 1)
44 self.tbl.add_vpp_config()
45 self.pg1.set_table_ip4(1)
47 for i in self.pg_interfaces:
51 self.pg0.resolve_arp()
53 self.pg1.resolve_arp()
55 self.pg2.resolve_ndp()
58 for i in self.pg_interfaces:
62 self.pg1.set_table_ip4(0)
63 super(TestGRE, self).tearDown()
65 def create_stream_ip4(self, src_if, src_ip, dst_ip):
67 for i in range(0, 257):
68 info = self.create_packet_info(src_if, src_if)
69 payload = self.info_to_payload(info)
70 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
71 IP(src=src_ip, dst=dst_ip) /
72 UDP(sport=1234, dport=1234) /
78 def create_stream_ip6(self, src_if, src_ip, dst_ip):
80 for i in range(0, 257):
81 info = self.create_packet_info(src_if, src_if)
82 payload = self.info_to_payload(info)
83 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
84 IPv6(src=src_ip, dst=dst_ip) /
85 UDP(sport=1234, dport=1234) /
91 def create_tunnel_stream_4o4(self, src_if,
92 tunnel_src, tunnel_dst,
95 for i in range(0, 257):
96 info = self.create_packet_info(src_if, src_if)
97 payload = self.info_to_payload(info)
98 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
99 IP(src=tunnel_src, dst=tunnel_dst) /
101 IP(src=src_ip, dst=dst_ip) /
102 UDP(sport=1234, dport=1234) /
108 def create_tunnel_stream_6o4(self, src_if,
109 tunnel_src, tunnel_dst,
112 for i in range(0, 257):
113 info = self.create_packet_info(src_if, src_if)
114 payload = self.info_to_payload(info)
115 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
116 IP(src=tunnel_src, dst=tunnel_dst) /
118 IPv6(src=src_ip, dst=dst_ip) /
119 UDP(sport=1234, dport=1234) /
125 def create_tunnel_stream_6o6(self, src_if,
126 tunnel_src, tunnel_dst,
129 for i in range(0, 257):
130 info = self.create_packet_info(src_if, src_if)
131 payload = self.info_to_payload(info)
132 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
133 IPv6(src=tunnel_src, dst=tunnel_dst) /
135 IPv6(src=src_ip, dst=dst_ip) /
136 UDP(sport=1234, dport=1234) /
142 def create_tunnel_stream_l2o4(self, src_if,
143 tunnel_src, tunnel_dst):
145 for i in range(0, 257):
146 info = self.create_packet_info(src_if, src_if)
147 payload = self.info_to_payload(info)
148 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
149 IP(src=tunnel_src, dst=tunnel_dst) /
151 Ether(dst=RandMAC('*:*:*:*:*:*'),
152 src=RandMAC('*:*:*:*:*:*')) /
153 IP(src=scapy.compat.raw(RandIP()),
154 dst=scapy.compat.raw(RandIP())) /
155 UDP(sport=1234, dport=1234) /
161 def create_tunnel_stream_vlano4(self, src_if,
162 tunnel_src, tunnel_dst, vlan):
164 for i in range(0, 257):
165 info = self.create_packet_info(src_if, src_if)
166 payload = self.info_to_payload(info)
167 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
168 IP(src=tunnel_src, dst=tunnel_dst) /
170 Ether(dst=RandMAC('*:*:*:*:*:*'),
171 src=RandMAC('*:*:*:*:*:*')) /
173 IP(src=scapy.compat.raw(RandIP()),
174 dst=scapy.compat.raw(RandIP())) /
175 UDP(sport=1234, dport=1234) /
181 def verify_tunneled_4o4(self, src_if, capture, sent,
182 tunnel_src, tunnel_dst):
184 self.assertEqual(len(capture), len(sent))
186 for i in range(len(capture)):
194 self.assertEqual(rx_ip.src, tunnel_src)
195 self.assertEqual(rx_ip.dst, tunnel_dst)
200 self.assertEqual(rx_ip.src, tx_ip.src)
201 self.assertEqual(rx_ip.dst, tx_ip.dst)
202 # IP processing post pop has decremented the TTL
203 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
206 self.logger.error(ppp("Rx:", rx))
207 self.logger.error(ppp("Tx:", tx))
210 def verify_tunneled_6o6(self, src_if, capture, sent,
211 tunnel_src, tunnel_dst):
213 self.assertEqual(len(capture), len(sent))
215 for i in range(len(capture)):
223 self.assertEqual(rx_ip.src, tunnel_src)
224 self.assertEqual(rx_ip.dst, tunnel_dst)
226 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
229 self.assertEqual(rx_ip.src, tx_ip.src)
230 self.assertEqual(rx_ip.dst, tx_ip.dst)
233 self.logger.error(ppp("Rx:", rx))
234 self.logger.error(ppp("Tx:", tx))
237 def verify_tunneled_4o6(self, src_if, capture, sent,
238 tunnel_src, tunnel_dst):
240 self.assertEqual(len(capture), len(sent))
242 for i in range(len(capture)):
249 self.assertEqual(rx_ip.src, tunnel_src)
250 self.assertEqual(rx_ip.dst, tunnel_dst)
252 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
256 self.assertEqual(rx_ip.src, tx_ip.src)
257 self.assertEqual(rx_ip.dst, tx_ip.dst)
260 self.logger.error(ppp("Rx:", rx))
261 self.logger.error(ppp("Tx:", tx))
264 def verify_tunneled_6o4(self, src_if, capture, sent,
265 tunnel_src, tunnel_dst):
267 self.assertEqual(len(capture), len(sent))
269 for i in range(len(capture)):
276 self.assertEqual(rx_ip.src, tunnel_src)
277 self.assertEqual(rx_ip.dst, tunnel_dst)
279 rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload))
283 self.assertEqual(rx_ip.src, tx_ip.src)
284 self.assertEqual(rx_ip.dst, tx_ip.dst)
287 self.logger.error(ppp("Rx:", rx))
288 self.logger.error(ppp("Tx:", tx))
291 def verify_tunneled_l2o4(self, src_if, capture, sent,
292 tunnel_src, tunnel_dst):
293 self.assertEqual(len(capture), len(sent))
295 for i in range(len(capture)):
303 self.assertEqual(rx_ip.src, tunnel_src)
304 self.assertEqual(rx_ip.dst, tunnel_dst)
307 rx_l2 = rx_gre[Ether]
310 tx_l2 = tx_gre[Ether]
313 self.assertEqual(rx_ip.src, tx_ip.src)
314 self.assertEqual(rx_ip.dst, tx_ip.dst)
315 # bridged, not L3 forwarded, so no TTL decrement
316 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
319 self.logger.error(ppp("Rx:", rx))
320 self.logger.error(ppp("Tx:", tx))
323 def verify_tunneled_vlano4(self, src_if, capture, sent,
324 tunnel_src, tunnel_dst, vlan):
326 self.assertEqual(len(capture), len(sent))
328 ppc("Unexpected packets captured:", capture)
331 for i in range(len(capture)):
339 self.assertEqual(rx_ip.src, tunnel_src)
340 self.assertEqual(rx_ip.dst, tunnel_dst)
343 rx_l2 = rx_gre[Ether]
344 rx_vlan = rx_l2[Dot1Q]
347 self.assertEqual(rx_vlan.vlan, vlan)
350 tx_l2 = tx_gre[Ether]
353 self.assertEqual(rx_ip.src, tx_ip.src)
354 self.assertEqual(rx_ip.dst, tx_ip.dst)
355 # bridged, not L3 forwarded, so no TTL decrement
356 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
359 self.logger.error(ppp("Rx:", rx))
360 self.logger.error(ppp("Tx:", tx))
363 def verify_decapped_4o4(self, src_if, capture, sent):
364 self.assertEqual(len(capture), len(sent))
366 for i in range(len(capture)):
376 self.assertEqual(rx_ip.src, tx_ip.src)
377 self.assertEqual(rx_ip.dst, tx_ip.dst)
378 # IP processing post pop has decremented the TTL
379 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
382 self.logger.error(ppp("Rx:", rx))
383 self.logger.error(ppp("Tx:", tx))
386 def verify_decapped_6o4(self, src_if, capture, sent):
387 self.assertEqual(len(capture), len(sent))
389 for i in range(len(capture)):
399 self.assertEqual(rx_ip.src, tx_ip.src)
400 self.assertEqual(rx_ip.dst, tx_ip.dst)
401 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
404 self.logger.error(ppp("Rx:", rx))
405 self.logger.error(ppp("Tx:", tx))
409 """ GRE IPv4 tunnel Tests """
412 # Create an L3 GRE tunnel.
414 # - assign an IP Addres
415 # - Add a route via the tunnel
417 gre_if = VppGreInterface(self,
420 gre_if.add_vpp_config()
423 # The double create (create the same tunnel twice) should fail,
424 # and we should still be able to use the original
427 gre_if.add_vpp_config()
431 self.fail("Double GRE tunnel add does not fail")
436 route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
437 [VppRoutePath("0.0.0.0",
438 gre_if.sw_if_index)])
440 route_via_tun.add_vpp_config()
443 # Send a packet stream that is routed into the tunnel
444 # - they are all dropped since the tunnel's destintation IP
445 # is unresolved - or resolves via the default route - which
448 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
450 self.send_and_assert_no_replies(self.pg0, tx)
453 # Add a route that resolves the tunnel's destination
455 route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
456 [VppRoutePath(self.pg0.remote_ip4,
457 self.pg0.sw_if_index)])
458 route_tun_dst.add_vpp_config()
461 # Send a packet stream that is routed into the tunnel
462 # - packets are GRE encapped
464 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
465 rx = self.send_and_expect(self.pg0, tx, self.pg0)
466 self.verify_tunneled_4o4(self.pg0, rx, tx,
467 self.pg0.local_ip4, "1.1.1.2")
470 # Send tunneled packets that match the created tunnel and
471 # are decapped and forwarded
473 tx = self.create_tunnel_stream_4o4(self.pg0,
478 rx = self.send_and_expect(self.pg0, tx, self.pg0)
479 self.verify_decapped_4o4(self.pg0, rx, tx)
482 # Send tunneled packets that do not match the tunnel's src
484 self.vapi.cli("clear trace")
485 tx = self.create_tunnel_stream_4o4(self.pg0,
490 self.send_and_assert_no_replies(
492 remark="GRE packets forwarded despite no SRC address match")
495 # Configure IPv6 on the PG interface so we can route IPv6
498 self.pg0.config_ip6()
499 self.pg0.resolve_ndp()
502 # Send IPv6 tunnel encapslated packets
503 # - dropped since IPv6 is not enabled on the tunnel
505 tx = self.create_tunnel_stream_6o4(self.pg0,
510 self.send_and_assert_no_replies(self.pg0, tx,
511 "IPv6 GRE packets forwarded "
512 "despite IPv6 not enabled on tunnel")
515 # Enable IPv6 on the tunnel
520 # Send IPv6 tunnel encapslated packets
521 # - forwarded since IPv6 is enabled on the tunnel
523 tx = self.create_tunnel_stream_6o4(self.pg0,
528 rx = self.send_and_expect(self.pg0, tx, self.pg0)
529 self.verify_decapped_6o4(self.pg0, rx, tx)
532 # Send v6 packets for v4 encap
534 route6_via_tun = VppIpRoute(
535 self, "2001::1", 128,
538 proto=DpoProto.DPO_PROTO_IP6)],
540 route6_via_tun.add_vpp_config()
542 tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
543 rx = self.send_and_expect(self.pg0, tx, self.pg0)
545 self.verify_tunneled_6o4(self.pg0, rx, tx,
546 self.pg0.local_ip4, "1.1.1.2")
551 route_tun_dst.remove_vpp_config()
552 route_via_tun.remove_vpp_config()
553 route6_via_tun.remove_vpp_config()
554 gre_if.remove_vpp_config()
556 self.pg0.unconfig_ip6()
559 """ GRE IPv6 tunnel Tests """
561 self.pg1.config_ip6()
562 self.pg1.resolve_ndp()
565 # Create an L3 GRE tunnel.
567 # - assign an IP Address
568 # - Add a route via the tunnel
570 gre_if = VppGre6Interface(self,
573 gre_if.add_vpp_config()
577 route_via_tun = VppIpRoute(
578 self, "4004::1", 128,
579 [VppRoutePath("0::0",
581 proto=DpoProto.DPO_PROTO_IP6)],
584 route_via_tun.add_vpp_config()
587 # Send a packet stream that is routed into the tunnel
588 # - they are all dropped since the tunnel's destintation IP
589 # is unresolved - or resolves via the default route - which
592 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
593 self.send_and_assert_no_replies(
595 "GRE packets forwarded without DIP resolved")
598 # Add a route that resolves the tunnel's destination
600 route_tun_dst = VppIpRoute(
601 self, "1002::1", 128,
602 [VppRoutePath(self.pg2.remote_ip6,
603 self.pg2.sw_if_index,
604 proto=DpoProto.DPO_PROTO_IP6)],
606 route_tun_dst.add_vpp_config()
609 # Send a packet stream that is routed into the tunnel
610 # - packets are GRE encapped
612 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
613 rx = self.send_and_expect(self.pg2, tx, self.pg2)
614 self.verify_tunneled_6o6(self.pg2, rx, tx,
615 self.pg2.local_ip6, "1002::1")
618 # Test decap. decapped packets go out pg1
620 tx = self.create_tunnel_stream_6o6(self.pg2,
625 rx = self.send_and_expect(self.pg2, tx, self.pg1)
628 # RX'd packet is UDP over IPv6, test the GRE header is gone.
630 self.assertFalse(rx[0].haslayer(GRE))
631 self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
636 route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
637 [VppRoutePath("0.0.0.0",
638 gre_if.sw_if_index)])
639 route4_via_tun.add_vpp_config()
641 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
642 rx = self.send_and_expect(self.pg0, tx, self.pg2)
644 self.verify_tunneled_4o6(self.pg0, rx, tx,
645 self.pg2.local_ip6, "1002::1")
650 route_tun_dst.remove_vpp_config()
651 route_via_tun.remove_vpp_config()
652 route4_via_tun.remove_vpp_config()
653 gre_if.remove_vpp_config()
655 self.pg2.unconfig_ip6()
656 self.pg1.unconfig_ip6()
658 def test_gre_vrf(self):
659 """ GRE tunnel VRF Tests """
662 # Create an L3 GRE tunnel whose destination is in the non-default
663 # table. The underlay is thus non-default - the overlay is still
666 # - assign an IP Addres
668 gre_if = VppGreInterface(self, self.pg1.local_ip4,
671 gre_if.add_vpp_config()
676 # Add a route via the tunnel - in the overlay
678 route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
679 [VppRoutePath("0.0.0.0",
680 gre_if.sw_if_index)])
681 route_via_tun.add_vpp_config()
684 # Add a route that resolves the tunnel's destination - in the
687 route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
688 paths=[VppRoutePath(self.pg1.remote_ip4,
689 self.pg1.sw_if_index)])
690 route_tun_dst.add_vpp_config()
693 # Send a packet stream that is routed into the tunnel
694 # packets are sent in on pg0 which is in the default table
695 # - packets are GRE encapped
697 self.vapi.cli("clear trace")
698 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
699 rx = self.send_and_expect(self.pg0, tx, self.pg1)
700 self.verify_tunneled_4o4(self.pg1, rx, tx,
701 self.pg1.local_ip4, "2.2.2.2")
704 # Send tunneled packets that match the created tunnel and
705 # are decapped and forwarded. This tests the decap lookup
706 # does not happen in the encap table
708 self.vapi.cli("clear trace")
709 tx = self.create_tunnel_stream_4o4(self.pg1,
714 rx = self.send_and_expect(self.pg1, tx, self.pg0)
715 self.verify_decapped_4o4(self.pg0, rx, tx)
718 # Send tunneled packets that match the created tunnel
719 # but arrive on an interface that is not in the tunnel's
720 # encap VRF, these are dropped.
721 # IP enable the interface so they aren't dropped due to
722 # IP not being enabled.
724 self.pg2.config_ip4()
725 self.vapi.cli("clear trace")
726 tx = self.create_tunnel_stream_4o4(self.pg2,
731 rx = self.send_and_assert_no_replies(
733 "GRE decap packets in wrong VRF")
735 self.pg2.unconfig_ip4()
740 route_tun_dst.remove_vpp_config()
741 route_via_tun.remove_vpp_config()
742 gre_if.remove_vpp_config()
744 def test_gre_l2(self):
745 """ GRE tunnel L2 Tests """
748 # Add routes to resolve the tunnel destinations
750 route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
751 [VppRoutePath(self.pg0.remote_ip4,
752 self.pg0.sw_if_index)])
753 route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
754 [VppRoutePath(self.pg0.remote_ip4,
755 self.pg0.sw_if_index)])
757 route_tun1_dst.add_vpp_config()
758 route_tun2_dst.add_vpp_config()
761 # Create 2 L2 GRE tunnels and x-connect them
763 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
765 type=GreTunnelTypes.TT_TEB)
766 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
768 type=GreTunnelTypes.TT_TEB)
769 gre_if1.add_vpp_config()
770 gre_if2.add_vpp_config()
775 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
778 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
783 # Send in tunnel encapped L2. expect out tunnel encapped L2
786 tx = self.create_tunnel_stream_l2o4(self.pg0,
789 rx = self.send_and_expect(self.pg0, tx, self.pg0)
790 self.verify_tunneled_l2o4(self.pg0, rx, tx,
794 tx = self.create_tunnel_stream_l2o4(self.pg0,
797 rx = self.send_and_expect(self.pg0, tx, self.pg0)
798 self.verify_tunneled_l2o4(self.pg0, rx, tx,
802 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
805 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
810 # Create a VLAN sub-interfaces on the GRE TEB interfaces
811 # then x-connect them
813 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
814 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
816 # gre_if_11.add_vpp_config()
817 # gre_if_12.add_vpp_config()
822 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
823 gre_if_12.sw_if_index,
825 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
826 gre_if_11.sw_if_index,
830 # Configure both to pop thier respective VLAN tags,
831 # so that during the x-coonect they will subsequently push
833 self.vapi.l2_interface_vlan_tag_rewrite(
834 sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
836 self.vapi.l2_interface_vlan_tag_rewrite(
837 sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
841 # Send traffic in both directiond - expect the VLAN tags to
844 tx = self.create_tunnel_stream_vlano4(self.pg0,
848 rx = self.send_and_expect(self.pg0, tx, self.pg0)
849 self.verify_tunneled_vlano4(self.pg0, rx, tx,
854 tx = self.create_tunnel_stream_vlano4(self.pg0,
858 rx = self.send_and_expect(self.pg0, tx, self.pg0)
859 self.verify_tunneled_vlano4(self.pg0, rx, tx,
865 # Cleanup Test resources
867 gre_if_11.remove_vpp_config()
868 gre_if_12.remove_vpp_config()
869 gre_if1.remove_vpp_config()
870 gre_if2.remove_vpp_config()
871 route_tun1_dst.add_vpp_config()
872 route_tun2_dst.add_vpp_config()
874 def test_gre_loop(self):
875 """ GRE tunnel loop Tests """
878 # Create an L3 GRE tunnel.
880 # - assign an IP Addres
882 gre_if = VppGreInterface(self,
885 gre_if.add_vpp_config()
890 # add a route to the tunnel's destination that points
891 # through the tunnel, hence forming a loop in the forwarding
894 route_dst = VppIpRoute(self, "1.1.1.2", 32,
895 [VppRoutePath("0.0.0.0",
896 gre_if.sw_if_index)])
897 route_dst.add_vpp_config()
900 # packets to the tunnels destination should be dropped
902 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
903 self.send_and_assert_no_replies(self.pg2, tx)
905 self.logger.info(self.vapi.ppcli("sh adj 7"))
910 route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
911 self.pg1.sw_if_index)])
912 route_dst.add_vpp_config()
914 rx = self.send_and_expect(self.pg0, tx, self.pg1)
917 # a good route throught the tunnel to check it restacked
919 route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
920 [VppRoutePath("0.0.0.0",
921 gre_if.sw_if_index)])
922 route_via_tun_2.add_vpp_config()
924 tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
925 rx = self.send_and_expect(self.pg0, tx, self.pg1)
926 self.verify_tunneled_4o4(self.pg1, rx, tx,
927 self.pg0.local_ip4, "1.1.1.2")
932 route_via_tun_2.remove_vpp_config()
933 gre_if.remove_vpp_config()
936 if __name__ == '__main__':
937 unittest.main(testRunner=VppTestRunner)