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, IpPath
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 [IpPath("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 [IpPath(self.pg0.remote_ip4, self.pg0.sw_if_index)])
350 route_tun_dst.add_vpp_config()
353 # Send a packet stream that is routed into the tunnel
354 # - packets are GRE encapped
356 self.vapi.cli("clear trace")
357 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
358 self.pg0.add_stream(tx)
360 self.pg_enable_capture(self.pg_interfaces)
363 rx = self.pg0.get_capture()
364 self.verify_tunneled_4o4(self.pg0, rx, tx,
365 self.pg0.local_ip4, "1.1.1.2")
368 # Send tunneled packets that match the created tunnel and
369 # are decapped and forwarded
371 self.vapi.cli("clear trace")
372 tx = self.create_tunnel_stream_4o4(self.pg0,
377 self.pg0.add_stream(tx)
379 self.pg_enable_capture(self.pg_interfaces)
382 rx = self.pg0.get_capture()
383 self.verify_decapped_4o4(self.pg0, rx, tx)
386 # Send tunneled packets that do not match the tunnel's src
388 self.vapi.cli("clear trace")
389 tx = self.create_tunnel_stream_4o4(self.pg0,
394 self.pg0.add_stream(tx)
396 self.pg_enable_capture(self.pg_interfaces)
399 rx = self.pg0.get_capture()
401 self.assertEqual(0, len(rx))
403 error("GRE packets forwarded despite no SRC address match")
408 # Configure IPv6 on the PG interface so we can route IPv6
411 self.pg0.config_ip6()
412 self.pg0.resolve_ndp()
415 # Send IPv6 tunnel encapslated packets
416 # - dropped since IPv6 is not enabled on the tunnel
418 self.vapi.cli("clear trace")
419 tx = self.create_tunnel_stream_6o4(self.pg0,
424 self.pg0.add_stream(tx)
426 self.pg_enable_capture(self.pg_interfaces)
429 rx = self.pg0.get_capture()
431 self.assertEqual(0, len(rx))
433 error("IPv6 GRE packets forwarded despite IPv6 not enabled on tunnel")
438 # Enable IPv6 on the tunnel
443 # Send IPv6 tunnel encapslated packets
444 # - forwarded since IPv6 is enabled on the tunnel
446 self.vapi.cli("clear trace")
447 tx = self.create_tunnel_stream_6o4(self.pg0,
452 self.pg0.add_stream(tx)
454 self.pg_enable_capture(self.pg_interfaces)
457 rx = self.pg0.get_capture()
458 self.verify_decapped_6o4(self.pg0, rx, tx)
463 route_tun_dst.remove_vpp_config()
464 route_via_tun.remove_vpp_config()
465 gre_if.remove_vpp_config()
467 self.pg0.unconfig_ip6()
469 def test_gre_vrf(self):
470 """ GRE tunnel VRF Tests """
473 # Create an L3 GRE tunnel whose destination is in the non-default
474 # table. The underlay is thus non-default - the overlay is still
477 # - assign an IP Addres
479 gre_if = VppGreInterface(self, self.pg1.local_ip4,
482 gre_if.add_vpp_config()
487 # Add a route via the tunnel - in the overlay
489 route_via_tun = IpRoute(self, "9.9.9.9", 32,
490 [IpPath("0.0.0.0", gre_if.sw_if_index)])
491 route_via_tun.add_vpp_config()
494 # Add a route that resolves the tunnel's destination - in the
497 route_tun_dst = IpRoute(self, "2.2.2.2", 32, table_id=1,
498 paths=[IpPath(self.pg1.remote_ip4,
499 self.pg1.sw_if_index)])
500 route_tun_dst.add_vpp_config()
503 # Send a packet stream that is routed into the tunnel
504 # packets are sent in on pg0 which is in the default table
505 # - packets are GRE encapped
507 self.vapi.cli("clear trace")
508 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
509 self.pg0.add_stream(tx)
511 self.pg_enable_capture(self.pg_interfaces)
514 rx = self.pg1.get_capture()
515 self.verify_tunneled_4o4(self.pg1, rx, tx,
516 self.pg1.local_ip4, "2.2.2.2")
519 # Send tunneled packets that match the created tunnel and
520 # are decapped and forwarded. This tests the decap lookup
521 # does not happen in the encap table
523 self.vapi.cli("clear trace")
524 tx = self.create_tunnel_stream_4o4(self.pg1,
529 self.pg1.add_stream(tx)
531 self.pg_enable_capture(self.pg_interfaces)
534 rx = self.pg0.get_capture()
535 self.verify_decapped_4o4(self.pg0, rx, tx)
540 route_tun_dst.remove_vpp_config()
541 route_via_tun.remove_vpp_config()
542 gre_if.remove_vpp_config()
544 def test_gre_l2(self):
545 """ GRE tunnel L2 Tests """
548 # Add routes to resolve the tunnel destinations
550 route_tun1_dst = IpRoute(self, "2.2.2.2", 32,
551 [IpPath(self.pg0.remote_ip4,
552 self.pg0.sw_if_index)])
553 route_tun2_dst = IpRoute(self, "2.2.2.3", 32,
554 [IpPath(self.pg0.remote_ip4,
555 self.pg0.sw_if_index)])
557 route_tun1_dst.add_vpp_config()
558 route_tun2_dst.add_vpp_config()
561 # Create 2 L2 GRE tunnels and x-connect them
563 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
566 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
569 gre_if1.add_vpp_config()
570 gre_if2.add_vpp_config()
575 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
578 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
583 # Send in tunnel encapped L2. expect out tunnel encapped L2
586 self.vapi.cli("clear trace")
587 tx = self.create_tunnel_stream_l2o4(self.pg0,
590 self.pg0.add_stream(tx)
592 self.pg_enable_capture(self.pg_interfaces)
595 rx = self.pg0.get_capture()
596 self.verify_tunneled_l2o4(self.pg0, rx, tx,
600 self.vapi.cli("clear trace")
601 tx = self.create_tunnel_stream_l2o4(self.pg0,
604 self.pg0.add_stream(tx)
606 self.pg_enable_capture(self.pg_interfaces)
609 rx = self.pg0.get_capture()
610 self.verify_tunneled_l2o4(self.pg0, rx, tx,
614 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
617 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
622 # Create a VLAN sub-interfaces on the GRE TEB interfaces
623 # then x-connect them
625 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
626 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
628 # gre_if_11.add_vpp_config()
629 # gre_if_12.add_vpp_config()
634 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
635 gre_if_12.sw_if_index,
637 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
638 gre_if_11.sw_if_index,
642 # Configure both to pop thier respective VLAN tags,
643 # so that during the x-coonect they will subsequently push
645 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
648 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
653 # Send traffic in both directiond - expect the VLAN tags to
656 self.vapi.cli("clear trace")
657 tx = self.create_tunnel_stream_vlano4(self.pg0,
661 self.pg0.add_stream(tx)
663 self.pg_enable_capture(self.pg_interfaces)
666 rx = self.pg0.get_capture()
667 self.verify_tunneled_vlano4(self.pg0, rx, tx,
672 self.vapi.cli("clear trace")
673 tx = self.create_tunnel_stream_vlano4(self.pg0,
677 self.pg0.add_stream(tx)
679 self.pg_enable_capture(self.pg_interfaces)
682 rx = self.pg0.get_capture()
683 self.verify_tunneled_vlano4(self.pg0, rx, tx,
689 # Cleanup Test resources
691 gre_if_11.remove_vpp_config()
692 gre_if_12.remove_vpp_config()
693 gre_if1.remove_vpp_config()
694 gre_if2.remove_vpp_config()
695 route_tun1_dst.add_vpp_config()
696 route_tun2_dst.add_vpp_config()
699 if __name__ == '__main__':
700 unittest.main(testRunner=VppTestRunner)