6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppDot1QSubint
8 from vpp_gre_interface import VppGreInterface, VppGre6Interface
9 from vpp_ip import DpoProto
10 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
11 from vpp_papi_provider import L2_VTR_OP
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether, Dot1Q, GRE
15 from scapy.layers.inet import IP, UDP
16 from scapy.layers.inet6 import IPv6
17 from scapy.volatile import RandMAC, RandIP
19 from util import ppp, ppc
28 class TestGRE(VppTestCase):
33 super(TestGRE, cls).setUpClass()
36 super(TestGRE, self).setUp()
38 # create 3 pg interfaces - set one in a non-default table.
39 self.create_pg_interfaces(range(3))
41 self.tbl = VppIpTable(self, 1)
42 self.tbl.add_vpp_config()
43 self.pg1.set_table_ip4(1)
45 for i in self.pg_interfaces:
49 self.pg0.resolve_arp()
51 self.pg1.resolve_arp()
53 self.pg2.resolve_ndp()
56 for i in self.pg_interfaces:
60 self.pg1.set_table_ip4(0)
61 super(TestGRE, self).tearDown()
63 def create_stream_ip4(self, src_if, src_ip, dst_ip):
65 for i in range(0, 257):
66 info = self.create_packet_info(src_if, src_if)
67 payload = self.info_to_payload(info)
68 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
69 IP(src=src_ip, dst=dst_ip) /
70 UDP(sport=1234, dport=1234) /
76 def create_stream_ip6(self, src_if, src_ip, dst_ip):
78 for i in range(0, 257):
79 info = self.create_packet_info(src_if, src_if)
80 payload = self.info_to_payload(info)
81 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
82 IPv6(src=src_ip, dst=dst_ip) /
83 UDP(sport=1234, dport=1234) /
89 def create_tunnel_stream_4o4(self, src_if,
90 tunnel_src, tunnel_dst,
93 for i in range(0, 257):
94 info = self.create_packet_info(src_if, src_if)
95 payload = self.info_to_payload(info)
96 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
97 IP(src=tunnel_src, dst=tunnel_dst) /
99 IP(src=src_ip, dst=dst_ip) /
100 UDP(sport=1234, dport=1234) /
106 def create_tunnel_stream_6o4(self, src_if,
107 tunnel_src, tunnel_dst,
110 for i in range(0, 257):
111 info = self.create_packet_info(src_if, src_if)
112 payload = self.info_to_payload(info)
113 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
114 IP(src=tunnel_src, dst=tunnel_dst) /
116 IPv6(src=src_ip, dst=dst_ip) /
117 UDP(sport=1234, dport=1234) /
123 def create_tunnel_stream_6o6(self, src_if,
124 tunnel_src, tunnel_dst,
127 for i in range(0, 257):
128 info = self.create_packet_info(src_if, src_if)
129 payload = self.info_to_payload(info)
130 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
131 IPv6(src=tunnel_src, dst=tunnel_dst) /
133 IPv6(src=src_ip, dst=dst_ip) /
134 UDP(sport=1234, dport=1234) /
140 def create_tunnel_stream_l2o4(self, src_if,
141 tunnel_src, tunnel_dst):
143 for i in range(0, 257):
144 info = self.create_packet_info(src_if, src_if)
145 payload = self.info_to_payload(info)
146 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
147 IP(src=tunnel_src, dst=tunnel_dst) /
149 Ether(dst=RandMAC('*:*:*:*:*:*'),
150 src=RandMAC('*:*:*:*:*:*')) /
151 IP(src=str(RandIP()), dst=str(RandIP())) /
152 UDP(sport=1234, dport=1234) /
158 def create_tunnel_stream_vlano4(self, src_if,
159 tunnel_src, tunnel_dst, vlan):
161 for i in range(0, 257):
162 info = self.create_packet_info(src_if, src_if)
163 payload = self.info_to_payload(info)
164 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
165 IP(src=tunnel_src, dst=tunnel_dst) /
167 Ether(dst=RandMAC('*:*:*:*:*:*'),
168 src=RandMAC('*:*:*:*:*:*')) /
170 IP(src=str(RandIP()), dst=str(RandIP())) /
171 UDP(sport=1234, dport=1234) /
177 def verify_tunneled_4o4(self, src_if, capture, sent,
178 tunnel_src, tunnel_dst):
180 self.assertEqual(len(capture), len(sent))
182 for i in range(len(capture)):
190 self.assertEqual(rx_ip.src, tunnel_src)
191 self.assertEqual(rx_ip.dst, tunnel_dst)
196 self.assertEqual(rx_ip.src, tx_ip.src)
197 self.assertEqual(rx_ip.dst, tx_ip.dst)
198 # IP processing post pop has decremented the TTL
199 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
202 self.logger.error(ppp("Rx:", rx))
203 self.logger.error(ppp("Tx:", tx))
206 def verify_tunneled_6o6(self, src_if, capture, sent,
207 tunnel_src, tunnel_dst):
209 self.assertEqual(len(capture), len(sent))
211 for i in range(len(capture)):
219 self.assertEqual(rx_ip.src, tunnel_src)
220 self.assertEqual(rx_ip.dst, tunnel_dst)
222 rx_gre = GRE(str(rx_ip[IPv6].payload))
225 self.assertEqual(rx_ip.src, tx_ip.src)
226 self.assertEqual(rx_ip.dst, tx_ip.dst)
229 self.logger.error(ppp("Rx:", rx))
230 self.logger.error(ppp("Tx:", tx))
233 def verify_tunneled_4o6(self, src_if, capture, sent,
234 tunnel_src, tunnel_dst):
236 self.assertEqual(len(capture), len(sent))
238 for i in range(len(capture)):
245 self.assertEqual(rx_ip.src, tunnel_src)
246 self.assertEqual(rx_ip.dst, tunnel_dst)
248 rx_gre = GRE(str(rx_ip[IPv6].payload))
252 self.assertEqual(rx_ip.src, tx_ip.src)
253 self.assertEqual(rx_ip.dst, tx_ip.dst)
256 self.logger.error(ppp("Rx:", rx))
257 self.logger.error(ppp("Tx:", tx))
260 def verify_tunneled_6o4(self, src_if, capture, sent,
261 tunnel_src, tunnel_dst):
263 self.assertEqual(len(capture), len(sent))
265 for i in range(len(capture)):
272 self.assertEqual(rx_ip.src, tunnel_src)
273 self.assertEqual(rx_ip.dst, tunnel_dst)
275 rx_gre = GRE(str(rx_ip[IP].payload))
279 self.assertEqual(rx_ip.src, tx_ip.src)
280 self.assertEqual(rx_ip.dst, tx_ip.dst)
283 self.logger.error(ppp("Rx:", rx))
284 self.logger.error(ppp("Tx:", tx))
287 def verify_tunneled_l2o4(self, src_if, capture, sent,
288 tunnel_src, tunnel_dst):
289 self.assertEqual(len(capture), len(sent))
291 for i in range(len(capture)):
299 self.assertEqual(rx_ip.src, tunnel_src)
300 self.assertEqual(rx_ip.dst, tunnel_dst)
303 rx_l2 = rx_gre[Ether]
306 tx_l2 = tx_gre[Ether]
309 self.assertEqual(rx_ip.src, tx_ip.src)
310 self.assertEqual(rx_ip.dst, tx_ip.dst)
311 # bridged, not L3 forwarded, so no TTL decrement
312 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
315 self.logger.error(ppp("Rx:", rx))
316 self.logger.error(ppp("Tx:", tx))
319 def verify_tunneled_vlano4(self, src_if, capture, sent,
320 tunnel_src, tunnel_dst, vlan):
322 self.assertEqual(len(capture), len(sent))
324 ppc("Unexpected packets captured:", capture)
327 for i in range(len(capture)):
335 self.assertEqual(rx_ip.src, tunnel_src)
336 self.assertEqual(rx_ip.dst, tunnel_dst)
339 rx_l2 = rx_gre[Ether]
340 rx_vlan = rx_l2[Dot1Q]
343 self.assertEqual(rx_vlan.vlan, vlan)
346 tx_l2 = tx_gre[Ether]
349 self.assertEqual(rx_ip.src, tx_ip.src)
350 self.assertEqual(rx_ip.dst, tx_ip.dst)
351 # bridged, not L3 forwarded, so no TTL decrement
352 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
355 self.logger.error(ppp("Rx:", rx))
356 self.logger.error(ppp("Tx:", tx))
359 def verify_decapped_4o4(self, src_if, capture, sent):
360 self.assertEqual(len(capture), len(sent))
362 for i in range(len(capture)):
372 self.assertEqual(rx_ip.src, tx_ip.src)
373 self.assertEqual(rx_ip.dst, tx_ip.dst)
374 # IP processing post pop has decremented the TTL
375 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
378 self.logger.error(ppp("Rx:", rx))
379 self.logger.error(ppp("Tx:", tx))
382 def verify_decapped_6o4(self, src_if, capture, sent):
383 self.assertEqual(len(capture), len(sent))
385 for i in range(len(capture)):
395 self.assertEqual(rx_ip.src, tx_ip.src)
396 self.assertEqual(rx_ip.dst, tx_ip.dst)
397 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
400 self.logger.error(ppp("Rx:", rx))
401 self.logger.error(ppp("Tx:", tx))
405 """ GRE IPv4 tunnel Tests """
408 # Create an L3 GRE tunnel.
410 # - assign an IP Addres
411 # - Add a route via the tunnel
413 gre_if = VppGreInterface(self,
416 gre_if.add_vpp_config()
419 # The double create (create the same tunnel twice) should fail,
420 # and we should still be able to use the original
423 gre_if.add_vpp_config()
427 self.fail("Double GRE tunnel add does not fail")
432 route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
433 [VppRoutePath("0.0.0.0",
434 gre_if.sw_if_index)])
436 route_via_tun.add_vpp_config()
439 # Send a packet stream that is routed into the tunnel
440 # - they are all dropped since the tunnel's desintation IP
441 # is unresolved - or resolves via the default route - which
444 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
445 self.pg0.add_stream(tx)
447 self.pg_enable_capture(self.pg_interfaces)
450 self.pg0.assert_nothing_captured(
451 remark="GRE packets forwarded without DIP resolved")
454 # Add a route that resolves the tunnel's destination
456 route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
457 [VppRoutePath(self.pg0.remote_ip4,
458 self.pg0.sw_if_index)])
459 route_tun_dst.add_vpp_config()
462 # Send a packet stream that is routed into the tunnel
463 # - packets are GRE encapped
465 self.vapi.cli("clear trace")
466 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
467 self.pg0.add_stream(tx)
469 self.pg_enable_capture(self.pg_interfaces)
472 rx = self.pg0.get_capture(len(tx))
473 self.verify_tunneled_4o4(self.pg0, rx, tx,
474 self.pg0.local_ip4, "1.1.1.2")
477 # Send tunneled packets that match the created tunnel and
478 # are decapped and forwarded
480 self.vapi.cli("clear trace")
481 tx = self.create_tunnel_stream_4o4(self.pg0,
486 self.pg0.add_stream(tx)
488 self.pg_enable_capture(self.pg_interfaces)
491 rx = self.pg0.get_capture(len(tx))
492 self.verify_decapped_4o4(self.pg0, rx, tx)
495 # Send tunneled packets that do not match the tunnel's src
497 self.vapi.cli("clear trace")
498 tx = self.create_tunnel_stream_4o4(self.pg0,
503 self.pg0.add_stream(tx)
505 self.pg_enable_capture(self.pg_interfaces)
508 self.pg0.assert_nothing_captured(
509 remark="GRE packets forwarded despite no SRC address match")
512 # Configure IPv6 on the PG interface so we can route IPv6
515 self.pg0.config_ip6()
516 self.pg0.resolve_ndp()
519 # Send IPv6 tunnel encapslated packets
520 # - dropped since IPv6 is not enabled on the tunnel
522 self.vapi.cli("clear trace")
523 tx = self.create_tunnel_stream_6o4(self.pg0,
528 self.pg0.add_stream(tx)
530 self.pg_enable_capture(self.pg_interfaces)
533 self.pg0.assert_nothing_captured(remark="IPv6 GRE packets forwarded "
534 "despite IPv6 not enabled on tunnel")
537 # Enable IPv6 on the tunnel
542 # Send IPv6 tunnel encapslated packets
543 # - forwarded since IPv6 is enabled on the tunnel
545 self.vapi.cli("clear trace")
546 tx = self.create_tunnel_stream_6o4(self.pg0,
551 self.pg0.add_stream(tx)
553 self.pg_enable_capture(self.pg_interfaces)
556 rx = self.pg0.get_capture(len(tx))
557 self.verify_decapped_6o4(self.pg0, rx, tx)
560 # Send v6 packets for v4 encap
562 route6_via_tun = VppIpRoute(
563 self, "2001::1", 128,
566 proto=DpoProto.DPO_PROTO_IP6)],
568 route6_via_tun.add_vpp_config()
570 tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
571 rx = self.send_and_expect(self.pg0, tx, self.pg0)
573 self.verify_tunneled_6o4(self.pg0, rx, tx,
574 self.pg0.local_ip4, "1.1.1.2")
579 route_tun_dst.remove_vpp_config()
580 route_via_tun.remove_vpp_config()
581 route6_via_tun.remove_vpp_config()
582 gre_if.remove_vpp_config()
584 self.pg0.unconfig_ip6()
587 """ GRE IPv6 tunnel Tests """
589 self.pg1.config_ip6()
590 self.pg1.resolve_ndp()
593 # Create an L3 GRE tunnel.
595 # - assign an IP Address
596 # - Add a route via the tunnel
598 gre_if = VppGre6Interface(self,
601 gre_if.add_vpp_config()
605 route_via_tun = VppIpRoute(
606 self, "4004::1", 128,
607 [VppRoutePath("0::0",
609 proto=DpoProto.DPO_PROTO_IP6)],
612 route_via_tun.add_vpp_config()
615 # Send a packet stream that is routed into the tunnel
616 # - they are all dropped since the tunnel's desintation IP
617 # is unresolved - or resolves via the default route - which
620 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
621 self.pg2.add_stream(tx)
623 self.pg_enable_capture(self.pg_interfaces)
626 self.pg2.assert_nothing_captured(
627 remark="GRE packets forwarded without DIP resolved")
630 # Add a route that resolves the tunnel's destination
632 route_tun_dst = VppIpRoute(
633 self, "1002::1", 128,
634 [VppRoutePath(self.pg2.remote_ip6,
635 self.pg2.sw_if_index,
636 proto=DpoProto.DPO_PROTO_IP6)],
638 route_tun_dst.add_vpp_config()
641 # Send a packet stream that is routed into the tunnel
642 # - packets are GRE encapped
644 self.vapi.cli("clear trace")
645 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
646 self.pg2.add_stream(tx)
648 self.pg_enable_capture(self.pg_interfaces)
651 rx = self.pg2.get_capture(len(tx))
652 self.verify_tunneled_6o6(self.pg2, rx, tx,
653 self.pg2.local_ip6, "1002::1")
656 # Test decap. decapped packets go out pg1
658 tx = self.create_tunnel_stream_6o6(self.pg2,
663 self.vapi.cli("clear trace")
664 self.pg2.add_stream(tx)
666 self.pg_enable_capture(self.pg_interfaces)
668 rx = self.pg1.get_capture(len(tx))
671 # RX'd packet is UDP over IPv6, test the GRE header is gone.
673 self.assertFalse(rx[0].haslayer(GRE))
674 self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
679 route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
680 [VppRoutePath("0.0.0.0",
681 gre_if.sw_if_index)])
682 route4_via_tun.add_vpp_config()
684 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
685 rx = self.send_and_expect(self.pg0, tx, self.pg2)
687 self.verify_tunneled_4o6(self.pg0, rx, tx,
688 self.pg2.local_ip6, "1002::1")
693 route_tun_dst.remove_vpp_config()
694 route_via_tun.remove_vpp_config()
695 route4_via_tun.remove_vpp_config()
696 gre_if.remove_vpp_config()
698 self.pg2.unconfig_ip6()
699 self.pg1.unconfig_ip6()
701 def test_gre_vrf(self):
702 """ GRE tunnel VRF Tests """
705 # Create an L3 GRE tunnel whose destination is in the non-default
706 # table. The underlay is thus non-default - the overlay is still
709 # - assign an IP Addres
711 gre_if = VppGreInterface(self, self.pg1.local_ip4,
714 gre_if.add_vpp_config()
719 # Add a route via the tunnel - in the overlay
721 route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
722 [VppRoutePath("0.0.0.0",
723 gre_if.sw_if_index)])
724 route_via_tun.add_vpp_config()
727 # Add a route that resolves the tunnel's destination - in the
730 route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
731 paths=[VppRoutePath(self.pg1.remote_ip4,
732 self.pg1.sw_if_index)])
733 route_tun_dst.add_vpp_config()
736 # Send a packet stream that is routed into the tunnel
737 # packets are sent in on pg0 which is in the default table
738 # - packets are GRE encapped
740 self.vapi.cli("clear trace")
741 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
742 self.pg0.add_stream(tx)
744 self.pg_enable_capture(self.pg_interfaces)
747 rx = self.pg1.get_capture(len(tx))
748 self.verify_tunneled_4o4(self.pg1, rx, tx,
749 self.pg1.local_ip4, "2.2.2.2")
752 # Send tunneled packets that match the created tunnel and
753 # are decapped and forwarded. This tests the decap lookup
754 # does not happen in the encap table
756 self.vapi.cli("clear trace")
757 tx = self.create_tunnel_stream_4o4(self.pg1,
762 self.pg1.add_stream(tx)
764 self.pg_enable_capture(self.pg_interfaces)
767 rx = self.pg0.get_capture(len(tx))
768 self.verify_decapped_4o4(self.pg0, rx, tx)
771 # Send tunneled packets that match the created tunnel and
772 # but arrive on an interface that is not in the tunnel's
773 # encap VRF, these are dropped
775 self.vapi.cli("clear trace")
776 tx = self.create_tunnel_stream_4o4(self.pg2,
781 self.pg1.add_stream(tx)
783 self.pg_enable_capture(self.pg_interfaces)
786 self.pg0.assert_nothing_captured(
787 remark="GRE decap packets in wrong VRF")
792 route_tun_dst.remove_vpp_config()
793 route_via_tun.remove_vpp_config()
794 gre_if.remove_vpp_config()
796 def test_gre_l2(self):
797 """ GRE tunnel L2 Tests """
800 # Add routes to resolve the tunnel destinations
802 route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
803 [VppRoutePath(self.pg0.remote_ip4,
804 self.pg0.sw_if_index)])
805 route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
806 [VppRoutePath(self.pg0.remote_ip4,
807 self.pg0.sw_if_index)])
809 route_tun1_dst.add_vpp_config()
810 route_tun2_dst.add_vpp_config()
813 # Create 2 L2 GRE tunnels and x-connect them
815 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
817 type=GreTunnelTypes.TT_TEB)
818 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
820 type=GreTunnelTypes.TT_TEB)
821 gre_if1.add_vpp_config()
822 gre_if2.add_vpp_config()
827 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
830 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
835 # Send in tunnel encapped L2. expect out tunnel encapped L2
838 self.vapi.cli("clear trace")
839 tx = self.create_tunnel_stream_l2o4(self.pg0,
842 self.pg0.add_stream(tx)
844 self.pg_enable_capture(self.pg_interfaces)
847 rx = self.pg0.get_capture(len(tx))
848 self.verify_tunneled_l2o4(self.pg0, rx, tx,
852 self.vapi.cli("clear trace")
853 tx = self.create_tunnel_stream_l2o4(self.pg0,
856 self.pg0.add_stream(tx)
858 self.pg_enable_capture(self.pg_interfaces)
861 rx = self.pg0.get_capture(len(tx))
862 self.verify_tunneled_l2o4(self.pg0, rx, tx,
866 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
869 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
874 # Create a VLAN sub-interfaces on the GRE TEB interfaces
875 # then x-connect them
877 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
878 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
880 # gre_if_11.add_vpp_config()
881 # gre_if_12.add_vpp_config()
886 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
887 gre_if_12.sw_if_index,
889 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
890 gre_if_11.sw_if_index,
894 # Configure both to pop thier respective VLAN tags,
895 # so that during the x-coonect they will subsequently push
897 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
900 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
905 # Send traffic in both directiond - expect the VLAN tags to
908 self.vapi.cli("clear trace")
909 tx = self.create_tunnel_stream_vlano4(self.pg0,
913 self.pg0.add_stream(tx)
915 self.pg_enable_capture(self.pg_interfaces)
918 rx = self.pg0.get_capture(len(tx))
919 self.verify_tunneled_vlano4(self.pg0, rx, tx,
924 self.vapi.cli("clear trace")
925 tx = self.create_tunnel_stream_vlano4(self.pg0,
929 self.pg0.add_stream(tx)
931 self.pg_enable_capture(self.pg_interfaces)
934 rx = self.pg0.get_capture(len(tx))
935 self.verify_tunneled_vlano4(self.pg0, rx, tx,
941 # Cleanup Test resources
943 gre_if_11.remove_vpp_config()
944 gre_if_12.remove_vpp_config()
945 gre_if1.remove_vpp_config()
946 gre_if2.remove_vpp_config()
947 route_tun1_dst.add_vpp_config()
948 route_tun2_dst.add_vpp_config()
951 if __name__ == '__main__':
952 unittest.main(testRunner=VppTestRunner)