6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppDot1QSubint
8 from vpp_gre_interface import VppGreInterface
9 from vpp_ip_route import IpRoute, RoutePath
10 from vpp_papi_provider import L2_VTR_OP
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether, Dot1Q, GRE
14 from scapy.layers.inet import IP, UDP
15 from scapy.layers.inet6 import IPv6
16 from scapy.volatile import RandMAC, RandIP
18 from util import ppp, ppc
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, src_if)
47 payload = self.info_to_payload(info)
48 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
49 IP(src=src_ip, dst=dst_ip) /
50 UDP(sport=1234, dport=1234) /
56 def create_tunnel_stream_4o4(self, src_if,
57 tunnel_src, tunnel_dst,
60 for i in range(0, 257):
61 info = self.create_packet_info(src_if, src_if)
62 payload = self.info_to_payload(info)
63 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
64 IP(src=tunnel_src, dst=tunnel_dst) /
66 IP(src=src_ip, dst=dst_ip) /
67 UDP(sport=1234, dport=1234) /
73 def create_tunnel_stream_6o4(self, src_if,
74 tunnel_src, tunnel_dst,
77 for i in range(0, 257):
78 info = self.create_packet_info(src_if, src_if)
79 payload = self.info_to_payload(info)
80 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
81 IP(src=tunnel_src, dst=tunnel_dst) /
83 IPv6(src=src_ip, dst=dst_ip) /
84 UDP(sport=1234, dport=1234) /
90 def create_tunnel_stream_l2o4(self, src_if,
91 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 Ether(dst=RandMAC('*:*:*:*:*:*'),
100 src=RandMAC('*:*:*:*:*:*')) /
101 IP(src=str(RandIP()), dst=str(RandIP())) /
102 UDP(sport=1234, dport=1234) /
108 def create_tunnel_stream_vlano4(self, src_if,
109 tunnel_src, tunnel_dst, vlan):
111 for i in range(0, 257):
112 info = self.create_packet_info(src_if, src_if)
113 payload = self.info_to_payload(info)
114 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
115 IP(src=tunnel_src, dst=tunnel_dst) /
117 Ether(dst=RandMAC('*:*:*:*:*:*'),
118 src=RandMAC('*:*:*:*:*:*')) /
120 IP(src=str(RandIP()), dst=str(RandIP())) /
121 UDP(sport=1234, dport=1234) /
127 def verify_tunneled_4o4(self, src_if, capture, sent,
128 tunnel_src, tunnel_dst):
130 self.assertEqual(len(capture), len(sent))
132 for i in range(len(capture)):
140 self.assertEqual(rx_ip.src, tunnel_src)
141 self.assertEqual(rx_ip.dst, tunnel_dst)
146 self.assertEqual(rx_ip.src, tx_ip.src)
147 self.assertEqual(rx_ip.dst, tx_ip.dst)
148 # IP processing post pop has decremented the TTL
149 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
152 self.logger.error(ppp("Rx:", rx))
153 self.logger.error(ppp("Tx:", tx))
156 def verify_tunneled_l2o4(self, src_if, capture, sent,
157 tunnel_src, tunnel_dst):
158 self.assertEqual(len(capture), len(sent))
160 for i in range(len(capture)):
168 self.assertEqual(rx_ip.src, tunnel_src)
169 self.assertEqual(rx_ip.dst, tunnel_dst)
172 rx_l2 = rx_gre[Ether]
175 tx_l2 = tx_gre[Ether]
178 self.assertEqual(rx_ip.src, tx_ip.src)
179 self.assertEqual(rx_ip.dst, tx_ip.dst)
180 # bridged, not L3 forwarded, so no TTL decrement
181 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
184 self.logger.error(ppp("Rx:", rx))
185 self.logger.error(ppp("Tx:", tx))
188 def verify_tunneled_vlano4(self, src_if, capture, sent,
189 tunnel_src, tunnel_dst, vlan):
191 self.assertEqual(len(capture), len(sent))
193 ppc("Unexpected packets captured:", capture)
196 for i in range(len(capture)):
204 self.assertEqual(rx_ip.src, tunnel_src)
205 self.assertEqual(rx_ip.dst, tunnel_dst)
208 rx_l2 = rx_gre[Ether]
209 rx_vlan = rx_l2[Dot1Q]
212 self.assertEqual(rx_vlan.vlan, vlan)
215 tx_l2 = tx_gre[Ether]
218 self.assertEqual(rx_ip.src, tx_ip.src)
219 self.assertEqual(rx_ip.dst, tx_ip.dst)
220 # bridged, not L3 forwarded, so no TTL decrement
221 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
224 self.logger.error(ppp("Rx:", rx))
225 self.logger.error(ppp("Tx:", tx))
228 def verify_decapped_4o4(self, src_if, capture, sent):
229 self.assertEqual(len(capture), len(sent))
231 for i in range(len(capture)):
241 self.assertEqual(rx_ip.src, tx_ip.src)
242 self.assertEqual(rx_ip.dst, tx_ip.dst)
243 # IP processing post pop has decremented the TTL
244 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
247 self.logger.error(ppp("Rx:", rx))
248 self.logger.error(ppp("Tx:", tx))
251 def verify_decapped_6o4(self, src_if, capture, sent):
252 self.assertEqual(len(capture), len(sent))
254 for i in range(len(capture)):
264 self.assertEqual(rx_ip.src, tx_ip.src)
265 self.assertEqual(rx_ip.dst, tx_ip.dst)
266 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
269 self.logger.error(ppp("Rx:", rx))
270 self.logger.error(ppp("Tx:", tx))
274 """ GRE tunnel Tests """
277 # Create an L3 GRE tunnel.
279 # - assign an IP Addres
280 # - Add a route via the tunnel
282 gre_if = VppGreInterface(self,
285 gre_if.add_vpp_config()
288 # The double create (create the same tunnel twice) should fail,
289 # and we should still be able to use the original
292 gre_if.add_vpp_config()
296 self.fail("Double GRE tunnel add does not fail")
301 route_via_tun = IpRoute(self, "4.4.4.4", 32,
302 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
304 route_via_tun.add_vpp_config()
307 # Send a packet stream that is routed into the tunnel
308 # - they are all dropped since the tunnel's desintation IP
309 # is unresolved - or resolves via the default route - which
312 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
313 self.pg0.add_stream(tx)
315 self.pg_enable_capture(self.pg_interfaces)
318 self.pg0.assert_nothing_captured(
319 remark="GRE packets forwarded without DIP resolved")
322 # Add a route that resolves the tunnel's destination
324 route_tun_dst = IpRoute(self, "1.1.1.2", 32,
325 [RoutePath(self.pg0.remote_ip4,
326 self.pg0.sw_if_index)])
327 route_tun_dst.add_vpp_config()
330 # Send a packet stream that is routed into the tunnel
331 # - packets are GRE encapped
333 self.vapi.cli("clear trace")
334 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
335 self.pg0.add_stream(tx)
337 self.pg_enable_capture(self.pg_interfaces)
340 rx = self.pg0.get_capture(len(tx))
341 self.verify_tunneled_4o4(self.pg0, rx, tx,
342 self.pg0.local_ip4, "1.1.1.2")
345 # Send tunneled packets that match the created tunnel and
346 # are decapped and forwarded
348 self.vapi.cli("clear trace")
349 tx = self.create_tunnel_stream_4o4(self.pg0,
354 self.pg0.add_stream(tx)
356 self.pg_enable_capture(self.pg_interfaces)
359 rx = self.pg0.get_capture(len(tx))
360 self.verify_decapped_4o4(self.pg0, rx, tx)
363 # Send tunneled packets that do not match the tunnel's src
365 self.vapi.cli("clear trace")
366 tx = self.create_tunnel_stream_4o4(self.pg0,
371 self.pg0.add_stream(tx)
373 self.pg_enable_capture(self.pg_interfaces)
376 self.pg0.assert_nothing_captured(
377 remark="GRE packets forwarded despite no SRC address match")
380 # Configure IPv6 on the PG interface so we can route IPv6
383 self.pg0.config_ip6()
384 self.pg0.resolve_ndp()
387 # Send IPv6 tunnel encapslated packets
388 # - dropped since IPv6 is not enabled on the tunnel
390 self.vapi.cli("clear trace")
391 tx = self.create_tunnel_stream_6o4(self.pg0,
396 self.pg0.add_stream(tx)
398 self.pg_enable_capture(self.pg_interfaces)
401 self.pg0.assert_nothing_captured(remark="IPv6 GRE packets forwarded "
402 "despite IPv6 not enabled on tunnel")
405 # Enable IPv6 on the tunnel
410 # Send IPv6 tunnel encapslated packets
411 # - forwarded since IPv6 is enabled on the tunnel
413 self.vapi.cli("clear trace")
414 tx = self.create_tunnel_stream_6o4(self.pg0,
419 self.pg0.add_stream(tx)
421 self.pg_enable_capture(self.pg_interfaces)
424 rx = self.pg0.get_capture(len(tx))
425 self.verify_decapped_6o4(self.pg0, rx, tx)
430 route_tun_dst.remove_vpp_config()
431 route_via_tun.remove_vpp_config()
432 gre_if.remove_vpp_config()
434 self.pg0.unconfig_ip6()
436 def test_gre_vrf(self):
437 """ GRE tunnel VRF Tests """
440 # Create an L3 GRE tunnel whose destination is in the non-default
441 # table. The underlay is thus non-default - the overlay is still
444 # - assign an IP Addres
446 gre_if = VppGreInterface(self, self.pg1.local_ip4,
449 gre_if.add_vpp_config()
454 # Add a route via the tunnel - in the overlay
456 route_via_tun = IpRoute(self, "9.9.9.9", 32,
457 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
458 route_via_tun.add_vpp_config()
461 # Add a route that resolves the tunnel's destination - in the
464 route_tun_dst = IpRoute(self, "2.2.2.2", 32, table_id=1,
465 paths=[RoutePath(self.pg1.remote_ip4,
466 self.pg1.sw_if_index)])
467 route_tun_dst.add_vpp_config()
470 # Send a packet stream that is routed into the tunnel
471 # packets are sent in on pg0 which is in the default table
472 # - packets are GRE encapped
474 self.vapi.cli("clear trace")
475 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
476 self.pg0.add_stream(tx)
478 self.pg_enable_capture(self.pg_interfaces)
481 rx = self.pg1.get_capture(len(tx))
482 self.verify_tunneled_4o4(self.pg1, rx, tx,
483 self.pg1.local_ip4, "2.2.2.2")
486 # Send tunneled packets that match the created tunnel and
487 # are decapped and forwarded. This tests the decap lookup
488 # does not happen in the encap table
490 self.vapi.cli("clear trace")
491 tx = self.create_tunnel_stream_4o4(self.pg1,
496 self.pg1.add_stream(tx)
498 self.pg_enable_capture(self.pg_interfaces)
501 rx = self.pg0.get_capture(len(tx))
502 self.verify_decapped_4o4(self.pg0, rx, tx)
507 route_tun_dst.remove_vpp_config()
508 route_via_tun.remove_vpp_config()
509 gre_if.remove_vpp_config()
511 def test_gre_l2(self):
512 """ GRE tunnel L2 Tests """
515 # Add routes to resolve the tunnel destinations
517 route_tun1_dst = IpRoute(self, "2.2.2.2", 32,
518 [RoutePath(self.pg0.remote_ip4,
519 self.pg0.sw_if_index)])
520 route_tun2_dst = IpRoute(self, "2.2.2.3", 32,
521 [RoutePath(self.pg0.remote_ip4,
522 self.pg0.sw_if_index)])
524 route_tun1_dst.add_vpp_config()
525 route_tun2_dst.add_vpp_config()
528 # Create 2 L2 GRE tunnels and x-connect them
530 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
533 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
536 gre_if1.add_vpp_config()
537 gre_if2.add_vpp_config()
542 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
545 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
550 # Send in tunnel encapped L2. expect out tunnel encapped L2
553 self.vapi.cli("clear trace")
554 tx = self.create_tunnel_stream_l2o4(self.pg0,
557 self.pg0.add_stream(tx)
559 self.pg_enable_capture(self.pg_interfaces)
562 rx = self.pg0.get_capture(len(tx))
563 self.verify_tunneled_l2o4(self.pg0, rx, tx,
567 self.vapi.cli("clear trace")
568 tx = self.create_tunnel_stream_l2o4(self.pg0,
571 self.pg0.add_stream(tx)
573 self.pg_enable_capture(self.pg_interfaces)
576 rx = self.pg0.get_capture(len(tx))
577 self.verify_tunneled_l2o4(self.pg0, rx, tx,
581 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
584 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
589 # Create a VLAN sub-interfaces on the GRE TEB interfaces
590 # then x-connect them
592 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
593 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
595 # gre_if_11.add_vpp_config()
596 # gre_if_12.add_vpp_config()
601 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
602 gre_if_12.sw_if_index,
604 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
605 gre_if_11.sw_if_index,
609 # Configure both to pop thier respective VLAN tags,
610 # so that during the x-coonect they will subsequently push
612 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
615 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
620 # Send traffic in both directiond - expect the VLAN tags to
623 self.vapi.cli("clear trace")
624 tx = self.create_tunnel_stream_vlano4(self.pg0,
628 self.pg0.add_stream(tx)
630 self.pg_enable_capture(self.pg_interfaces)
633 rx = self.pg0.get_capture(len(tx))
634 self.verify_tunneled_vlano4(self.pg0, rx, tx,
639 self.vapi.cli("clear trace")
640 tx = self.create_tunnel_stream_vlano4(self.pg0,
644 self.pg0.add_stream(tx)
646 self.pg_enable_capture(self.pg_interfaces)
649 rx = self.pg0.get_capture(len(tx))
650 self.verify_tunneled_vlano4(self.pg0, rx, tx,
656 # Cleanup Test resources
658 gre_if_11.remove_vpp_config()
659 gre_if_12.remove_vpp_config()
660 gre_if1.remove_vpp_config()
661 gre_if2.remove_vpp_config()
662 route_tun1_dst.add_vpp_config()
663 route_tun2_dst.add_vpp_config()
666 if __name__ == '__main__':
667 unittest.main(testRunner=VppTestRunner)