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 super(TestGRE, self).setUp()
36 # create 3 pg interfaces - set one in a non-default table.
37 self.create_pg_interfaces(range(3))
39 self.tbl = VppIpTable(self, 1)
40 self.tbl.add_vpp_config()
41 self.pg1.set_table_ip4(1)
43 for i in self.pg_interfaces:
47 self.pg0.resolve_arp()
49 self.pg1.resolve_arp()
51 self.pg2.resolve_ndp()
54 for i in self.pg_interfaces:
58 self.pg1.set_table_ip4(0)
59 super(TestGRE, self).tearDown()
61 def create_stream_ip4(self, src_if, src_ip, dst_ip):
63 for i in range(0, 257):
64 info = self.create_packet_info(src_if, src_if)
65 payload = self.info_to_payload(info)
66 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
67 IP(src=src_ip, dst=dst_ip) /
68 UDP(sport=1234, dport=1234) /
74 def create_stream_ip6(self, src_if, src_ip, dst_ip):
76 for i in range(0, 257):
77 info = self.create_packet_info(src_if, src_if)
78 payload = self.info_to_payload(info)
79 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
80 IPv6(src=src_ip, dst=dst_ip) /
81 UDP(sport=1234, dport=1234) /
87 def create_tunnel_stream_4o4(self, src_if,
88 tunnel_src, tunnel_dst,
91 for i in range(0, 257):
92 info = self.create_packet_info(src_if, src_if)
93 payload = self.info_to_payload(info)
94 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
95 IP(src=tunnel_src, dst=tunnel_dst) /
97 IP(src=src_ip, dst=dst_ip) /
98 UDP(sport=1234, dport=1234) /
104 def create_tunnel_stream_6o4(self, src_if,
105 tunnel_src, tunnel_dst,
108 for i in range(0, 257):
109 info = self.create_packet_info(src_if, src_if)
110 payload = self.info_to_payload(info)
111 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
112 IP(src=tunnel_src, dst=tunnel_dst) /
114 IPv6(src=src_ip, dst=dst_ip) /
115 UDP(sport=1234, dport=1234) /
121 def create_tunnel_stream_6o6(self, src_if,
122 tunnel_src, tunnel_dst,
125 for i in range(0, 257):
126 info = self.create_packet_info(src_if, src_if)
127 payload = self.info_to_payload(info)
128 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
129 IPv6(src=tunnel_src, dst=tunnel_dst) /
131 IPv6(src=src_ip, dst=dst_ip) /
132 UDP(sport=1234, dport=1234) /
138 def create_tunnel_stream_l2o4(self, src_if,
139 tunnel_src, tunnel_dst):
141 for i in range(0, 257):
142 info = self.create_packet_info(src_if, src_if)
143 payload = self.info_to_payload(info)
144 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
145 IP(src=tunnel_src, dst=tunnel_dst) /
147 Ether(dst=RandMAC('*:*:*:*:*:*'),
148 src=RandMAC('*:*:*:*:*:*')) /
149 IP(src=scapy.compat.raw(RandIP()),
150 dst=scapy.compat.raw(RandIP())) /
151 UDP(sport=1234, dport=1234) /
157 def create_tunnel_stream_vlano4(self, src_if,
158 tunnel_src, tunnel_dst, vlan):
160 for i in range(0, 257):
161 info = self.create_packet_info(src_if, src_if)
162 payload = self.info_to_payload(info)
163 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
164 IP(src=tunnel_src, dst=tunnel_dst) /
166 Ether(dst=RandMAC('*:*:*:*:*:*'),
167 src=RandMAC('*:*:*:*:*:*')) /
169 IP(src=scapy.compat.raw(RandIP()),
170 dst=scapy.compat.raw(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(scapy.compat.raw(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(scapy.compat.raw(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(scapy.compat.raw(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 destintation 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")
446 self.send_and_assert_no_replies(self.pg0, tx)
449 # Add a route that resolves the tunnel's destination
451 route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
452 [VppRoutePath(self.pg0.remote_ip4,
453 self.pg0.sw_if_index)])
454 route_tun_dst.add_vpp_config()
457 # Send a packet stream that is routed into the tunnel
458 # - packets are GRE encapped
460 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
461 rx = self.send_and_expect(self.pg0, tx, self.pg0)
462 self.verify_tunneled_4o4(self.pg0, rx, tx,
463 self.pg0.local_ip4, "1.1.1.2")
466 # Send tunneled packets that match the created tunnel and
467 # are decapped and forwarded
469 tx = self.create_tunnel_stream_4o4(self.pg0,
474 rx = self.send_and_expect(self.pg0, tx, self.pg0)
475 self.verify_decapped_4o4(self.pg0, rx, tx)
478 # Send tunneled packets that do not match the tunnel's src
480 self.vapi.cli("clear trace")
481 tx = self.create_tunnel_stream_4o4(self.pg0,
486 self.send_and_assert_no_replies(
488 remark="GRE packets forwarded despite no SRC address match")
491 # Configure IPv6 on the PG interface so we can route IPv6
494 self.pg0.config_ip6()
495 self.pg0.resolve_ndp()
498 # Send IPv6 tunnel encapslated packets
499 # - dropped since IPv6 is not enabled on the tunnel
501 tx = self.create_tunnel_stream_6o4(self.pg0,
506 self.send_and_assert_no_replies(self.pg0, tx,
507 "IPv6 GRE packets forwarded "
508 "despite IPv6 not enabled on tunnel")
511 # Enable IPv6 on the tunnel
516 # Send IPv6 tunnel encapslated packets
517 # - forwarded since IPv6 is enabled on the tunnel
519 tx = self.create_tunnel_stream_6o4(self.pg0,
524 rx = self.send_and_expect(self.pg0, tx, self.pg0)
525 self.verify_decapped_6o4(self.pg0, rx, tx)
528 # Send v6 packets for v4 encap
530 route6_via_tun = VppIpRoute(
531 self, "2001::1", 128,
534 proto=DpoProto.DPO_PROTO_IP6)],
536 route6_via_tun.add_vpp_config()
538 tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
539 rx = self.send_and_expect(self.pg0, tx, self.pg0)
541 self.verify_tunneled_6o4(self.pg0, rx, tx,
542 self.pg0.local_ip4, "1.1.1.2")
547 route_tun_dst.remove_vpp_config()
548 route_via_tun.remove_vpp_config()
549 route6_via_tun.remove_vpp_config()
550 gre_if.remove_vpp_config()
552 self.pg0.unconfig_ip6()
555 """ GRE IPv6 tunnel Tests """
557 self.pg1.config_ip6()
558 self.pg1.resolve_ndp()
561 # Create an L3 GRE tunnel.
563 # - assign an IP Address
564 # - Add a route via the tunnel
566 gre_if = VppGre6Interface(self,
569 gre_if.add_vpp_config()
573 route_via_tun = VppIpRoute(
574 self, "4004::1", 128,
575 [VppRoutePath("0::0",
577 proto=DpoProto.DPO_PROTO_IP6)],
580 route_via_tun.add_vpp_config()
583 # Send a packet stream that is routed into the tunnel
584 # - they are all dropped since the tunnel's destintation IP
585 # is unresolved - or resolves via the default route - which
588 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
589 self.send_and_assert_no_replies(
591 "GRE packets forwarded without DIP resolved")
594 # Add a route that resolves the tunnel's destination
596 route_tun_dst = VppIpRoute(
597 self, "1002::1", 128,
598 [VppRoutePath(self.pg2.remote_ip6,
599 self.pg2.sw_if_index,
600 proto=DpoProto.DPO_PROTO_IP6)],
602 route_tun_dst.add_vpp_config()
605 # Send a packet stream that is routed into the tunnel
606 # - packets are GRE encapped
608 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
609 rx = self.send_and_expect(self.pg2, tx, self.pg2)
610 self.verify_tunneled_6o6(self.pg2, rx, tx,
611 self.pg2.local_ip6, "1002::1")
614 # Test decap. decapped packets go out pg1
616 tx = self.create_tunnel_stream_6o6(self.pg2,
621 rx = self.send_and_expect(self.pg2, tx, self.pg1)
624 # RX'd packet is UDP over IPv6, test the GRE header is gone.
626 self.assertFalse(rx[0].haslayer(GRE))
627 self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
632 route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
633 [VppRoutePath("0.0.0.0",
634 gre_if.sw_if_index)])
635 route4_via_tun.add_vpp_config()
637 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
638 rx = self.send_and_expect(self.pg0, tx, self.pg2)
640 self.verify_tunneled_4o6(self.pg0, rx, tx,
641 self.pg2.local_ip6, "1002::1")
646 route_tun_dst.remove_vpp_config()
647 route_via_tun.remove_vpp_config()
648 route4_via_tun.remove_vpp_config()
649 gre_if.remove_vpp_config()
651 self.pg2.unconfig_ip6()
652 self.pg1.unconfig_ip6()
654 def test_gre_vrf(self):
655 """ GRE tunnel VRF Tests """
658 # Create an L3 GRE tunnel whose destination is in the non-default
659 # table. The underlay is thus non-default - the overlay is still
662 # - assign an IP Addres
664 gre_if = VppGreInterface(self, self.pg1.local_ip4,
667 gre_if.add_vpp_config()
672 # Add a route via the tunnel - in the overlay
674 route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
675 [VppRoutePath("0.0.0.0",
676 gre_if.sw_if_index)])
677 route_via_tun.add_vpp_config()
680 # Add a route that resolves the tunnel's destination - in the
683 route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
684 paths=[VppRoutePath(self.pg1.remote_ip4,
685 self.pg1.sw_if_index)])
686 route_tun_dst.add_vpp_config()
689 # Send a packet stream that is routed into the tunnel
690 # packets are sent in on pg0 which is in the default table
691 # - packets are GRE encapped
693 self.vapi.cli("clear trace")
694 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
695 rx = self.send_and_expect(self.pg0, tx, self.pg1)
696 self.verify_tunneled_4o4(self.pg1, rx, tx,
697 self.pg1.local_ip4, "2.2.2.2")
700 # Send tunneled packets that match the created tunnel and
701 # are decapped and forwarded. This tests the decap lookup
702 # does not happen in the encap table
704 self.vapi.cli("clear trace")
705 tx = self.create_tunnel_stream_4o4(self.pg1,
710 rx = self.send_and_expect(self.pg1, tx, self.pg0)
711 self.verify_decapped_4o4(self.pg0, rx, tx)
714 # Send tunneled packets that match the created tunnel
715 # but arrive on an interface that is not in the tunnel's
716 # encap VRF, these are dropped.
717 # IP enable the interface so they aren't dropped due to
718 # IP not being enabled.
720 self.pg2.config_ip4()
721 self.vapi.cli("clear trace")
722 tx = self.create_tunnel_stream_4o4(self.pg2,
727 rx = self.send_and_assert_no_replies(
729 "GRE decap packets in wrong VRF")
731 self.pg2.unconfig_ip4()
736 route_tun_dst.remove_vpp_config()
737 route_via_tun.remove_vpp_config()
738 gre_if.remove_vpp_config()
740 def test_gre_l2(self):
741 """ GRE tunnel L2 Tests """
744 # Add routes to resolve the tunnel destinations
746 route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
747 [VppRoutePath(self.pg0.remote_ip4,
748 self.pg0.sw_if_index)])
749 route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
750 [VppRoutePath(self.pg0.remote_ip4,
751 self.pg0.sw_if_index)])
753 route_tun1_dst.add_vpp_config()
754 route_tun2_dst.add_vpp_config()
757 # Create 2 L2 GRE tunnels and x-connect them
759 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
761 type=GreTunnelTypes.TT_TEB)
762 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
764 type=GreTunnelTypes.TT_TEB)
765 gre_if1.add_vpp_config()
766 gre_if2.add_vpp_config()
771 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
774 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
779 # Send in tunnel encapped L2. expect out tunnel encapped L2
782 tx = self.create_tunnel_stream_l2o4(self.pg0,
785 rx = self.send_and_expect(self.pg0, tx, self.pg0)
786 self.verify_tunneled_l2o4(self.pg0, rx, tx,
790 tx = self.create_tunnel_stream_l2o4(self.pg0,
793 rx = self.send_and_expect(self.pg0, tx, self.pg0)
794 self.verify_tunneled_l2o4(self.pg0, rx, tx,
798 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
801 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
806 # Create a VLAN sub-interfaces on the GRE TEB interfaces
807 # then x-connect them
809 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
810 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
812 # gre_if_11.add_vpp_config()
813 # gre_if_12.add_vpp_config()
818 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
819 gre_if_12.sw_if_index,
821 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
822 gre_if_11.sw_if_index,
826 # Configure both to pop thier respective VLAN tags,
827 # so that during the x-coonect they will subsequently push
829 self.vapi.l2_interface_vlan_tag_rewrite(
830 sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
832 self.vapi.l2_interface_vlan_tag_rewrite(
833 sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
837 # Send traffic in both directiond - expect the VLAN tags to
840 tx = self.create_tunnel_stream_vlano4(self.pg0,
844 rx = self.send_and_expect(self.pg0, tx, self.pg0)
845 self.verify_tunneled_vlano4(self.pg0, rx, tx,
850 tx = self.create_tunnel_stream_vlano4(self.pg0,
854 rx = self.send_and_expect(self.pg0, tx, self.pg0)
855 self.verify_tunneled_vlano4(self.pg0, rx, tx,
861 # Cleanup Test resources
863 gre_if_11.remove_vpp_config()
864 gre_if_12.remove_vpp_config()
865 gre_if1.remove_vpp_config()
866 gre_if2.remove_vpp_config()
867 route_tun1_dst.add_vpp_config()
868 route_tun2_dst.add_vpp_config()
870 def test_gre_loop(self):
871 """ GRE tunnel loop Tests """
874 # Create an L3 GRE tunnel.
876 # - assign an IP Addres
878 gre_if = VppGreInterface(self,
881 gre_if.add_vpp_config()
886 # add a route to the tunnel's destination that points
887 # through the tunnel, hence forming a loop in the forwarding
890 route_dst = VppIpRoute(self, "1.1.1.2", 32,
891 [VppRoutePath("0.0.0.0",
892 gre_if.sw_if_index)])
893 route_dst.add_vpp_config()
896 # packets to the tunnels destination should be dropped
898 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
899 self.send_and_assert_no_replies(self.pg2, tx)
901 self.logger.info(self.vapi.ppcli("sh adj 7"))
906 route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
907 self.pg1.sw_if_index)])
908 route_dst.add_vpp_config()
910 rx = self.send_and_expect(self.pg0, tx, self.pg1)
913 # a good route throught the tunnel to check it restacked
915 route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
916 [VppRoutePath("0.0.0.0",
917 gre_if.sw_if_index)])
918 route_via_tun_2.add_vpp_config()
920 tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
921 rx = self.send_and_expect(self.pg0, tx, self.pg1)
922 self.verify_tunneled_4o4(self.pg1, rx, tx,
923 self.pg0.local_ip4, "1.1.1.2")
928 route_via_tun_2.remove_vpp_config()
929 gre_if.remove_vpp_config()
932 if __name__ == '__main__':
933 unittest.main(testRunner=VppTestRunner)