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 VppIpRoute, VppRoutePath
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()
42 for i in self.pg_interfaces:
47 def create_stream_ip4(self, src_if, src_ip, dst_ip):
49 for i in range(0, 257):
50 info = self.create_packet_info(src_if, src_if)
51 payload = self.info_to_payload(info)
52 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
53 IP(src=src_ip, dst=dst_ip) /
54 UDP(sport=1234, dport=1234) /
60 def create_tunnel_stream_4o4(self, src_if,
61 tunnel_src, tunnel_dst,
64 for i in range(0, 257):
65 info = self.create_packet_info(src_if, src_if)
66 payload = self.info_to_payload(info)
67 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
68 IP(src=tunnel_src, dst=tunnel_dst) /
70 IP(src=src_ip, dst=dst_ip) /
71 UDP(sport=1234, dport=1234) /
77 def create_tunnel_stream_6o4(self, src_if,
78 tunnel_src, tunnel_dst,
81 for i in range(0, 257):
82 info = self.create_packet_info(src_if, src_if)
83 payload = self.info_to_payload(info)
84 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
85 IP(src=tunnel_src, dst=tunnel_dst) /
87 IPv6(src=src_ip, dst=dst_ip) /
88 UDP(sport=1234, dport=1234) /
94 def create_tunnel_stream_l2o4(self, src_if,
95 tunnel_src, tunnel_dst):
97 for i in range(0, 257):
98 info = self.create_packet_info(src_if, src_if)
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, src_if)
117 payload = self.info_to_payload(info)
118 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
119 IP(src=tunnel_src, dst=tunnel_dst) /
121 Ether(dst=RandMAC('*:*:*:*:*:*'),
122 src=RandMAC('*:*:*:*:*:*')) /
124 IP(src=str(RandIP()), dst=str(RandIP())) /
125 UDP(sport=1234, dport=1234) /
131 def verify_tunneled_4o4(self, src_if, capture, sent,
132 tunnel_src, tunnel_dst):
134 self.assertEqual(len(capture), len(sent))
136 for i in range(len(capture)):
144 self.assertEqual(rx_ip.src, tunnel_src)
145 self.assertEqual(rx_ip.dst, tunnel_dst)
150 self.assertEqual(rx_ip.src, tx_ip.src)
151 self.assertEqual(rx_ip.dst, tx_ip.dst)
152 # IP processing post pop has decremented the TTL
153 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
156 self.logger.error(ppp("Rx:", rx))
157 self.logger.error(ppp("Tx:", tx))
160 def verify_tunneled_l2o4(self, src_if, capture, sent,
161 tunnel_src, tunnel_dst):
162 self.assertEqual(len(capture), len(sent))
164 for i in range(len(capture)):
172 self.assertEqual(rx_ip.src, tunnel_src)
173 self.assertEqual(rx_ip.dst, tunnel_dst)
176 rx_l2 = rx_gre[Ether]
179 tx_l2 = tx_gre[Ether]
182 self.assertEqual(rx_ip.src, tx_ip.src)
183 self.assertEqual(rx_ip.dst, tx_ip.dst)
184 # bridged, not L3 forwarded, so no TTL decrement
185 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
188 self.logger.error(ppp("Rx:", rx))
189 self.logger.error(ppp("Tx:", tx))
192 def verify_tunneled_vlano4(self, src_if, capture, sent,
193 tunnel_src, tunnel_dst, vlan):
195 self.assertEqual(len(capture), len(sent))
197 ppc("Unexpected packets captured:", capture)
200 for i in range(len(capture)):
208 self.assertEqual(rx_ip.src, tunnel_src)
209 self.assertEqual(rx_ip.dst, tunnel_dst)
212 rx_l2 = rx_gre[Ether]
213 rx_vlan = rx_l2[Dot1Q]
216 self.assertEqual(rx_vlan.vlan, vlan)
219 tx_l2 = tx_gre[Ether]
222 self.assertEqual(rx_ip.src, tx_ip.src)
223 self.assertEqual(rx_ip.dst, tx_ip.dst)
224 # bridged, not L3 forwarded, so no TTL decrement
225 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
228 self.logger.error(ppp("Rx:", rx))
229 self.logger.error(ppp("Tx:", tx))
232 def verify_decapped_4o4(self, src_if, capture, sent):
233 self.assertEqual(len(capture), len(sent))
235 for i in range(len(capture)):
245 self.assertEqual(rx_ip.src, tx_ip.src)
246 self.assertEqual(rx_ip.dst, tx_ip.dst)
247 # IP processing post pop has decremented the TTL
248 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
251 self.logger.error(ppp("Rx:", rx))
252 self.logger.error(ppp("Tx:", tx))
255 def verify_decapped_6o4(self, src_if, capture, sent):
256 self.assertEqual(len(capture), len(sent))
258 for i in range(len(capture)):
268 self.assertEqual(rx_ip.src, tx_ip.src)
269 self.assertEqual(rx_ip.dst, tx_ip.dst)
270 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
273 self.logger.error(ppp("Rx:", rx))
274 self.logger.error(ppp("Tx:", tx))
278 """ GRE tunnel Tests """
281 # Create an L3 GRE tunnel.
283 # - assign an IP Addres
284 # - Add a route via the tunnel
286 gre_if = VppGreInterface(self,
289 gre_if.add_vpp_config()
292 # The double create (create the same tunnel twice) should fail,
293 # and we should still be able to use the original
296 gre_if.add_vpp_config()
300 self.fail("Double GRE tunnel add does not fail")
305 route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
306 [VppRoutePath("0.0.0.0",
307 gre_if.sw_if_index)])
309 route_via_tun.add_vpp_config()
312 # Send a packet stream that is routed into the tunnel
313 # - they are all dropped since the tunnel's desintation IP
314 # is unresolved - or resolves via the default route - which
317 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
318 self.pg0.add_stream(tx)
320 self.pg_enable_capture(self.pg_interfaces)
323 self.pg0.assert_nothing_captured(
324 remark="GRE packets forwarded without DIP resolved")
327 # Add a route that resolves the tunnel's destination
329 route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
330 [VppRoutePath(self.pg0.remote_ip4,
331 self.pg0.sw_if_index)])
332 route_tun_dst.add_vpp_config()
335 # Send a packet stream that is routed into the tunnel
336 # - packets are GRE encapped
338 self.vapi.cli("clear trace")
339 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
340 self.pg0.add_stream(tx)
342 self.pg_enable_capture(self.pg_interfaces)
345 rx = self.pg0.get_capture(len(tx))
346 self.verify_tunneled_4o4(self.pg0, rx, tx,
347 self.pg0.local_ip4, "1.1.1.2")
350 # Send tunneled packets that match the created tunnel and
351 # are decapped and forwarded
353 self.vapi.cli("clear trace")
354 tx = self.create_tunnel_stream_4o4(self.pg0,
359 self.pg0.add_stream(tx)
361 self.pg_enable_capture(self.pg_interfaces)
364 rx = self.pg0.get_capture(len(tx))
365 self.verify_decapped_4o4(self.pg0, rx, tx)
368 # Send tunneled packets that do not match the tunnel's src
370 self.vapi.cli("clear trace")
371 tx = self.create_tunnel_stream_4o4(self.pg0,
376 self.pg0.add_stream(tx)
378 self.pg_enable_capture(self.pg_interfaces)
381 self.pg0.assert_nothing_captured(
382 remark="GRE packets forwarded despite no SRC address match")
385 # Configure IPv6 on the PG interface so we can route IPv6
388 self.pg0.config_ip6()
389 self.pg0.resolve_ndp()
392 # Send IPv6 tunnel encapslated packets
393 # - dropped since IPv6 is not enabled on the tunnel
395 self.vapi.cli("clear trace")
396 tx = self.create_tunnel_stream_6o4(self.pg0,
401 self.pg0.add_stream(tx)
403 self.pg_enable_capture(self.pg_interfaces)
406 self.pg0.assert_nothing_captured(remark="IPv6 GRE packets forwarded "
407 "despite IPv6 not enabled on tunnel")
410 # Enable IPv6 on the tunnel
415 # Send IPv6 tunnel encapslated packets
416 # - forwarded since IPv6 is 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(len(tx))
430 self.verify_decapped_6o4(self.pg0, rx, tx)
435 route_tun_dst.remove_vpp_config()
436 route_via_tun.remove_vpp_config()
437 gre_if.remove_vpp_config()
439 self.pg0.unconfig_ip6()
441 def test_gre_vrf(self):
442 """ GRE tunnel VRF Tests """
445 # Create an L3 GRE tunnel whose destination is in the non-default
446 # table. The underlay is thus non-default - the overlay is still
449 # - assign an IP Addres
451 gre_if = VppGreInterface(self, self.pg1.local_ip4,
454 gre_if.add_vpp_config()
459 # Add a route via the tunnel - in the overlay
461 route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
462 [VppRoutePath("0.0.0.0",
463 gre_if.sw_if_index)])
464 route_via_tun.add_vpp_config()
467 # Add a route that resolves the tunnel's destination - in the
470 route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
471 paths=[VppRoutePath(self.pg1.remote_ip4,
472 self.pg1.sw_if_index)])
473 route_tun_dst.add_vpp_config()
476 # Send a packet stream that is routed into the tunnel
477 # packets are sent in on pg0 which is in the default table
478 # - packets are GRE encapped
480 self.vapi.cli("clear trace")
481 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
482 self.pg0.add_stream(tx)
484 self.pg_enable_capture(self.pg_interfaces)
487 rx = self.pg1.get_capture(len(tx))
488 self.verify_tunneled_4o4(self.pg1, rx, tx,
489 self.pg1.local_ip4, "2.2.2.2")
492 # Send tunneled packets that match the created tunnel and
493 # are decapped and forwarded. This tests the decap lookup
494 # does not happen in the encap table
496 self.vapi.cli("clear trace")
497 tx = self.create_tunnel_stream_4o4(self.pg1,
502 self.pg1.add_stream(tx)
504 self.pg_enable_capture(self.pg_interfaces)
507 rx = self.pg0.get_capture(len(tx))
508 self.verify_decapped_4o4(self.pg0, rx, tx)
513 route_tun_dst.remove_vpp_config()
514 route_via_tun.remove_vpp_config()
515 gre_if.remove_vpp_config()
517 def test_gre_l2(self):
518 """ GRE tunnel L2 Tests """
521 # Add routes to resolve the tunnel destinations
523 route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
524 [VppRoutePath(self.pg0.remote_ip4,
525 self.pg0.sw_if_index)])
526 route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
527 [VppRoutePath(self.pg0.remote_ip4,
528 self.pg0.sw_if_index)])
530 route_tun1_dst.add_vpp_config()
531 route_tun2_dst.add_vpp_config()
534 # Create 2 L2 GRE tunnels and x-connect them
536 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
539 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
542 gre_if1.add_vpp_config()
543 gre_if2.add_vpp_config()
548 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
551 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
556 # Send in tunnel encapped L2. expect out tunnel encapped L2
559 self.vapi.cli("clear trace")
560 tx = self.create_tunnel_stream_l2o4(self.pg0,
563 self.pg0.add_stream(tx)
565 self.pg_enable_capture(self.pg_interfaces)
568 rx = self.pg0.get_capture(len(tx))
569 self.verify_tunneled_l2o4(self.pg0, rx, tx,
573 self.vapi.cli("clear trace")
574 tx = self.create_tunnel_stream_l2o4(self.pg0,
577 self.pg0.add_stream(tx)
579 self.pg_enable_capture(self.pg_interfaces)
582 rx = self.pg0.get_capture(len(tx))
583 self.verify_tunneled_l2o4(self.pg0, rx, tx,
587 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
590 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
595 # Create a VLAN sub-interfaces on the GRE TEB interfaces
596 # then x-connect them
598 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
599 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
601 # gre_if_11.add_vpp_config()
602 # gre_if_12.add_vpp_config()
607 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
608 gre_if_12.sw_if_index,
610 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
611 gre_if_11.sw_if_index,
615 # Configure both to pop thier respective VLAN tags,
616 # so that during the x-coonect they will subsequently push
618 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
621 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
626 # Send traffic in both directiond - expect the VLAN tags to
629 self.vapi.cli("clear trace")
630 tx = self.create_tunnel_stream_vlano4(self.pg0,
634 self.pg0.add_stream(tx)
636 self.pg_enable_capture(self.pg_interfaces)
639 rx = self.pg0.get_capture(len(tx))
640 self.verify_tunneled_vlano4(self.pg0, rx, tx,
645 self.vapi.cli("clear trace")
646 tx = self.create_tunnel_stream_vlano4(self.pg0,
650 self.pg0.add_stream(tx)
652 self.pg_enable_capture(self.pg_interfaces)
655 rx = self.pg0.get_capture(len(tx))
656 self.verify_tunneled_vlano4(self.pg0, rx, tx,
662 # Cleanup Test resources
664 gre_if_11.remove_vpp_config()
665 gre_if_12.remove_vpp_config()
666 gre_if1.remove_vpp_config()
667 gre_if2.remove_vpp_config()
668 route_tun1_dst.add_vpp_config()
669 route_tun2_dst.add_vpp_config()
672 if __name__ == '__main__':
673 unittest.main(testRunner=VppTestRunner)