6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
8 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
9 MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable
10 from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether
14 from scapy.layers.inet import IP, UDP, ICMP
15 from scapy.layers.inet6 import IPv6
16 from scapy.contrib.mpls import MPLS
19 def verify_filter(capture, sent):
20 if not len(capture) == len(sent):
21 # filter out any IPv6 RAs from the capture
28 def verify_mpls_stack(tst, rx, mpls_labels, ttl=255, num=0):
29 # the rx'd packet has the MPLS label popped
31 tst.assertEqual(eth.type, 0x8847)
35 for ii in range(len(mpls_labels)):
36 tst.assertEqual(rx_mpls.label, mpls_labels[ii])
37 tst.assertEqual(rx_mpls.cos, 0)
39 tst.assertEqual(rx_mpls.ttl, ttl)
41 tst.assertEqual(rx_mpls.ttl, 255)
42 if ii == len(mpls_labels) - 1:
43 tst.assertEqual(rx_mpls.s, 1)
46 tst.assertEqual(rx_mpls.s, 0)
47 # pop the label to expose the next
48 rx_mpls = rx_mpls[MPLS].payload
51 class TestMPLS(VppTestCase):
52 """ MPLS Test Case """
55 super(TestMPLS, self).setUp()
57 # create 2 pg interfaces
58 self.create_pg_interfaces(range(4))
60 # setup both interfaces
61 # assign them different tables.
65 tbl = VppMplsTable(self, 0)
67 self.tables.append(tbl)
69 for i in self.pg_interfaces:
73 tbl = VppIpTable(self, table_id)
75 self.tables.append(tbl)
76 tbl = VppIpTable(self, table_id, is_ip6=1)
78 self.tables.append(tbl)
80 i.set_table_ip4(table_id)
81 i.set_table_ip6(table_id)
90 for i in self.pg_interfaces:
98 super(TestMPLS, self).tearDown()
100 # the default of 64 matches the IP packet TTL default
101 def create_stream_labelled_ip4(
111 self.reset_packet_infos()
113 for i in range(0, n):
114 info = self.create_packet_info(src_if, src_if)
115 payload = self.info_to_payload(info)
116 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
118 for ii in range(len(mpls_labels)):
119 if ii == len(mpls_labels) - 1:
120 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
122 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
125 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
126 UDP(sport=1234, dport=1234) /
129 p = (p / IP(src=src_if.local_ip4, dst=dst_ip) /
130 UDP(sport=1234, dport=1234) /
133 p = (p / IP(src=ip_itf.remote_ip4,
134 dst=ip_itf.local_ip4) /
138 p[IP].chksum = chksum
143 def create_stream_ip4(self, src_if, dst_ip):
144 self.reset_packet_infos()
146 for i in range(0, 257):
147 info = self.create_packet_info(src_if, src_if)
148 payload = self.info_to_payload(info)
149 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
150 IP(src=src_if.remote_ip4, dst=dst_ip) /
151 UDP(sport=1234, dport=1234) /
157 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl,
158 dst_ip=None, hlim=64):
160 dst_ip = src_if.remote_ip6
161 self.reset_packet_infos()
163 for i in range(0, 257):
164 info = self.create_packet_info(src_if, src_if)
165 payload = self.info_to_payload(info)
166 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
167 MPLS(label=mpls_label, ttl=mpls_ttl) /
168 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
169 UDP(sport=1234, dport=1234) /
175 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
177 capture = verify_filter(capture, sent)
179 self.assertEqual(len(capture), len(sent))
181 for i in range(len(capture)):
185 # the rx'd packet has the MPLS label popped
187 self.assertEqual(eth.type, 0x800)
193 self.assertEqual(rx_ip.src, tx_ip.src)
194 self.assertEqual(rx_ip.dst, tx_ip.dst)
195 # IP processing post pop has decremented the TTL
196 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
198 self.assertEqual(rx_ip.src, tx_ip.dst)
199 self.assertEqual(rx_ip.dst, tx_ip.src)
204 def verify_capture_labelled_ip4(self, src_if, capture, sent,
207 capture = verify_filter(capture, sent)
209 self.assertEqual(len(capture), len(sent))
211 for i in range(len(capture)):
217 # the MPLS TTL is copied from the IP
218 verify_mpls_stack(self, rx, mpls_labels, rx_ip.ttl,
219 len(mpls_labels) - 1)
221 self.assertEqual(rx_ip.src, tx_ip.src)
222 self.assertEqual(rx_ip.dst, tx_ip.dst)
223 # IP processing post pop has decremented the TTL
224 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
229 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
232 top = len(mpls_labels) - 1
234 capture = verify_filter(capture, sent)
236 self.assertEqual(len(capture), len(sent))
238 for i in range(len(capture)):
244 # the MPLS TTL is 255 since it enters a new tunnel
245 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
247 self.assertEqual(rx_ip.src, tx_ip.src)
248 self.assertEqual(rx_ip.dst, tx_ip.dst)
249 # IP processing post pop has decremented the TTL
250 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
255 def verify_capture_labelled(self, src_if, capture, sent,
256 mpls_labels, ttl=254, num=0):
258 capture = verify_filter(capture, sent)
260 self.assertEqual(len(capture), len(sent))
262 for i in range(len(capture)):
264 verify_mpls_stack(self, rx, mpls_labels, ttl, num)
268 def verify_capture_ip6(self, src_if, capture, sent):
270 self.assertEqual(len(capture), len(sent))
272 for i in range(len(capture)):
276 # the rx'd packet has the MPLS label popped
278 self.assertEqual(eth.type, 0x86DD)
283 self.assertEqual(rx_ip.src, tx_ip.src)
284 self.assertEqual(rx_ip.dst, tx_ip.dst)
285 # IP processing post pop has decremented the TTL
286 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
291 def send_and_assert_no_replies(self, intf, pkts, remark):
292 intf.add_stream(pkts)
293 self.pg_enable_capture(self.pg_interfaces)
295 for i in self.pg_interfaces:
296 i.assert_nothing_captured(remark=remark)
299 """ MPLS label swap tests """
302 # A simple MPLS xconnect - eos label in label out
304 route_32_eos = VppMplsRoute(self, 32, 1,
305 [VppRoutePath(self.pg0.remote_ip4,
306 self.pg0.sw_if_index,
308 route_32_eos.add_vpp_config()
311 # a stream that matches the route for 10.0.0.1
312 # PG0 is in the default table
314 self.vapi.cli("clear trace")
315 tx = self.create_stream_labelled_ip4(self.pg0, [32])
316 self.pg0.add_stream(tx)
318 self.pg_enable_capture(self.pg_interfaces)
321 rx = self.pg0.get_capture()
322 self.verify_capture_labelled(self.pg0, rx, tx, [33])
325 # A simple MPLS xconnect - non-eos label in label out
327 route_32_neos = VppMplsRoute(self, 32, 0,
328 [VppRoutePath(self.pg0.remote_ip4,
329 self.pg0.sw_if_index,
331 route_32_neos.add_vpp_config()
334 # a stream that matches the route for 10.0.0.1
335 # PG0 is in the default table
337 self.vapi.cli("clear trace")
338 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
339 self.pg0.add_stream(tx)
341 self.pg_enable_capture(self.pg_interfaces)
344 rx = self.pg0.get_capture()
345 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
348 # An MPLS xconnect - EOS label in IP out
350 route_33_eos = VppMplsRoute(self, 33, 1,
351 [VppRoutePath(self.pg0.remote_ip4,
352 self.pg0.sw_if_index,
354 route_33_eos.add_vpp_config()
356 self.vapi.cli("clear trace")
357 tx = self.create_stream_labelled_ip4(self.pg0, [33])
358 self.pg0.add_stream(tx)
360 self.pg_enable_capture(self.pg_interfaces)
363 rx = self.pg0.get_capture()
364 self.verify_capture_ip4(self.pg0, rx, tx)
367 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
368 # so this traffic should be dropped.
370 route_33_neos = VppMplsRoute(self, 33, 0,
371 [VppRoutePath(self.pg0.remote_ip4,
372 self.pg0.sw_if_index,
374 route_33_neos.add_vpp_config()
376 self.vapi.cli("clear trace")
377 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
378 self.pg0.add_stream(tx)
380 self.pg_enable_capture(self.pg_interfaces)
382 self.pg0.assert_nothing_captured(
383 remark="MPLS non-EOS packets popped and forwarded")
386 # A recursive EOS x-connect, which resolves through another x-connect
388 route_34_eos = VppMplsRoute(self, 34, 1,
389 [VppRoutePath("0.0.0.0",
393 route_34_eos.add_vpp_config()
395 tx = self.create_stream_labelled_ip4(self.pg0, [34])
396 self.pg0.add_stream(tx)
398 self.pg_enable_capture(self.pg_interfaces)
401 rx = self.pg0.get_capture()
402 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
405 # A recursive non-EOS x-connect, which resolves through another
408 route_34_neos = VppMplsRoute(self, 34, 0,
409 [VppRoutePath("0.0.0.0",
413 route_34_neos.add_vpp_config()
415 self.vapi.cli("clear trace")
416 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
417 self.pg0.add_stream(tx)
419 self.pg_enable_capture(self.pg_interfaces)
422 rx = self.pg0.get_capture()
423 # it's the 2nd (counting from 0) label in the stack that is swapped
424 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
427 # an recursive IP route that resolves through the recursive non-eos
430 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
431 [VppRoutePath("0.0.0.0",
435 ip_10_0_0_1.add_vpp_config()
437 self.vapi.cli("clear trace")
438 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
439 self.pg0.add_stream(tx)
441 self.pg_enable_capture(self.pg_interfaces)
444 rx = self.pg0.get_capture()
445 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
447 ip_10_0_0_1.remove_vpp_config()
448 route_34_neos.remove_vpp_config()
449 route_34_eos.remove_vpp_config()
450 route_33_neos.remove_vpp_config()
451 route_33_eos.remove_vpp_config()
452 route_32_neos.remove_vpp_config()
453 route_32_eos.remove_vpp_config()
456 """ MPLS Local Label Binding test """
459 # Add a non-recursive route with a single out label
461 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
462 [VppRoutePath(self.pg0.remote_ip4,
463 self.pg0.sw_if_index,
465 route_10_0_0_1.add_vpp_config()
467 # bind a local label to the route
468 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
469 binding.add_vpp_config()
472 self.vapi.cli("clear trace")
473 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
474 self.pg0.add_stream(tx)
476 self.pg_enable_capture(self.pg_interfaces)
479 rx = self.pg0.get_capture()
480 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
483 self.vapi.cli("clear trace")
484 tx = self.create_stream_labelled_ip4(self.pg0, [44])
485 self.pg0.add_stream(tx)
487 self.pg_enable_capture(self.pg_interfaces)
490 rx = self.pg0.get_capture()
491 self.verify_capture_labelled(self.pg0, rx, tx, [45])
494 self.vapi.cli("clear trace")
495 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
496 self.pg0.add_stream(tx)
498 self.pg_enable_capture(self.pg_interfaces)
501 rx = self.pg0.get_capture()
502 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
507 binding.remove_vpp_config()
508 route_10_0_0_1.remove_vpp_config()
510 def test_imposition(self):
511 """ MPLS label imposition test """
514 # Add a non-recursive route with a single out label
516 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
517 [VppRoutePath(self.pg0.remote_ip4,
518 self.pg0.sw_if_index,
520 route_10_0_0_1.add_vpp_config()
523 # a stream that matches the route for 10.0.0.1
524 # PG0 is in the default table
526 self.vapi.cli("clear trace")
527 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
528 self.pg0.add_stream(tx)
530 self.pg_enable_capture(self.pg_interfaces)
533 rx = self.pg0.get_capture()
534 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
537 # Add a non-recursive route with a 3 out labels
539 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
540 [VppRoutePath(self.pg0.remote_ip4,
541 self.pg0.sw_if_index,
542 labels=[32, 33, 34])])
543 route_10_0_0_2.add_vpp_config()
546 # a stream that matches the route for 10.0.0.1
547 # PG0 is in the default table
549 self.vapi.cli("clear trace")
550 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
551 self.pg0.add_stream(tx)
553 self.pg_enable_capture(self.pg_interfaces)
556 rx = self.pg0.get_capture()
557 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
560 # add a recursive path, with output label, via the 1 label route
562 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
563 [VppRoutePath("10.0.0.1",
566 route_11_0_0_1.add_vpp_config()
569 # a stream that matches the route for 11.0.0.1, should pick up
570 # the label stack for 11.0.0.1 and 10.0.0.1
572 self.vapi.cli("clear trace")
573 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
574 self.pg0.add_stream(tx)
576 self.pg_enable_capture(self.pg_interfaces)
579 rx = self.pg0.get_capture()
580 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
583 # add a recursive path, with 2 labels, via the 3 label route
585 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
586 [VppRoutePath("10.0.0.2",
589 route_11_0_0_2.add_vpp_config()
592 # a stream that matches the route for 11.0.0.1, should pick up
593 # the label stack for 11.0.0.1 and 10.0.0.1
595 self.vapi.cli("clear trace")
596 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
597 self.pg0.add_stream(tx)
599 self.pg_enable_capture(self.pg_interfaces)
602 rx = self.pg0.get_capture()
603 self.verify_capture_labelled_ip4(
604 self.pg0, rx, tx, [32, 33, 34, 44, 45])
609 route_11_0_0_2.remove_vpp_config()
610 route_11_0_0_1.remove_vpp_config()
611 route_10_0_0_2.remove_vpp_config()
612 route_10_0_0_1.remove_vpp_config()
614 def test_tunnel(self):
615 """ MPLS Tunnel Tests """
618 # Create a tunnel with a single out label
620 mpls_tun = VppMPLSTunnelInterface(self,
621 [VppRoutePath(self.pg0.remote_ip4,
622 self.pg0.sw_if_index,
624 mpls_tun.add_vpp_config()
628 # add an unlabelled route through the new tunnel
630 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
631 [VppRoutePath("0.0.0.0",
632 mpls_tun._sw_if_index)])
633 route_10_0_0_3.add_vpp_config()
635 self.vapi.cli("clear trace")
636 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
637 self.pg0.add_stream(tx)
639 self.pg_enable_capture(self.pg_interfaces)
642 rx = self.pg0.get_capture()
643 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
646 # add a labelled route through the new tunnel
648 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
649 [VppRoutePath("0.0.0.0",
650 mpls_tun._sw_if_index,
652 route_10_0_0_4.add_vpp_config()
654 self.vapi.cli("clear trace")
655 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
656 self.pg0.add_stream(tx)
658 self.pg_enable_capture(self.pg_interfaces)
661 rx = self.pg0.get_capture()
662 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
665 def test_v4_exp_null(self):
666 """ MPLS V4 Explicit NULL test """
669 # The first test case has an MPLS TTL of 0
670 # all packet should be dropped
672 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
673 self.pg0.add_stream(tx)
675 self.pg_enable_capture(self.pg_interfaces)
678 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
681 # a stream with a non-zero MPLS TTL
682 # PG0 is in the default table
684 tx = self.create_stream_labelled_ip4(self.pg0, [0])
685 self.pg0.add_stream(tx)
687 self.pg_enable_capture(self.pg_interfaces)
690 rx = self.pg0.get_capture()
691 self.verify_capture_ip4(self.pg0, rx, tx)
694 # a stream with a non-zero MPLS TTL
696 # we are ensuring the post-pop lookup occurs in the VRF table
698 self.vapi.cli("clear trace")
699 tx = self.create_stream_labelled_ip4(self.pg1, [0])
700 self.pg1.add_stream(tx)
702 self.pg_enable_capture(self.pg_interfaces)
705 rx = self.pg1.get_capture()
706 self.verify_capture_ip4(self.pg0, rx, tx)
708 def test_v6_exp_null(self):
709 """ MPLS V6 Explicit NULL test """
712 # a stream with a non-zero MPLS TTL
713 # PG0 is in the default table
715 self.vapi.cli("clear trace")
716 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
717 self.pg0.add_stream(tx)
719 self.pg_enable_capture(self.pg_interfaces)
722 rx = self.pg0.get_capture()
723 self.verify_capture_ip6(self.pg0, rx, tx)
726 # a stream with a non-zero MPLS TTL
728 # we are ensuring the post-pop lookup occurs in the VRF table
730 self.vapi.cli("clear trace")
731 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
732 self.pg1.add_stream(tx)
734 self.pg_enable_capture(self.pg_interfaces)
737 rx = self.pg1.get_capture()
738 self.verify_capture_ip6(self.pg0, rx, tx)
744 # A de-agg route - next-hop lookup in default table
746 route_34_eos = VppMplsRoute(self, 34, 1,
747 [VppRoutePath("0.0.0.0",
750 route_34_eos.add_vpp_config()
753 # ping an interface in the default table
754 # PG0 is in the default table
756 self.vapi.cli("clear trace")
757 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
759 self.pg0.add_stream(tx)
761 self.pg_enable_capture(self.pg_interfaces)
764 rx = self.pg0.get_capture()
765 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
768 # A de-agg route - next-hop lookup in non-default table
770 route_35_eos = VppMplsRoute(self, 35, 1,
771 [VppRoutePath("0.0.0.0",
774 route_35_eos.add_vpp_config()
777 # ping an interface in the non-default table
778 # PG0 is in the default table. packet arrive labelled in the
779 # default table and egress unlabelled in the non-default
781 self.vapi.cli("clear trace")
782 tx = self.create_stream_labelled_ip4(
783 self.pg0, [35], ping=1, ip_itf=self.pg1)
784 self.pg0.add_stream(tx)
786 self.pg_enable_capture(self.pg_interfaces)
789 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
790 rx = self.pg1.get_capture(packet_count)
791 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
796 route_36_neos = VppMplsRoute(self, 36, 0,
797 [VppRoutePath("0.0.0.0",
799 route_36_neos.add_vpp_config()
801 self.vapi.cli("clear trace")
802 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
803 ping=1, ip_itf=self.pg1)
804 self.pg0.add_stream(tx)
806 self.pg_enable_capture(self.pg_interfaces)
809 rx = self.pg1.get_capture(len(tx))
810 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
812 route_36_neos.remove_vpp_config()
813 route_35_eos.remove_vpp_config()
814 route_34_eos.remove_vpp_config()
816 def test_interface_rx(self):
817 """ MPLS Interface Receive """
820 # Add a non-recursive route that will forward the traffic
823 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
825 paths=[VppRoutePath(self.pg1.remote_ip4,
826 self.pg1.sw_if_index)])
827 route_10_0_0_1.add_vpp_config()
830 # An interface receive label that maps traffic to RX on interface
832 # by injecting the packet in on pg0, which is in table 0
833 # doing an interface-rx on pg1 and matching a route in table 1
834 # if the packet egresses, then we must have swapped to pg1
835 # so as to have matched the route in table 1
837 route_34_eos = VppMplsRoute(self, 34, 1,
838 [VppRoutePath("0.0.0.0",
839 self.pg1.sw_if_index,
841 route_34_eos.add_vpp_config()
844 # ping an interface in the default table
845 # PG0 is in the default table
847 self.vapi.cli("clear trace")
848 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
850 self.pg0.add_stream(tx)
852 self.pg_enable_capture(self.pg_interfaces)
855 rx = self.pg1.get_capture(257)
856 self.verify_capture_ip4(self.pg1, rx, tx)
858 def test_mcast_mid_point(self):
859 """ MPLS Multicast Mid Point """
862 # Add a non-recursive route that will forward the traffic
865 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
867 paths=[VppRoutePath(self.pg1.remote_ip4,
868 self.pg1.sw_if_index)])
869 route_10_0_0_1.add_vpp_config()
872 # Add a mcast entry that replicate to pg2 and pg3
873 # and replicate to a interface-rx (like a bud node would)
875 route_3400_eos = VppMplsRoute(self, 3400, 1,
876 [VppRoutePath(self.pg2.remote_ip4,
877 self.pg2.sw_if_index,
879 VppRoutePath(self.pg3.remote_ip4,
880 self.pg3.sw_if_index,
882 VppRoutePath("0.0.0.0",
883 self.pg1.sw_if_index,
886 route_3400_eos.add_vpp_config()
889 # ping an interface in the default table
890 # PG0 is in the default table
892 self.vapi.cli("clear trace")
893 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
895 self.pg0.add_stream(tx)
897 self.pg_enable_capture(self.pg_interfaces)
900 rx = self.pg1.get_capture(257)
901 self.verify_capture_ip4(self.pg1, rx, tx)
903 rx = self.pg2.get_capture(257)
904 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
905 rx = self.pg3.get_capture(257)
906 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
908 def test_mcast_head(self):
909 """ MPLS Multicast Head-end """
912 # Create a multicast tunnel with two replications
914 mpls_tun = VppMPLSTunnelInterface(self,
915 [VppRoutePath(self.pg2.remote_ip4,
916 self.pg2.sw_if_index,
918 VppRoutePath(self.pg3.remote_ip4,
919 self.pg3.sw_if_index,
922 mpls_tun.add_vpp_config()
926 # add an unlabelled route through the new tunnel
928 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
929 [VppRoutePath("0.0.0.0",
930 mpls_tun._sw_if_index)])
931 route_10_0_0_3.add_vpp_config()
933 self.vapi.cli("clear trace")
934 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
935 self.pg0.add_stream(tx)
937 self.pg_enable_capture(self.pg_interfaces)
940 rx = self.pg2.get_capture(257)
941 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
942 rx = self.pg3.get_capture(257)
943 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
946 # An an IP multicast route via the tunnel
948 # one accepting interface, pg0, 1 forwarding interface via the tunnel
950 route_232_1_1_1 = VppIpMRoute(
954 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
955 [VppMRoutePath(self.pg0.sw_if_index,
956 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
957 VppMRoutePath(mpls_tun._sw_if_index,
958 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
959 route_232_1_1_1.add_vpp_config()
961 self.vapi.cli("clear trace")
962 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
963 self.pg0.add_stream(tx)
965 self.pg_enable_capture(self.pg_interfaces)
968 rx = self.pg2.get_capture(257)
969 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
970 rx = self.pg3.get_capture(257)
971 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
973 def test_mcast_ip4_tail(self):
974 """ MPLS IPv4 Multicast Tail """
977 # Add a multicast route that will forward the traffic
980 route_232_1_1_1 = VppIpMRoute(
984 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
986 paths=[VppMRoutePath(self.pg1.sw_if_index,
987 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
988 route_232_1_1_1.add_vpp_config()
991 # An interface receive label that maps traffic to RX on interface
993 # by injecting the packet in on pg0, which is in table 0
994 # doing an rpf-id and matching a route in table 1
995 # if the packet egresses, then we must have matched the route in
998 route_34_eos = VppMplsRoute(self, 34, 1,
999 [VppRoutePath("0.0.0.0",
1000 self.pg1.sw_if_index,
1005 route_34_eos.add_vpp_config()
1008 # Drop due to interface lookup miss
1010 self.vapi.cli("clear trace")
1011 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1012 dst_ip="232.1.1.1", n=1)
1013 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1016 # set the RPF-ID of the enrtry to match the input packet's
1018 route_232_1_1_1.update_rpf_id(55)
1020 self.vapi.cli("clear trace")
1021 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1022 dst_ip="232.1.1.1", n=257)
1023 self.pg0.add_stream(tx)
1025 self.pg_enable_capture(self.pg_interfaces)
1028 rx = self.pg1.get_capture(257)
1029 self.verify_capture_ip4(self.pg1, rx, tx)
1032 # disposed packets have an invalid IPv4 checkusm
1034 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1035 dst_ip="232.1.1.1", n=65,
1037 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1040 # set the RPF-ID of the enrtry to not match the input packet's
1042 route_232_1_1_1.update_rpf_id(56)
1043 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1045 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1046 self.logger.error(self.vapi.cli("sh error"))
1048 def test_mcast_ip6_tail(self):
1049 """ MPLS IPv6 Multicast Tail """
1052 # Add a multicast route that will forward the traffic
1055 route_ff = VppIpMRoute(
1059 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1061 paths=[VppMRoutePath(self.pg1.sw_if_index,
1062 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1064 route_ff.add_vpp_config()
1067 # An interface receive label that maps traffic to RX on interface
1069 # by injecting the packet in on pg0, which is in table 0
1070 # doing an rpf-id and matching a route in table 1
1071 # if the packet egresses, then we must have matched the route in
1074 route_34_eos = VppMplsRoute(
1077 self.pg1.sw_if_index,
1080 proto=DpoProto.DPO_PROTO_IP6)],
1083 route_34_eos.add_vpp_config()
1086 # Drop due to interface lookup miss
1088 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1092 # set the RPF-ID of the enrtry to match the input packet's
1094 route_ff.update_rpf_id(55)
1096 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1098 self.pg0.add_stream(tx)
1100 self.pg_enable_capture(self.pg_interfaces)
1103 rx = self.pg1.get_capture(257)
1104 self.verify_capture_ip6(self.pg1, rx, tx)
1107 # disposed packets have hop-limit = 1
1109 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1110 dst_ip="ff01::1", hlim=1)
1111 self.send_and_assert_no_replies(self.pg0, tx, "Hop Limt Expired")
1114 # set the RPF-ID of the enrtry to not match the input packet's
1116 route_ff.update_rpf_id(56)
1117 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1119 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1122 class TestMPLSDisabled(VppTestCase):
1123 """ MPLS disabled """
1126 super(TestMPLSDisabled, self).setUp()
1128 # create 2 pg interfaces
1129 self.create_pg_interfaces(range(2))
1131 self.tbl = VppMplsTable(self, 0)
1132 self.tbl.add_vpp_config()
1134 # PG0 is MPLS enalbed
1136 self.pg0.config_ip4()
1137 self.pg0.resolve_arp()
1138 self.pg0.enable_mpls()
1140 # PG 1 is not MPLS enabled
1144 for i in self.pg_interfaces:
1148 self.pg0.disable_mpls()
1149 super(TestMPLSDisabled, self).tearDown()
1151 def send_and_assert_no_replies(self, intf, pkts, remark):
1152 intf.add_stream(pkts)
1153 self.pg_enable_capture(self.pg_interfaces)
1155 for i in self.pg_interfaces:
1157 i.assert_nothing_captured(remark=remark)
1159 def test_mpls_disabled(self):
1160 """ MPLS Disabled """
1162 tx = (Ether(src=self.pg1.remote_mac,
1163 dst=self.pg1.local_mac) /
1164 MPLS(label=32, ttl=64) /
1165 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1166 UDP(sport=1234, dport=1234) /
1170 # A simple MPLS xconnect - eos label in label out
1172 route_32_eos = VppMplsRoute(self, 32, 1,
1173 [VppRoutePath(self.pg0.remote_ip4,
1174 self.pg0.sw_if_index,
1176 route_32_eos.add_vpp_config()
1179 # PG1 does not forward IP traffic
1181 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1186 self.pg1.enable_mpls()
1189 # Now we get packets through
1191 self.pg1.add_stream(tx)
1192 self.pg_enable_capture(self.pg_interfaces)
1195 rx = self.pg0.get_capture(1)
1200 self.pg1.disable_mpls()
1203 # PG1 does not forward IP traffic
1205 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1206 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1209 class TestMPLSPIC(VppTestCase):
1210 """ MPLS PIC edge convergence """
1213 super(TestMPLSPIC, self).setUp()
1215 # create 2 pg interfaces
1216 self.create_pg_interfaces(range(4))
1218 mpls_tbl = VppMplsTable(self, 0)
1219 mpls_tbl.add_vpp_config()
1220 tbl4 = VppIpTable(self, 1)
1221 tbl4.add_vpp_config()
1222 tbl6 = VppIpTable(self, 1, is_ip6=1)
1223 tbl6.add_vpp_config()
1227 self.pg0.config_ip4()
1228 self.pg0.resolve_arp()
1229 self.pg0.enable_mpls()
1231 self.pg1.config_ip4()
1232 self.pg1.resolve_arp()
1233 self.pg1.enable_mpls()
1235 # VRF (customer facing) link
1237 self.pg2.set_table_ip4(1)
1238 self.pg2.config_ip4()
1239 self.pg2.resolve_arp()
1240 self.pg2.set_table_ip6(1)
1241 self.pg2.config_ip6()
1242 self.pg2.resolve_ndp()
1244 self.pg3.set_table_ip4(1)
1245 self.pg3.config_ip4()
1246 self.pg3.resolve_arp()
1247 self.pg3.set_table_ip6(1)
1248 self.pg3.config_ip6()
1249 self.pg3.resolve_ndp()
1252 self.pg0.disable_mpls()
1253 self.pg1.disable_mpls()
1254 for i in self.pg_interfaces:
1260 super(TestMPLSPIC, self).tearDown()
1262 def test_mpls_ibgp_pic(self):
1263 """ MPLS iBGP PIC edge convergence
1265 1) setup many iBGP VPN routes via a pair of iBGP peers.
1266 2) Check EMCP forwarding to these peers
1267 3) withdraw the IGP route to one of these peers.
1268 4) check forwarding continues to the remaining peer
1272 # IGP+LDP core routes
1274 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1275 [VppRoutePath(self.pg0.remote_ip4,
1276 self.pg0.sw_if_index,
1278 core_10_0_0_45.add_vpp_config()
1280 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1281 [VppRoutePath(self.pg1.remote_ip4,
1282 self.pg1.sw_if_index,
1284 core_10_0_0_46.add_vpp_config()
1287 # Lot's of VPN routes. We need more the 64 so VPP will build
1288 # the fast convergence indirection
1292 for ii in range(64):
1293 dst = "192.168.1.%d" % ii
1294 vpn_routes.append(VppIpRoute(self, dst, 32,
1295 [VppRoutePath("10.0.0.45",
1299 VppRoutePath("10.0.0.46",
1302 is_resolve_host=1)],
1304 vpn_routes[ii].add_vpp_config()
1306 pkts.append(Ether(dst=self.pg2.local_mac,
1307 src=self.pg2.remote_mac) /
1308 IP(src=self.pg2.remote_ip4, dst=dst) /
1309 UDP(sport=1234, dport=1234) /
1313 # Send the packet stream (one pkt to each VPN route)
1314 # - expect a 50-50 split of the traffic
1316 self.pg2.add_stream(pkts)
1317 self.pg_enable_capture(self.pg_interfaces)
1320 rx0 = self.pg0._get_capture(1)
1321 rx1 = self.pg1._get_capture(1)
1323 # not testig the LB hashing algorithm so we're not concerned
1324 # with the split ratio, just as long as neither is 0
1325 self.assertNotEqual(0, len(rx0))
1326 self.assertNotEqual(0, len(rx1))
1329 # use a test CLI command to stop the FIB walk process, this
1330 # will prevent the FIB converging the VPN routes and thus allow
1331 # us to probe the interim (psot-fail, pre-converge) state
1333 self.vapi.ppcli("test fib-walk-process disable")
1336 # Withdraw one of the IGP routes
1338 core_10_0_0_46.remove_vpp_config()
1341 # now all packets should be forwarded through the remaining peer
1343 self.vapi.ppcli("clear trace")
1344 self.pg2.add_stream(pkts)
1345 self.pg_enable_capture(self.pg_interfaces)
1348 rx0 = self.pg0.get_capture(len(pkts))
1351 # enable the FIB walk process to converge the FIB
1353 self.vapi.ppcli("test fib-walk-process enable")
1356 # packets should still be forwarded through the remaining peer
1358 self.pg2.add_stream(pkts)
1359 self.pg_enable_capture(self.pg_interfaces)
1362 rx0 = self.pg0.get_capture(64)
1365 # Add the IGP route back and we return to load-balancing
1367 core_10_0_0_46.add_vpp_config()
1369 self.pg2.add_stream(pkts)
1370 self.pg_enable_capture(self.pg_interfaces)
1373 rx0 = self.pg0._get_capture(1)
1374 rx1 = self.pg1._get_capture(1)
1375 self.assertNotEqual(0, len(rx0))
1376 self.assertNotEqual(0, len(rx1))
1378 def test_mpls_ebgp_pic(self):
1379 """ MPLS eBGP PIC edge convergence
1381 1) setup many eBGP VPN routes via a pair of eBGP peers
1382 2) Check EMCP forwarding to these peers
1383 3) withdraw one eBGP path - expect LB across remaining eBGP
1387 # Lot's of VPN routes. We need more the 64 so VPP will build
1388 # the fast convergence indirection
1393 for ii in range(64):
1394 dst = "192.168.1.%d" % ii
1395 local_label = 1600 + ii
1396 vpn_routes.append(VppIpRoute(self, dst, 32,
1397 [VppRoutePath(self.pg2.remote_ip4,
1400 is_resolve_attached=1),
1401 VppRoutePath(self.pg3.remote_ip4,
1404 is_resolve_attached=1)],
1406 vpn_routes[ii].add_vpp_config()
1408 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1410 vpn_bindings[ii].add_vpp_config()
1412 pkts.append(Ether(dst=self.pg0.local_mac,
1413 src=self.pg0.remote_mac) /
1414 MPLS(label=local_label, ttl=64) /
1415 IP(src=self.pg0.remote_ip4, dst=dst) /
1416 UDP(sport=1234, dport=1234) /
1419 self.pg0.add_stream(pkts)
1420 self.pg_enable_capture(self.pg_interfaces)
1423 rx0 = self.pg2._get_capture(1)
1424 rx1 = self.pg3._get_capture(1)
1425 self.assertNotEqual(0, len(rx0))
1426 self.assertNotEqual(0, len(rx1))
1429 # use a test CLI command to stop the FIB walk process, this
1430 # will prevent the FIB converging the VPN routes and thus allow
1431 # us to probe the interim (psot-fail, pre-converge) state
1433 self.vapi.ppcli("test fib-walk-process disable")
1436 # withdraw the connected prefix on the interface.
1438 self.pg2.unconfig_ip4()
1441 # now all packets should be forwarded through the remaining peer
1443 self.pg0.add_stream(pkts)
1444 self.pg_enable_capture(self.pg_interfaces)
1447 rx0 = self.pg3.get_capture(len(pkts))
1450 # enable the FIB walk process to converge the FIB
1452 self.vapi.ppcli("test fib-walk-process enable")
1453 self.pg0.add_stream(pkts)
1454 self.pg_enable_capture(self.pg_interfaces)
1457 rx0 = self.pg3.get_capture(len(pkts))
1460 # put the connecteds back
1462 self.pg2.config_ip4()
1464 self.pg0.add_stream(pkts)
1465 self.pg_enable_capture(self.pg_interfaces)
1468 rx0 = self.pg2._get_capture(1)
1469 rx1 = self.pg3._get_capture(1)
1470 self.assertNotEqual(0, len(rx0))
1471 self.assertNotEqual(0, len(rx1))
1473 def test_mpls_v6_ebgp_pic(self):
1474 """ MPLSv6 eBGP PIC edge convergence
1476 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1477 2) Check EMCP forwarding to these peers
1478 3) withdraw one eBGP path - expect LB across remaining eBGP
1482 # Lot's of VPN routes. We need more the 64 so VPP will build
1483 # the fast convergence indirection
1488 for ii in range(64):
1489 dst = "3000::%d" % ii
1490 local_label = 1600 + ii
1491 vpn_routes.append(VppIpRoute(
1493 [VppRoutePath(self.pg2.remote_ip6,
1496 is_resolve_attached=1,
1497 proto=DpoProto.DPO_PROTO_IP6),
1498 VppRoutePath(self.pg3.remote_ip6,
1501 proto=DpoProto.DPO_PROTO_IP6,
1502 is_resolve_attached=1)],
1505 vpn_routes[ii].add_vpp_config()
1507 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1510 vpn_bindings[ii].add_vpp_config()
1512 pkts.append(Ether(dst=self.pg0.local_mac,
1513 src=self.pg0.remote_mac) /
1514 MPLS(label=local_label, ttl=64) /
1515 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1516 UDP(sport=1234, dport=1234) /
1519 self.pg0.add_stream(pkts)
1520 self.pg_enable_capture(self.pg_interfaces)
1523 rx0 = self.pg2._get_capture(1)
1524 rx1 = self.pg3._get_capture(1)
1525 self.assertNotEqual(0, len(rx0))
1526 self.assertNotEqual(0, len(rx1))
1529 # use a test CLI command to stop the FIB walk process, this
1530 # will prevent the FIB converging the VPN routes and thus allow
1531 # us to probe the interim (psot-fail, pre-converge) state
1533 self.vapi.ppcli("test fib-walk-process disable")
1536 # withdraw the connected prefix on the interface.
1537 # and shutdown the interface so the ND cache is flushed.
1539 self.pg2.unconfig_ip6()
1540 self.pg2.admin_down()
1543 # now all packets should be forwarded through the remaining peer
1545 self.pg0.add_stream(pkts)
1546 self.pg_enable_capture(self.pg_interfaces)
1549 rx0 = self.pg3.get_capture(len(pkts))
1552 # enable the FIB walk process to converge the FIB
1554 self.vapi.ppcli("test fib-walk-process enable")
1555 self.pg0.add_stream(pkts)
1556 self.pg_enable_capture(self.pg_interfaces)
1559 rx0 = self.pg3.get_capture(len(pkts))
1562 # put the connecteds back
1565 self.pg2.config_ip6()
1567 self.pg0.add_stream(pkts)
1568 self.pg_enable_capture(self.pg_interfaces)
1571 rx0 = self.pg2._get_capture(1)
1572 rx1 = self.pg3._get_capture(1)
1573 self.assertNotEqual(0, len(rx0))
1574 self.assertNotEqual(0, len(rx1))
1577 class TestMPLSL2(VppTestCase):
1581 super(TestMPLSL2, self).setUp()
1583 # create 2 pg interfaces
1584 self.create_pg_interfaces(range(2))
1586 # create the default MPLS table
1588 tbl = VppMplsTable(self, 0)
1589 tbl.add_vpp_config()
1590 self.tables.append(tbl)
1592 # use pg0 as the core facing interface
1594 self.pg0.config_ip4()
1595 self.pg0.resolve_arp()
1596 self.pg0.enable_mpls()
1598 # use the other 2 for customer facing L2 links
1599 for i in self.pg_interfaces[1:]:
1603 for i in self.pg_interfaces[1:]:
1606 self.pg0.disable_mpls()
1607 self.pg0.unconfig_ip4()
1608 self.pg0.admin_down()
1609 super(TestMPLSL2, self).tearDown()
1611 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1614 top = len(mpls_labels) - 1
1616 capture = verify_filter(capture, sent)
1618 self.assertEqual(len(capture), len(sent))
1620 for i in range(len(capture)):
1624 # the MPLS TTL is 255 since it enters a new tunnel
1625 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1628 rx_eth = Ether(str(rx[MPLS].payload))
1630 self.assertEqual(rx_eth.src, tx_eth.src)
1631 self.assertEqual(rx_eth.dst, tx_eth.dst)
1633 def test_vpws(self):
1634 """ Virtual Private Wire Service """
1637 # Create an MPLS tunnel that pushes 1 label
1639 mpls_tun_1 = VppMPLSTunnelInterface(self,
1640 [VppRoutePath(self.pg0.remote_ip4,
1641 self.pg0.sw_if_index,
1644 mpls_tun_1.add_vpp_config()
1645 mpls_tun_1.admin_up()
1648 # Create a label entry to for 55 that does L2 input to the tunnel
1650 route_55_eos = VppMplsRoute(
1652 [VppRoutePath("0.0.0.0",
1653 mpls_tun_1.sw_if_index,
1655 proto=DpoProto.DPO_PROTO_ETHERNET)])
1656 route_55_eos.add_vpp_config()
1659 # Cross-connect the tunnel with one of the customers L2 interfaces
1661 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1662 mpls_tun_1.sw_if_index,
1664 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1665 self.pg1.sw_if_index,
1669 # inject a packet from the core
1671 pcore = (Ether(dst=self.pg0.local_mac,
1672 src=self.pg0.remote_mac) /
1673 MPLS(label=55, ttl=64) /
1674 Ether(dst="00:00:de:ad:ba:be",
1675 src="00:00:de:ad:be:ef") /
1676 IP(src="10.10.10.10", dst="11.11.11.11") /
1677 UDP(sport=1234, dport=1234) /
1680 self.pg0.add_stream(pcore * 65)
1681 self.pg_enable_capture(self.pg_interfaces)
1684 rx0 = self.pg1.get_capture(65)
1685 tx = pcore[MPLS].payload
1687 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1688 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1691 # Inject a packet from the custoer/L2 side
1693 self.pg1.add_stream(tx * 65)
1694 self.pg_enable_capture(self.pg_interfaces)
1697 rx0 = self.pg0.get_capture(65)
1699 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1701 def test_vpls(self):
1702 """ Virtual Private LAN Service """
1704 # Create an L2 MPLS tunnel
1706 mpls_tun = VppMPLSTunnelInterface(self,
1707 [VppRoutePath(self.pg0.remote_ip4,
1708 self.pg0.sw_if_index,
1711 mpls_tun.add_vpp_config()
1715 # Create a label entry to for 55 that does L2 input to the tunnel
1717 route_55_eos = VppMplsRoute(
1719 [VppRoutePath("0.0.0.0",
1720 mpls_tun.sw_if_index,
1722 proto=DpoProto.DPO_PROTO_ETHERNET)])
1723 route_55_eos.add_vpp_config()
1726 # add to tunnel to the customers bridge-domain
1728 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1730 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1734 # Packet from the customer interface and from the core
1736 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1737 src="00:00:de:ad:be:ef") /
1738 IP(src="10.10.10.10", dst="11.11.11.11") /
1739 UDP(sport=1234, dport=1234) /
1741 p_core = (Ether(src="00:00:de:ad:ba:be",
1742 dst="00:00:de:ad:be:ef") /
1743 IP(dst="10.10.10.10", src="11.11.11.11") /
1744 UDP(sport=1234, dport=1234) /
1748 # The BD is learning, so send in one of each packet to learn
1750 p_core_encap = (Ether(dst=self.pg0.local_mac,
1751 src=self.pg0.remote_mac) /
1752 MPLS(label=55, ttl=64) /
1755 self.pg1.add_stream(p_cust)
1756 self.pg_enable_capture(self.pg_interfaces)
1758 self.pg0.add_stream(p_core_encap)
1759 self.pg_enable_capture(self.pg_interfaces)
1762 # we've learnt this so expect it be be forwarded
1763 rx0 = self.pg1.get_capture(1)
1765 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1766 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1769 # now a stream in each direction
1771 self.pg1.add_stream(p_cust * 65)
1772 self.pg_enable_capture(self.pg_interfaces)
1775 rx0 = self.pg0.get_capture(65)
1777 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1780 # remove interfaces from customers bridge-domain
1782 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1785 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1789 if __name__ == '__main__':
1790 unittest.main(testRunner=VppTestRunner)