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.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_tunneled_4o4(self, src_if, capture, sent,
133 tunnel_src, tunnel_dst):
135 self.assertEqual(len(capture), len(sent))
137 for i in range(len(capture)):
145 self.assertEqual(rx_ip.src, tunnel_src)
146 self.assertEqual(rx_ip.dst, tunnel_dst)
151 self.assertEqual(rx_ip.src, tx_ip.src)
152 self.assertEqual(rx_ip.dst, tx_ip.dst)
153 # IP processing post pop has decremented the TTL
154 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
157 self.logger.error(ppp("Rx:", rx))
158 self.logger.error(ppp("Tx:", tx))
161 def verify_tunneled_l2o4(self, src_if, capture, sent,
162 tunnel_src, tunnel_dst):
163 self.assertEqual(len(capture), len(sent))
165 for i in range(len(capture)):
173 self.assertEqual(rx_ip.src, tunnel_src)
174 self.assertEqual(rx_ip.dst, tunnel_dst)
177 rx_l2 = rx_gre[Ether]
180 tx_l2 = tx_gre[Ether]
183 self.assertEqual(rx_ip.src, tx_ip.src)
184 self.assertEqual(rx_ip.dst, tx_ip.dst)
185 # bridged, not L3 forwarded, so no TTL decrement
186 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
189 self.logger.error(ppp("Rx:", rx))
190 self.logger.error(ppp("Tx:", tx))
193 def verify_tunneled_vlano4(self, src_if, capture, sent,
194 tunnel_src, tunnel_dst, vlan):
196 self.assertEqual(len(capture), len(sent))
198 ppc("Unexpected packets captured:", capture)
201 for i in range(len(capture)):
209 self.assertEqual(rx_ip.src, tunnel_src)
210 self.assertEqual(rx_ip.dst, tunnel_dst)
213 rx_l2 = rx_gre[Ether]
214 rx_vlan = rx_l2[Dot1Q]
217 self.assertEqual(rx_vlan.vlan, vlan)
220 tx_l2 = tx_gre[Ether]
223 self.assertEqual(rx_ip.src, tx_ip.src)
224 self.assertEqual(rx_ip.dst, tx_ip.dst)
225 # bridged, not L3 forwarded, so no TTL decrement
226 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
229 self.logger.error(ppp("Rx:", rx))
230 self.logger.error(ppp("Tx:", tx))
233 def verify_decapped_4o4(self, src_if, capture, sent):
234 self.assertEqual(len(capture), len(sent))
236 for i in range(len(capture)):
246 self.assertEqual(rx_ip.src, tx_ip.src)
247 self.assertEqual(rx_ip.dst, tx_ip.dst)
248 # IP processing post pop has decremented the TTL
249 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
252 self.logger.error(ppp("Rx:", rx))
253 self.logger.error(ppp("Tx:", tx))
256 def verify_decapped_6o4(self, src_if, capture, sent):
257 self.assertEqual(len(capture), len(sent))
259 for i in range(len(capture)):
269 self.assertEqual(rx_ip.src, tx_ip.src)
270 self.assertEqual(rx_ip.dst, tx_ip.dst)
271 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
274 self.logger.error(ppp("Rx:", rx))
275 self.logger.error(ppp("Tx:", tx))
279 """ GRE tunnel Tests """
282 # Create an L3 GRE tunnel.
284 # - assign an IP Addres
285 # - Add a route via the tunnel
287 gre_if = VppGreInterface(self,
290 gre_if.add_vpp_config()
293 # The double create (create the same tunnel twice) should fail,
294 # and we should still be able to use the original
297 gre_if.add_vpp_config()
301 self.fail("Double GRE tunnel add does not fail")
306 route_via_tun = IpRoute(self, "4.4.4.4", 32,
307 [RoutePath("0.0.0.0", 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 = IpRoute(self, "1.1.1.2", 32,
330 [RoutePath(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()
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()
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()
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 = IpRoute(self, "9.9.9.9", 32,
462 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
463 route_via_tun.add_vpp_config()
466 # Add a route that resolves the tunnel's destination - in the
469 route_tun_dst = IpRoute(self, "2.2.2.2", 32, table_id=1,
470 paths=[RoutePath(self.pg1.remote_ip4,
471 self.pg1.sw_if_index)])
472 route_tun_dst.add_vpp_config()
475 # Send a packet stream that is routed into the tunnel
476 # packets are sent in on pg0 which is in the default table
477 # - packets are GRE encapped
479 self.vapi.cli("clear trace")
480 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
481 self.pg0.add_stream(tx)
483 self.pg_enable_capture(self.pg_interfaces)
486 rx = self.pg1.get_capture()
487 self.verify_tunneled_4o4(self.pg1, rx, tx,
488 self.pg1.local_ip4, "2.2.2.2")
491 # Send tunneled packets that match the created tunnel and
492 # are decapped and forwarded. This tests the decap lookup
493 # does not happen in the encap table
495 self.vapi.cli("clear trace")
496 tx = self.create_tunnel_stream_4o4(self.pg1,
501 self.pg1.add_stream(tx)
503 self.pg_enable_capture(self.pg_interfaces)
506 rx = self.pg0.get_capture()
507 self.verify_decapped_4o4(self.pg0, rx, tx)
512 route_tun_dst.remove_vpp_config()
513 route_via_tun.remove_vpp_config()
514 gre_if.remove_vpp_config()
516 def test_gre_l2(self):
517 """ GRE tunnel L2 Tests """
520 # Add routes to resolve the tunnel destinations
522 route_tun1_dst = IpRoute(self, "2.2.2.2", 32,
523 [RoutePath(self.pg0.remote_ip4,
524 self.pg0.sw_if_index)])
525 route_tun2_dst = IpRoute(self, "2.2.2.3", 32,
526 [RoutePath(self.pg0.remote_ip4,
527 self.pg0.sw_if_index)])
529 route_tun1_dst.add_vpp_config()
530 route_tun2_dst.add_vpp_config()
533 # Create 2 L2 GRE tunnels and x-connect them
535 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
538 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
541 gre_if1.add_vpp_config()
542 gre_if2.add_vpp_config()
547 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
550 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
555 # Send in tunnel encapped L2. expect out tunnel encapped L2
558 self.vapi.cli("clear trace")
559 tx = self.create_tunnel_stream_l2o4(self.pg0,
562 self.pg0.add_stream(tx)
564 self.pg_enable_capture(self.pg_interfaces)
567 rx = self.pg0.get_capture()
568 self.verify_tunneled_l2o4(self.pg0, rx, tx,
572 self.vapi.cli("clear trace")
573 tx = self.create_tunnel_stream_l2o4(self.pg0,
576 self.pg0.add_stream(tx)
578 self.pg_enable_capture(self.pg_interfaces)
581 rx = self.pg0.get_capture()
582 self.verify_tunneled_l2o4(self.pg0, rx, tx,
586 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
589 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
594 # Create a VLAN sub-interfaces on the GRE TEB interfaces
595 # then x-connect them
597 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
598 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
600 # gre_if_11.add_vpp_config()
601 # gre_if_12.add_vpp_config()
606 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
607 gre_if_12.sw_if_index,
609 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
610 gre_if_11.sw_if_index,
614 # Configure both to pop thier respective VLAN tags,
615 # so that during the x-coonect they will subsequently push
617 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
620 self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
625 # Send traffic in both directiond - expect the VLAN tags to
628 self.vapi.cli("clear trace")
629 tx = self.create_tunnel_stream_vlano4(self.pg0,
633 self.pg0.add_stream(tx)
635 self.pg_enable_capture(self.pg_interfaces)
638 rx = self.pg0.get_capture()
639 self.verify_tunneled_vlano4(self.pg0, rx, tx,
644 self.vapi.cli("clear trace")
645 tx = self.create_tunnel_stream_vlano4(self.pg0,
649 self.pg0.add_stream(tx)
651 self.pg_enable_capture(self.pg_interfaces)
654 rx = self.pg0.get_capture()
655 self.verify_tunneled_vlano4(self.pg0, rx, tx,
661 # Cleanup Test resources
663 gre_if_11.remove_vpp_config()
664 gre_if_12.remove_vpp_config()
665 gre_if1.remove_vpp_config()
666 gre_if2.remove_vpp_config()
667 route_tun1_dst.add_vpp_config()
668 route_tun2_dst.add_vpp_config()
671 if __name__ == '__main__':
672 unittest.main(testRunner=VppTestRunner)