7 from framework import VppTestCase, VppTestRunner
8 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
9 from vpp_gre_interface import VppGreInterface
10 from vpp_ip_route import IpRoute, RoutePath
11 from vpp_papi_provider import L2_VTR_OP
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether, Dot1Q, ARP, GRE
15 from scapy.layers.inet import IP, UDP
16 from scapy.layers.inet6 import ICMPv6ND_NS, ICMPv6ND_RA, IPv6, UDP
17 from scapy.contrib.mpls import MPLS
18 from scapy.volatile import RandMAC, RandIP
21 class TestGRE(VppTestCase):
26 super(TestGRE, cls).setUpClass()
29 super(TestGRE, self).setUp()
31 # create 2 pg interfaces - set one in a non-default table.
32 self.create_pg_interfaces(range(2))
34 self.pg1.set_table_ip4(1)
35 for i in self.pg_interfaces:
41 super(TestGRE, self).tearDown()
43 def create_stream_ip4(self, src_if, src_ip, dst_ip):
45 for i in range(0, 257):
46 info = self.create_packet_info(src_if.sw_if_index,
48 payload = self.info_to_payload(info)
49 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
50 IP(src=src_ip, dst=dst_ip) /
51 UDP(sport=1234, dport=1234) /
57 def create_tunnel_stream_4o4(self, src_if,
58 tunnel_src, tunnel_dst,
61 for i in range(0, 257):
62 info = self.create_packet_info(src_if.sw_if_index,
64 payload = self.info_to_payload(info)
65 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
66 IP(src=tunnel_src, dst=tunnel_dst) /
68 IP(src=src_ip, dst=dst_ip) /
69 UDP(sport=1234, dport=1234) /
75 def create_tunnel_stream_6o4(self, src_if,
76 tunnel_src, tunnel_dst,
79 for i in range(0, 257):
80 info = self.create_packet_info(src_if.sw_if_index,
82 payload = self.info_to_payload(info)
83 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
84 IP(src=tunnel_src, dst=tunnel_dst) /
86 IPv6(src=src_ip, dst=dst_ip) /
87 UDP(sport=1234, dport=1234) /
93 def create_tunnel_stream_l2o4(self, src_if,
94 tunnel_src, tunnel_dst):
96 for i in range(0, 257):
97 info = self.create_packet_info(src_if.sw_if_index,
99 payload = self.info_to_payload(info)
100 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
101 IP(src=tunnel_src, dst=tunnel_dst) /
103 Ether(dst=RandMAC('*:*:*:*:*:*'),
104 src=RandMAC('*:*:*:*:*:*')) /
105 IP(src=str(RandIP()), dst=str(RandIP())) /
106 UDP(sport=1234, dport=1234) /
112 def create_tunnel_stream_vlano4(self, src_if,
113 tunnel_src, tunnel_dst, vlan):
115 for i in range(0, 257):
116 info = self.create_packet_info(src_if.sw_if_index,
118 payload = self.info_to_payload(info)
119 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
120 IP(src=tunnel_src, dst=tunnel_dst) /
122 Ether(dst=RandMAC('*:*:*:*:*:*'),
123 src=RandMAC('*:*:*:*:*:*')) /
125 IP(src=str(RandIP()), dst=str(RandIP())) /
126 UDP(sport=1234, dport=1234) /
132 def verify_filter(self, capture, sent):
133 if not len(capture) == len(sent):
134 # filter out any IPv6 RAs from the captur
136 if (p.haslayer(ICMPv6ND_RA)):
140 def verify_tunneled_4o4(self, src_if, capture, sent,
141 tunnel_src, tunnel_dst):
143 capture = self.verify_filter(capture, sent)
144 self.assertEqual(len(capture), len(sent))
146 for i in range(len(capture)):
154 self.assertEqual(rx_ip.src, tunnel_src)
155 self.assertEqual(rx_ip.dst, tunnel_dst)
160 self.assertEqual(rx_ip.src, tx_ip.src)
161 self.assertEqual(rx_ip.dst, tx_ip.dst)
162 # IP processing post pop has decremented the TTL
163 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
170 def verify_tunneled_l2o4(self, src_if, capture, sent,
171 tunnel_src, tunnel_dst):
172 capture = self.verify_filter(capture, sent)
173 self.assertEqual(len(capture), len(sent))
175 for i in range(len(capture)):
183 self.assertEqual(rx_ip.src, tunnel_src)
184 self.assertEqual(rx_ip.dst, tunnel_dst)
187 rx_l2 = rx_gre[Ether]
190 tx_l2 = tx_gre[Ether]
193 self.assertEqual(rx_ip.src, tx_ip.src)
194 self.assertEqual(rx_ip.dst, tx_ip.dst)
195 # bridged, not L3 forwarded, so no TTL decrement
196 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
203 def verify_tunneled_vlano4(self, src_if, capture, sent,
204 tunnel_src, tunnel_dst, vlan):
206 capture = self.verify_filter(capture, sent)
207 self.assertEqual(len(capture), len(sent))
212 for i in range(len(capture)):
220 self.assertEqual(rx_ip.src, tunnel_src)
221 self.assertEqual(rx_ip.dst, tunnel_dst)
224 rx_l2 = rx_gre[Ether]
225 rx_vlan = rx_l2[Dot1Q]
228 self.assertEqual(rx_vlan.vlan, vlan)
231 tx_l2 = tx_gre[Ether]
234 self.assertEqual(rx_ip.src, tx_ip.src)
235 self.assertEqual(rx_ip.dst, tx_ip.dst)
236 # bridged, not L3 forwarded, so no TTL decrement
237 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
244 def verify_decapped_4o4(self, src_if, capture, sent):
245 capture = self.verify_filter(capture, sent)
246 self.assertEqual(len(capture), len(sent))
248 for i in range(len(capture)):
258 self.assertEqual(rx_ip.src, tx_ip.src)
259 self.assertEqual(rx_ip.dst, tx_ip.dst)
260 # IP processing post pop has decremented the TTL
261 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
268 def verify_decapped_6o4(self, src_if, capture, sent):
269 capture = self.verify_filter(capture, sent)
270 self.assertEqual(len(capture), len(sent))
272 for i in range(len(capture)):
282 self.assertEqual(rx_ip.src, tx_ip.src)
283 self.assertEqual(rx_ip.dst, tx_ip.dst)
284 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
292 """ GRE tunnel Tests """
295 # Create an L3 GRE tunnel.
297 # - assign an IP Addres
298 # - Add a route via the tunnel
300 gre_if = VppGreInterface(self,
303 gre_if.add_vpp_config()
306 # The double create (create the same tunnel twice) should fail,
307 # and we should still be able to use the original
310 gre_if.add_vpp_config()
314 self.fail("Double GRE tunnel add does not fail")
319 route_via_tun = IpRoute(self, "4.4.4.4", 32,
320 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
322 route_via_tun.add_vpp_config()
325 # Send a packet stream that is routed into the tunnel
326 # - they are all dropped since the tunnel's desintation IP
327 # is unresolved - or resolves via the default route - which
330 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
331 self.pg0.add_stream(tx)
333 self.pg_enable_capture(self.pg_interfaces)
336 rx = self.pg0.get_capture()
339 self.assertEqual(0, len(rx))
341 error("GRE packets forwarded without DIP resolved")
346 # Add a route that resolves the tunnel's destination
348 route_tun_dst = IpRoute(self, "1.1.1.2", 32,
349 [RoutePath(self.pg0.remote_ip4,
350 self.pg0.sw_if_index)])
351 route_tun_dst.add_vpp_config()
354 # Send a packet stream that is routed into the tunnel
355 # - packets are GRE encapped
357 self.vapi.cli("clear trace")
358 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
359 self.pg0.add_stream(tx)
361 self.pg_enable_capture(self.pg_interfaces)
364 rx = self.pg0.get_capture()
365 self.verify_tunneled_4o4(self.pg0, rx, tx,
366 self.pg0.local_ip4, "1.1.1.2")
369 # Send tunneled packets that match the created tunnel and
370 # are decapped and forwarded
372 self.vapi.cli("clear trace")
373 tx = self.create_tunnel_stream_4o4(self.pg0,
378 self.pg0.add_stream(tx)
380 self.pg_enable_capture(self.pg_interfaces)
383 rx = self.pg0.get_capture()
384 self.verify_decapped_4o4(self.pg0, rx, tx)
387 # Send tunneled packets that do not match the tunnel's src
389 self.vapi.cli("clear trace")
390 tx = self.create_tunnel_stream_4o4(self.pg0,
395 self.pg0.add_stream(tx)
397 self.pg_enable_capture(self.pg_interfaces)
400 rx = self.pg0.get_capture()
402 self.assertEqual(0, len(rx))
404 error("GRE packets forwarded despite no SRC address match")
409 # Configure IPv6 on the PG interface so we can route IPv6
412 self.pg0.config_ip6()
413 self.pg0.resolve_ndp()
416 # Send IPv6 tunnel encapslated packets
417 # - dropped since IPv6 is not enabled on the tunnel
419 self.vapi.cli("clear trace")
420 tx = self.create_tunnel_stream_6o4(self.pg0,
425 self.pg0.add_stream(tx)
427 self.pg_enable_capture(self.pg_interfaces)
430 rx = self.pg0.get_capture()
432 self.assertEqual(0, len(rx))
434 error("IPv6 GRE packets forwarded despite IPv6 not enabled on tunnel")
439 # Enable IPv6 on the tunnel
444 # Send IPv6 tunnel encapslated packets
445 # - forwarded since IPv6 is enabled on the tunnel
447 self.vapi.cli("clear trace")
448 tx = self.create_tunnel_stream_6o4(self.pg0,
453 self.pg0.add_stream(tx)
455 self.pg_enable_capture(self.pg_interfaces)
458 rx = self.pg0.get_capture()
459 self.verify_decapped_6o4(self.pg0, rx, tx)
464 route_tun_dst.remove_vpp_config()
465 route_via_tun.remove_vpp_config()
466 gre_if.remove_vpp_config()
468 self.pg0.unconfig_ip6()
470 def test_gre_vrf(self):
471 """ GRE tunnel VRF Tests """
474 # Create an L3 GRE tunnel whose destination is in the non-default
475 # table. The underlay is thus non-default - the overlay is still
478 # - assign an IP Addres
480 gre_if = VppGreInterface(self, self.pg1.local_ip4,
483 gre_if.add_vpp_config()
488 # Add a route via the tunnel - in the overlay
490 route_via_tun = IpRoute(self, "9.9.9.9", 32,
491 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
492 route_via_tun.add_vpp_config()
495 # Add a route that resolves the tunnel's destination - in the
498 route_tun_dst = IpRoute(self, "2.2.2.2", 32, table_id=1,
499 paths=[RoutePath(self.pg1.remote_ip4,
500 self.pg1.sw_if_index)])
501 route_tun_dst.add_vpp_config()
504 # Send a packet stream that is routed into the tunnel
505 # packets are sent in on pg0 which is in the default table
506 # - packets are GRE encapped
508 self.vapi.cli("clear trace")
509 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
510 self.pg0.add_stream(tx)
512 self.pg_enable_capture(self.pg_interfaces)
515 rx = self.pg1.get_capture()
516 self.verify_tunneled_4o4(self.pg1, rx, tx,
517 self.pg1.local_ip4, "2.2.2.2")
520 # Send tunneled packets that match the created tunnel and
521 # are decapped and forwarded. This tests the decap lookup
522 # does not happen in the encap table
524 self.vapi.cli("clear trace")
525 tx = self.create_tunnel_stream_4o4(self.pg1,
530 self.pg1.add_stream(tx)
532 self.pg_enable_capture(self.pg_interfaces)
535 rx = self.pg0.get_capture()
536 self.verify_decapped_4o4(self.pg0, rx, tx)
541 route_tun_dst.remove_vpp_config()
542 route_via_tun.remove_vpp_config()
543 gre_if.remove_vpp_config()
545 def test_gre_l2(self):
546 """ GRE tunnel L2 Tests """
549 # Add routes to resolve the tunnel destinations
551 route_tun1_dst = IpRoute(self, "2.2.2.2", 32,
552 [RoutePath(self.pg0.remote_ip4,
553 self.pg0.sw_if_index)])
554 route_tun2_dst = IpRoute(self, "2.2.2.3", 32,
555 [RoutePath(self.pg0.remote_ip4,
556 self.pg0.sw_if_index)])
558 route_tun1_dst.add_vpp_config()
559 route_tun2_dst.add_vpp_config()
562 # Create 2 L2 GRE tunnels and x-connect them
564 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
567 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
570 gre_if1.add_vpp_config()
571 gre_if2.add_vpp_config()
576 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
579 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
584 # Send in tunnel encapped L2. expect out tunnel encapped L2
587 self.vapi.cli("clear trace")
588 tx = self.create_tunnel_stream_l2o4(self.pg0,
591 self.pg0.add_stream(tx)
593 self.pg_enable_capture(self.pg_interfaces)
596 rx = self.pg0.get_capture()
597 self.verify_tunneled_l2o4(self.pg0, rx, tx,
601 self.vapi.cli("clear trace")
602 tx = self.create_tunnel_stream_l2o4(self.pg0,
605 self.pg0.add_stream(tx)
607 self.pg_enable_capture(self.pg_interfaces)
610 rx = self.pg0.get_capture()
611 self.verify_tunneled_l2o4(self.pg0, rx, tx,
615 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
618 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
623 # Create a VLAN sub-interfaces on the GRE TEB interfaces
624 # then x-connect them
626 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
627 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
629 # gre_if_11.add_vpp_config()
630 # gre_if_12.add_vpp_config()
635 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
636 gre_if_12.sw_if_index,
638 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
639 gre_if_11.sw_if_index,
643 # Configure both to pop thier respective VLAN tags,
644 # so that during the x-coonect they will subsequently push
646 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
649 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
654 # Send traffic in both directiond - expect the VLAN tags to
657 self.vapi.cli("clear trace")
658 tx = self.create_tunnel_stream_vlano4(self.pg0,
662 self.pg0.add_stream(tx)
664 self.pg_enable_capture(self.pg_interfaces)
667 rx = self.pg0.get_capture()
668 self.verify_tunneled_vlano4(self.pg0, rx, tx,
673 self.vapi.cli("clear trace")
674 tx = self.create_tunnel_stream_vlano4(self.pg0,
678 self.pg0.add_stream(tx)
680 self.pg_enable_capture(self.pg_interfaces)
683 rx = self.pg0.get_capture()
684 self.verify_tunneled_vlano4(self.pg0, rx, tx,
690 # Cleanup Test resources
692 gre_if_11.remove_vpp_config()
693 gre_if_12.remove_vpp_config()
694 gre_if1.remove_vpp_config()
695 gre_if2.remove_vpp_config()
696 route_tun1_dst.add_vpp_config()
697 route_tun2_dst.add_vpp_config()
700 if __name__ == '__main__':
701 unittest.main(testRunner=VppTestRunner)