6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
8 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
9 MRouteItfFlags, MRouteEntryFlags, DpoProto
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.
64 for i in self.pg_interfaces:
66 i.set_table_ip4(table_id)
67 i.set_table_ip6(table_id)
76 super(TestMPLS, self).tearDown()
77 for i in self.pg_interfaces:
83 # the default of 64 matches the IP packet TTL default
84 def create_stream_labelled_ip4(
93 self.reset_packet_infos()
96 info = self.create_packet_info(src_if, src_if)
97 payload = self.info_to_payload(info)
98 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
100 for ii in range(len(mpls_labels)):
101 if ii == len(mpls_labels) - 1:
102 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
104 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
107 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
108 UDP(sport=1234, dport=1234) /
111 p = (p / IP(src=src_if.local_ip4, dst=dst_ip) /
112 UDP(sport=1234, dport=1234) /
115 p = (p / IP(src=ip_itf.remote_ip4,
116 dst=ip_itf.local_ip4) /
123 def create_stream_ip4(self, src_if, dst_ip):
124 self.reset_packet_infos()
126 for i in range(0, 257):
127 info = self.create_packet_info(src_if, src_if)
128 payload = self.info_to_payload(info)
129 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
130 IP(src=src_if.remote_ip4, dst=dst_ip) /
131 UDP(sport=1234, dport=1234) /
137 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl,
140 dst_ip = src_if.remote_ip6
141 self.reset_packet_infos()
143 for i in range(0, 257):
144 info = self.create_packet_info(src_if, src_if)
145 payload = self.info_to_payload(info)
146 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
147 MPLS(label=mpls_label, ttl=mpls_ttl) /
148 IPv6(src=src_if.remote_ip6, dst=dst_ip) /
149 UDP(sport=1234, dport=1234) /
155 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
157 capture = verify_filter(capture, sent)
159 self.assertEqual(len(capture), len(sent))
161 for i in range(len(capture)):
165 # the rx'd packet has the MPLS label popped
167 self.assertEqual(eth.type, 0x800)
173 self.assertEqual(rx_ip.src, tx_ip.src)
174 self.assertEqual(rx_ip.dst, tx_ip.dst)
175 # IP processing post pop has decremented the TTL
176 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
178 self.assertEqual(rx_ip.src, tx_ip.dst)
179 self.assertEqual(rx_ip.dst, tx_ip.src)
184 def verify_capture_labelled_ip4(self, src_if, capture, sent,
187 capture = verify_filter(capture, sent)
189 self.assertEqual(len(capture), len(sent))
191 for i in range(len(capture)):
197 # the MPLS TTL is copied from the IP
198 verify_mpls_stack(self, rx, mpls_labels, rx_ip.ttl,
199 len(mpls_labels) - 1)
201 self.assertEqual(rx_ip.src, tx_ip.src)
202 self.assertEqual(rx_ip.dst, tx_ip.dst)
203 # IP processing post pop has decremented the TTL
204 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
209 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
212 top = len(mpls_labels) - 1
214 capture = verify_filter(capture, sent)
216 self.assertEqual(len(capture), len(sent))
218 for i in range(len(capture)):
224 # the MPLS TTL is 255 since it enters a new tunnel
225 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
227 self.assertEqual(rx_ip.src, tx_ip.src)
228 self.assertEqual(rx_ip.dst, tx_ip.dst)
229 # IP processing post pop has decremented the TTL
230 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
235 def verify_capture_labelled(self, src_if, capture, sent,
236 mpls_labels, ttl=254, num=0):
238 capture = verify_filter(capture, sent)
240 self.assertEqual(len(capture), len(sent))
242 for i in range(len(capture)):
244 verify_mpls_stack(self, rx, mpls_labels, ttl, num)
248 def verify_capture_ip6(self, src_if, capture, sent):
250 self.assertEqual(len(capture), len(sent))
252 for i in range(len(capture)):
256 # the rx'd packet has the MPLS label popped
258 self.assertEqual(eth.type, 0x86DD)
263 self.assertEqual(rx_ip.src, tx_ip.src)
264 self.assertEqual(rx_ip.dst, tx_ip.dst)
265 # IP processing post pop has decremented the TTL
266 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
271 def send_and_assert_no_replies(self, intf, pkts, remark):
272 intf.add_stream(pkts)
273 self.pg_enable_capture(self.pg_interfaces)
275 for i in self.pg_interfaces:
276 i.assert_nothing_captured(remark=remark)
279 """ MPLS label swap tests """
282 # A simple MPLS xconnect - eos label in label out
284 route_32_eos = VppMplsRoute(self, 32, 1,
285 [VppRoutePath(self.pg0.remote_ip4,
286 self.pg0.sw_if_index,
288 route_32_eos.add_vpp_config()
291 # a stream that matches the route for 10.0.0.1
292 # PG0 is in the default table
294 self.vapi.cli("clear trace")
295 tx = self.create_stream_labelled_ip4(self.pg0, [32])
296 self.pg0.add_stream(tx)
298 self.pg_enable_capture(self.pg_interfaces)
301 rx = self.pg0.get_capture()
302 self.verify_capture_labelled(self.pg0, rx, tx, [33])
305 # A simple MPLS xconnect - non-eos label in label out
307 route_32_neos = VppMplsRoute(self, 32, 0,
308 [VppRoutePath(self.pg0.remote_ip4,
309 self.pg0.sw_if_index,
311 route_32_neos.add_vpp_config()
314 # a stream that matches the route for 10.0.0.1
315 # PG0 is in the default table
317 self.vapi.cli("clear trace")
318 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
319 self.pg0.add_stream(tx)
321 self.pg_enable_capture(self.pg_interfaces)
324 rx = self.pg0.get_capture()
325 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
328 # An MPLS xconnect - EOS label in IP out
330 route_33_eos = VppMplsRoute(self, 33, 1,
331 [VppRoutePath(self.pg0.remote_ip4,
332 self.pg0.sw_if_index,
334 route_33_eos.add_vpp_config()
336 self.vapi.cli("clear trace")
337 tx = self.create_stream_labelled_ip4(self.pg0, [33])
338 self.pg0.add_stream(tx)
340 self.pg_enable_capture(self.pg_interfaces)
343 rx = self.pg0.get_capture()
344 self.verify_capture_ip4(self.pg0, rx, tx)
347 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
348 # so this traffic should be dropped.
350 route_33_neos = VppMplsRoute(self, 33, 0,
351 [VppRoutePath(self.pg0.remote_ip4,
352 self.pg0.sw_if_index,
354 route_33_neos.add_vpp_config()
356 self.vapi.cli("clear trace")
357 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
358 self.pg0.add_stream(tx)
360 self.pg_enable_capture(self.pg_interfaces)
362 self.pg0.assert_nothing_captured(
363 remark="MPLS non-EOS packets popped and forwarded")
366 # A recursive EOS x-connect, which resolves through another x-connect
368 route_34_eos = VppMplsRoute(self, 34, 1,
369 [VppRoutePath("0.0.0.0",
373 route_34_eos.add_vpp_config()
375 tx = self.create_stream_labelled_ip4(self.pg0, [34])
376 self.pg0.add_stream(tx)
378 self.pg_enable_capture(self.pg_interfaces)
381 rx = self.pg0.get_capture()
382 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
385 # A recursive non-EOS x-connect, which resolves through another
388 route_34_neos = VppMplsRoute(self, 34, 0,
389 [VppRoutePath("0.0.0.0",
393 route_34_neos.add_vpp_config()
395 self.vapi.cli("clear trace")
396 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
397 self.pg0.add_stream(tx)
399 self.pg_enable_capture(self.pg_interfaces)
402 rx = self.pg0.get_capture()
403 # it's the 2nd (counting from 0) label in the stack that is swapped
404 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
407 # an recursive IP route that resolves through the recursive non-eos
410 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
411 [VppRoutePath("0.0.0.0",
415 ip_10_0_0_1.add_vpp_config()
417 self.vapi.cli("clear trace")
418 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
419 self.pg0.add_stream(tx)
421 self.pg_enable_capture(self.pg_interfaces)
424 rx = self.pg0.get_capture()
425 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
427 ip_10_0_0_1.remove_vpp_config()
428 route_34_neos.remove_vpp_config()
429 route_34_eos.remove_vpp_config()
430 route_33_neos.remove_vpp_config()
431 route_33_eos.remove_vpp_config()
432 route_32_neos.remove_vpp_config()
433 route_32_eos.remove_vpp_config()
436 """ MPLS Local Label Binding test """
439 # Add a non-recursive route with a single out label
441 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
442 [VppRoutePath(self.pg0.remote_ip4,
443 self.pg0.sw_if_index,
445 route_10_0_0_1.add_vpp_config()
447 # bind a local label to the route
448 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
449 binding.add_vpp_config()
452 self.vapi.cli("clear trace")
453 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
454 self.pg0.add_stream(tx)
456 self.pg_enable_capture(self.pg_interfaces)
459 rx = self.pg0.get_capture()
460 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
463 self.vapi.cli("clear trace")
464 tx = self.create_stream_labelled_ip4(self.pg0, [44])
465 self.pg0.add_stream(tx)
467 self.pg_enable_capture(self.pg_interfaces)
470 rx = self.pg0.get_capture()
471 self.verify_capture_labelled(self.pg0, rx, tx, [45])
474 self.vapi.cli("clear trace")
475 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
476 self.pg0.add_stream(tx)
478 self.pg_enable_capture(self.pg_interfaces)
481 rx = self.pg0.get_capture()
482 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
487 binding.remove_vpp_config()
488 route_10_0_0_1.remove_vpp_config()
490 def test_imposition(self):
491 """ MPLS label imposition test """
494 # Add a non-recursive route with a single out label
496 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
497 [VppRoutePath(self.pg0.remote_ip4,
498 self.pg0.sw_if_index,
500 route_10_0_0_1.add_vpp_config()
503 # a stream that matches the route for 10.0.0.1
504 # PG0 is in the default table
506 self.vapi.cli("clear trace")
507 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
508 self.pg0.add_stream(tx)
510 self.pg_enable_capture(self.pg_interfaces)
513 rx = self.pg0.get_capture()
514 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
517 # Add a non-recursive route with a 3 out labels
519 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
520 [VppRoutePath(self.pg0.remote_ip4,
521 self.pg0.sw_if_index,
522 labels=[32, 33, 34])])
523 route_10_0_0_2.add_vpp_config()
526 # a stream that matches the route for 10.0.0.1
527 # PG0 is in the default table
529 self.vapi.cli("clear trace")
530 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
531 self.pg0.add_stream(tx)
533 self.pg_enable_capture(self.pg_interfaces)
536 rx = self.pg0.get_capture()
537 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
540 # add a recursive path, with output label, via the 1 label route
542 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
543 [VppRoutePath("10.0.0.1",
546 route_11_0_0_1.add_vpp_config()
549 # a stream that matches the route for 11.0.0.1, should pick up
550 # the label stack for 11.0.0.1 and 10.0.0.1
552 self.vapi.cli("clear trace")
553 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
554 self.pg0.add_stream(tx)
556 self.pg_enable_capture(self.pg_interfaces)
559 rx = self.pg0.get_capture()
560 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
563 # add a recursive path, with 2 labels, via the 3 label route
565 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
566 [VppRoutePath("10.0.0.2",
569 route_11_0_0_2.add_vpp_config()
572 # a stream that matches the route for 11.0.0.1, should pick up
573 # the label stack for 11.0.0.1 and 10.0.0.1
575 self.vapi.cli("clear trace")
576 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
577 self.pg0.add_stream(tx)
579 self.pg_enable_capture(self.pg_interfaces)
582 rx = self.pg0.get_capture()
583 self.verify_capture_labelled_ip4(
584 self.pg0, rx, tx, [32, 33, 34, 44, 45])
589 route_11_0_0_2.remove_vpp_config()
590 route_11_0_0_1.remove_vpp_config()
591 route_10_0_0_2.remove_vpp_config()
592 route_10_0_0_1.remove_vpp_config()
594 def test_tunnel(self):
595 """ MPLS Tunnel Tests """
598 # Create a tunnel with a single out label
600 mpls_tun = VppMPLSTunnelInterface(self,
601 [VppRoutePath(self.pg0.remote_ip4,
602 self.pg0.sw_if_index,
604 mpls_tun.add_vpp_config()
608 # add an unlabelled route through the new tunnel
610 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
611 [VppRoutePath("0.0.0.0",
612 mpls_tun._sw_if_index)])
613 route_10_0_0_3.add_vpp_config()
615 self.vapi.cli("clear trace")
616 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
617 self.pg0.add_stream(tx)
619 self.pg_enable_capture(self.pg_interfaces)
622 rx = self.pg0.get_capture()
623 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
626 # add a labelled route through the new tunnel
628 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
629 [VppRoutePath("0.0.0.0",
630 mpls_tun._sw_if_index,
632 route_10_0_0_4.add_vpp_config()
634 self.vapi.cli("clear trace")
635 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
636 self.pg0.add_stream(tx)
638 self.pg_enable_capture(self.pg_interfaces)
641 rx = self.pg0.get_capture()
642 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
645 def test_v4_exp_null(self):
646 """ MPLS V4 Explicit NULL test """
649 # The first test case has an MPLS TTL of 0
650 # all packet should be dropped
652 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
653 self.pg0.add_stream(tx)
655 self.pg_enable_capture(self.pg_interfaces)
658 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
661 # a stream with a non-zero MPLS TTL
662 # PG0 is in the default table
664 tx = self.create_stream_labelled_ip4(self.pg0, [0])
665 self.pg0.add_stream(tx)
667 self.pg_enable_capture(self.pg_interfaces)
670 rx = self.pg0.get_capture()
671 self.verify_capture_ip4(self.pg0, rx, tx)
674 # a stream with a non-zero MPLS TTL
676 # we are ensuring the post-pop lookup occurs in the VRF table
678 self.vapi.cli("clear trace")
679 tx = self.create_stream_labelled_ip4(self.pg1, [0])
680 self.pg1.add_stream(tx)
682 self.pg_enable_capture(self.pg_interfaces)
685 rx = self.pg1.get_capture()
686 self.verify_capture_ip4(self.pg0, rx, tx)
688 def test_v6_exp_null(self):
689 """ MPLS V6 Explicit NULL test """
692 # a stream with a non-zero MPLS TTL
693 # PG0 is in the default table
695 self.vapi.cli("clear trace")
696 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
697 self.pg0.add_stream(tx)
699 self.pg_enable_capture(self.pg_interfaces)
702 rx = self.pg0.get_capture()
703 self.verify_capture_ip6(self.pg0, rx, tx)
706 # a stream with a non-zero MPLS TTL
708 # we are ensuring the post-pop lookup occurs in the VRF table
710 self.vapi.cli("clear trace")
711 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
712 self.pg1.add_stream(tx)
714 self.pg_enable_capture(self.pg_interfaces)
717 rx = self.pg1.get_capture()
718 self.verify_capture_ip6(self.pg0, rx, tx)
724 # A de-agg route - next-hop lookup in default table
726 route_34_eos = VppMplsRoute(self, 34, 1,
727 [VppRoutePath("0.0.0.0",
730 route_34_eos.add_vpp_config()
733 # ping an interface in the default table
734 # PG0 is in the default table
736 self.vapi.cli("clear trace")
737 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
739 self.pg0.add_stream(tx)
741 self.pg_enable_capture(self.pg_interfaces)
744 rx = self.pg0.get_capture()
745 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
748 # A de-agg route - next-hop lookup in non-default table
750 route_35_eos = VppMplsRoute(self, 35, 1,
751 [VppRoutePath("0.0.0.0",
754 route_35_eos.add_vpp_config()
757 # ping an interface in the non-default table
758 # PG0 is in the default table. packet arrive labelled in the
759 # default table and egress unlabelled in the non-default
761 self.vapi.cli("clear trace")
762 tx = self.create_stream_labelled_ip4(
763 self.pg0, [35], ping=1, ip_itf=self.pg1)
764 self.pg0.add_stream(tx)
766 self.pg_enable_capture(self.pg_interfaces)
769 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
770 rx = self.pg1.get_capture(packet_count)
771 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
776 route_36_neos = VppMplsRoute(self, 36, 0,
777 [VppRoutePath("0.0.0.0",
779 route_36_neos.add_vpp_config()
781 self.vapi.cli("clear trace")
782 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
783 ping=1, ip_itf=self.pg1)
784 self.pg0.add_stream(tx)
786 self.pg_enable_capture(self.pg_interfaces)
789 rx = self.pg1.get_capture(len(tx))
790 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
792 route_36_neos.remove_vpp_config()
793 route_35_eos.remove_vpp_config()
794 route_34_eos.remove_vpp_config()
796 def test_interface_rx(self):
797 """ MPLS Interface Receive """
800 # Add a non-recursive route that will forward the traffic
803 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
805 paths=[VppRoutePath(self.pg1.remote_ip4,
806 self.pg1.sw_if_index)])
807 route_10_0_0_1.add_vpp_config()
810 # An interface receive label that maps traffic to RX on interface
812 # by injecting the packet in on pg0, which is in table 0
813 # doing an interface-rx on pg1 and matching a route in table 1
814 # if the packet egresses, then we must have swapped to pg1
815 # so as to have matched the route in table 1
817 route_34_eos = VppMplsRoute(self, 34, 1,
818 [VppRoutePath("0.0.0.0",
819 self.pg1.sw_if_index,
821 route_34_eos.add_vpp_config()
824 # ping an interface in the default table
825 # PG0 is in the default table
827 self.vapi.cli("clear trace")
828 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
830 self.pg0.add_stream(tx)
832 self.pg_enable_capture(self.pg_interfaces)
835 rx = self.pg1.get_capture(257)
836 self.verify_capture_ip4(self.pg1, rx, tx)
838 def test_mcast_mid_point(self):
839 """ MPLS Multicast Mid Point """
842 # Add a non-recursive route that will forward the traffic
845 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
847 paths=[VppRoutePath(self.pg1.remote_ip4,
848 self.pg1.sw_if_index)])
849 route_10_0_0_1.add_vpp_config()
852 # Add a mcast entry that replicate to pg2 and pg3
853 # and replicate to a interface-rx (like a bud node would)
855 route_3400_eos = VppMplsRoute(self, 3400, 1,
856 [VppRoutePath(self.pg2.remote_ip4,
857 self.pg2.sw_if_index,
859 VppRoutePath(self.pg3.remote_ip4,
860 self.pg3.sw_if_index,
862 VppRoutePath("0.0.0.0",
863 self.pg1.sw_if_index,
866 route_3400_eos.add_vpp_config()
869 # ping an interface in the default table
870 # PG0 is in the default table
872 self.vapi.cli("clear trace")
873 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
875 self.pg0.add_stream(tx)
877 self.pg_enable_capture(self.pg_interfaces)
880 rx = self.pg1.get_capture(257)
881 self.verify_capture_ip4(self.pg1, rx, tx)
883 rx = self.pg2.get_capture(257)
884 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
885 rx = self.pg3.get_capture(257)
886 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
888 def test_mcast_head(self):
889 """ MPLS Multicast Head-end """
892 # Create a multicast tunnel with two replications
894 mpls_tun = VppMPLSTunnelInterface(self,
895 [VppRoutePath(self.pg2.remote_ip4,
896 self.pg2.sw_if_index,
898 VppRoutePath(self.pg3.remote_ip4,
899 self.pg3.sw_if_index,
902 mpls_tun.add_vpp_config()
906 # add an unlabelled route through the new tunnel
908 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
909 [VppRoutePath("0.0.0.0",
910 mpls_tun._sw_if_index)])
911 route_10_0_0_3.add_vpp_config()
913 self.vapi.cli("clear trace")
914 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
915 self.pg0.add_stream(tx)
917 self.pg_enable_capture(self.pg_interfaces)
920 rx = self.pg2.get_capture(257)
921 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
922 rx = self.pg3.get_capture(257)
923 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
926 # An an IP multicast route via the tunnel
928 # one accepting interface, pg0, 1 forwarding interface via the tunnel
930 route_232_1_1_1 = VppIpMRoute(
934 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
935 [VppMRoutePath(self.pg0.sw_if_index,
936 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
937 VppMRoutePath(mpls_tun._sw_if_index,
938 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
939 route_232_1_1_1.add_vpp_config()
941 self.vapi.cli("clear trace")
942 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
943 self.pg0.add_stream(tx)
945 self.pg_enable_capture(self.pg_interfaces)
948 rx = self.pg2.get_capture(257)
949 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
950 rx = self.pg3.get_capture(257)
951 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
953 def test_mcast_ip4_tail(self):
954 """ MPLS IPv4 Multicast Tail """
957 # Add a multicast route that will forward the traffic
960 route_232_1_1_1 = VppIpMRoute(
964 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
966 paths=[VppMRoutePath(self.pg1.sw_if_index,
967 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
968 route_232_1_1_1.add_vpp_config()
971 # An interface receive label that maps traffic to RX on interface
973 # by injecting the packet in on pg0, which is in table 0
974 # doing an rpf-id and matching a route in table 1
975 # if the packet egresses, then we must have matched the route in
978 route_34_eos = VppMplsRoute(self, 34, 1,
979 [VppRoutePath("0.0.0.0",
980 self.pg1.sw_if_index,
985 route_34_eos.add_vpp_config()
988 # Drop due to interface lookup miss
990 self.vapi.cli("clear trace")
991 tx = self.create_stream_labelled_ip4(self.pg0, [34],
992 dst_ip="232.1.1.1", n=1)
993 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
996 # set the RPF-ID of the enrtry to match the input packet's
998 route_232_1_1_1.update_rpf_id(55)
1000 self.vapi.cli("clear trace")
1001 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1002 dst_ip="232.1.1.1", n=257)
1003 self.pg0.add_stream(tx)
1005 self.pg_enable_capture(self.pg_interfaces)
1008 rx = self.pg1.get_capture(257)
1009 self.verify_capture_ip4(self.pg1, rx, tx)
1012 # set the RPF-ID of the enrtry to not match the input packet's
1014 route_232_1_1_1.update_rpf_id(56)
1015 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1017 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1019 def test_mcast_ip6_tail(self):
1020 """ MPLS IPv6 Multicast Tail """
1023 # Add a multicast route that will forward the traffic
1026 route_ff = VppIpMRoute(
1030 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1032 paths=[VppMRoutePath(self.pg1.sw_if_index,
1033 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1035 route_ff.add_vpp_config()
1038 # An interface receive label that maps traffic to RX on interface
1040 # by injecting the packet in on pg0, which is in table 0
1041 # doing an rpf-id and matching a route in table 1
1042 # if the packet egresses, then we must have matched the route in
1045 route_34_eos = VppMplsRoute(
1048 self.pg1.sw_if_index,
1051 proto=DpoProto.DPO_PROTO_IP6)],
1054 route_34_eos.add_vpp_config()
1057 # Drop due to interface lookup miss
1059 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1063 # set the RPF-ID of the enrtry to match the input packet's
1065 route_ff.update_rpf_id(55)
1067 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1069 self.pg0.add_stream(tx)
1071 self.pg_enable_capture(self.pg_interfaces)
1074 rx = self.pg1.get_capture(257)
1075 self.verify_capture_ip6(self.pg1, rx, tx)
1078 # set the RPF-ID of the enrtry to not match the input packet's
1080 route_ff.update_rpf_id(56)
1081 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1083 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1086 class TestMPLSDisabled(VppTestCase):
1087 """ MPLS disabled """
1090 super(TestMPLSDisabled, self).setUp()
1092 # create 2 pg interfaces
1093 self.create_pg_interfaces(range(2))
1095 # PG0 is MPLS enalbed
1097 self.pg0.config_ip4()
1098 self.pg0.resolve_arp()
1099 self.pg0.enable_mpls()
1101 # PG 1 is not MPLS enabled
1105 super(TestMPLSDisabled, self).tearDown()
1106 for i in self.pg_interfaces:
1110 def send_and_assert_no_replies(self, intf, pkts, remark):
1111 intf.add_stream(pkts)
1112 self.pg_enable_capture(self.pg_interfaces)
1114 for i in self.pg_interfaces:
1116 i.assert_nothing_captured(remark=remark)
1118 def test_mpls_disabled(self):
1119 """ MPLS Disabled """
1121 tx = (Ether(src=self.pg1.remote_mac,
1122 dst=self.pg1.local_mac) /
1123 MPLS(label=32, ttl=64) /
1124 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1125 UDP(sport=1234, dport=1234) /
1129 # A simple MPLS xconnect - eos label in label out
1131 route_32_eos = VppMplsRoute(self, 32, 1,
1132 [VppRoutePath(self.pg0.remote_ip4,
1133 self.pg0.sw_if_index,
1135 route_32_eos.add_vpp_config()
1138 # PG1 does not forward IP traffic
1140 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1145 self.pg1.enable_mpls()
1148 # Now we get packets through
1150 self.pg1.add_stream(tx)
1151 self.pg_enable_capture(self.pg_interfaces)
1154 rx = self.pg0.get_capture(1)
1159 self.pg1.disable_mpls()
1162 # PG1 does not forward IP traffic
1164 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1165 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1168 class TestMPLSPIC(VppTestCase):
1169 """ MPLS PIC edge convergence """
1172 super(TestMPLSPIC, self).setUp()
1174 # create 2 pg interfaces
1175 self.create_pg_interfaces(range(4))
1179 self.pg0.config_ip4()
1180 self.pg0.resolve_arp()
1181 self.pg0.enable_mpls()
1183 self.pg1.config_ip4()
1184 self.pg1.resolve_arp()
1185 self.pg1.enable_mpls()
1187 # VRF (customer facing) link
1189 self.pg2.set_table_ip4(1)
1190 self.pg2.config_ip4()
1191 self.pg2.resolve_arp()
1192 self.pg2.set_table_ip6(1)
1193 self.pg2.config_ip6()
1194 self.pg2.resolve_ndp()
1196 self.pg3.set_table_ip4(1)
1197 self.pg3.config_ip4()
1198 self.pg3.resolve_arp()
1199 self.pg3.set_table_ip6(1)
1200 self.pg3.config_ip6()
1201 self.pg3.resolve_ndp()
1204 super(TestMPLSPIC, self).tearDown()
1205 self.pg0.disable_mpls()
1206 for i in self.pg_interfaces:
1213 def test_mpls_ibgp_pic(self):
1214 """ MPLS iBGP PIC edge convergence
1216 1) setup many iBGP VPN routes via a pair of iBGP peers.
1217 2) Check EMCP forwarding to these peers
1218 3) withdraw the IGP route to one of these peers.
1219 4) check forwarding continues to the remaining peer
1223 # IGP+LDP core routes
1225 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1226 [VppRoutePath(self.pg0.remote_ip4,
1227 self.pg0.sw_if_index,
1229 core_10_0_0_45.add_vpp_config()
1231 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1232 [VppRoutePath(self.pg1.remote_ip4,
1233 self.pg1.sw_if_index,
1235 core_10_0_0_46.add_vpp_config()
1238 # Lot's of VPN routes. We need more the 64 so VPP will build
1239 # the fast convergence indirection
1243 for ii in range(64):
1244 dst = "192.168.1.%d" % ii
1245 vpn_routes.append(VppIpRoute(self, dst, 32,
1246 [VppRoutePath("10.0.0.45",
1250 VppRoutePath("10.0.0.46",
1253 is_resolve_host=1)],
1255 vpn_routes[ii].add_vpp_config()
1257 pkts.append(Ether(dst=self.pg2.local_mac,
1258 src=self.pg2.remote_mac) /
1259 IP(src=self.pg2.remote_ip4, dst=dst) /
1260 UDP(sport=1234, dport=1234) /
1264 # Send the packet stream (one pkt to each VPN route)
1265 # - expect a 50-50 split of the traffic
1267 self.pg2.add_stream(pkts)
1268 self.pg_enable_capture(self.pg_interfaces)
1271 rx0 = self.pg0._get_capture(1)
1272 rx1 = self.pg1._get_capture(1)
1274 # not testig the LB hashing algorithm so we're not concerned
1275 # with the split ratio, just as long as neither is 0
1276 self.assertNotEqual(0, len(rx0))
1277 self.assertNotEqual(0, len(rx1))
1280 # use a test CLI command to stop the FIB walk process, this
1281 # will prevent the FIB converging the VPN routes and thus allow
1282 # us to probe the interim (psot-fail, pre-converge) state
1284 self.vapi.ppcli("test fib-walk-process disable")
1287 # Withdraw one of the IGP routes
1289 core_10_0_0_46.remove_vpp_config()
1292 # now all packets should be forwarded through the remaining peer
1294 self.vapi.ppcli("clear trace")
1295 self.pg2.add_stream(pkts)
1296 self.pg_enable_capture(self.pg_interfaces)
1299 rx0 = self.pg0.get_capture(len(pkts))
1302 # enable the FIB walk process to converge the FIB
1304 self.vapi.ppcli("test fib-walk-process enable")
1307 # packets should still be forwarded through the remaining peer
1309 self.pg2.add_stream(pkts)
1310 self.pg_enable_capture(self.pg_interfaces)
1313 rx0 = self.pg0.get_capture(64)
1316 # Add the IGP route back and we return to load-balancing
1318 core_10_0_0_46.add_vpp_config()
1320 self.pg2.add_stream(pkts)
1321 self.pg_enable_capture(self.pg_interfaces)
1324 rx0 = self.pg0._get_capture(1)
1325 rx1 = self.pg1._get_capture(1)
1326 self.assertNotEqual(0, len(rx0))
1327 self.assertNotEqual(0, len(rx1))
1329 def test_mpls_ebgp_pic(self):
1330 """ MPLS eBGP PIC edge convergence
1332 1) setup many eBGP VPN routes via a pair of eBGP peers
1333 2) Check EMCP forwarding to these peers
1334 3) withdraw one eBGP path - expect LB across remaining eBGP
1338 # Lot's of VPN routes. We need more the 64 so VPP will build
1339 # the fast convergence indirection
1344 for ii in range(64):
1345 dst = "192.168.1.%d" % ii
1346 local_label = 1600 + ii
1347 vpn_routes.append(VppIpRoute(self, dst, 32,
1348 [VppRoutePath(self.pg2.remote_ip4,
1351 is_resolve_attached=1),
1352 VppRoutePath(self.pg3.remote_ip4,
1355 is_resolve_attached=1)],
1357 vpn_routes[ii].add_vpp_config()
1359 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1361 vpn_bindings[ii].add_vpp_config()
1363 pkts.append(Ether(dst=self.pg0.local_mac,
1364 src=self.pg0.remote_mac) /
1365 MPLS(label=local_label, ttl=64) /
1366 IP(src=self.pg0.remote_ip4, dst=dst) /
1367 UDP(sport=1234, dport=1234) /
1370 self.pg0.add_stream(pkts)
1371 self.pg_enable_capture(self.pg_interfaces)
1374 rx0 = self.pg2._get_capture(1)
1375 rx1 = self.pg3._get_capture(1)
1376 self.assertNotEqual(0, len(rx0))
1377 self.assertNotEqual(0, len(rx1))
1380 # use a test CLI command to stop the FIB walk process, this
1381 # will prevent the FIB converging the VPN routes and thus allow
1382 # us to probe the interim (psot-fail, pre-converge) state
1384 self.vapi.ppcli("test fib-walk-process disable")
1387 # withdraw the connected prefix on the interface.
1389 self.pg2.unconfig_ip4()
1392 # now all packets should be forwarded through the remaining peer
1394 self.pg0.add_stream(pkts)
1395 self.pg_enable_capture(self.pg_interfaces)
1398 rx0 = self.pg3.get_capture(len(pkts))
1401 # enable the FIB walk process to converge the FIB
1403 self.vapi.ppcli("test fib-walk-process enable")
1404 self.pg0.add_stream(pkts)
1405 self.pg_enable_capture(self.pg_interfaces)
1408 rx0 = self.pg3.get_capture(len(pkts))
1411 # put the connecteds back
1413 self.pg2.config_ip4()
1415 self.pg0.add_stream(pkts)
1416 self.pg_enable_capture(self.pg_interfaces)
1419 rx0 = self.pg2._get_capture(1)
1420 rx1 = self.pg3._get_capture(1)
1421 self.assertNotEqual(0, len(rx0))
1422 self.assertNotEqual(0, len(rx1))
1424 def test_mpls_v6_ebgp_pic(self):
1425 """ MPLSv6 eBGP PIC edge convergence
1427 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1428 2) Check EMCP forwarding to these peers
1429 3) withdraw one eBGP path - expect LB across remaining eBGP
1433 # Lot's of VPN routes. We need more the 64 so VPP will build
1434 # the fast convergence indirection
1439 for ii in range(64):
1440 dst = "3000::%d" % ii
1441 local_label = 1600 + ii
1442 vpn_routes.append(VppIpRoute(
1444 [VppRoutePath(self.pg2.remote_ip6,
1447 is_resolve_attached=1,
1448 proto=DpoProto.DPO_PROTO_IP6),
1449 VppRoutePath(self.pg3.remote_ip6,
1452 proto=DpoProto.DPO_PROTO_IP6,
1453 is_resolve_attached=1)],
1456 vpn_routes[ii].add_vpp_config()
1458 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1461 vpn_bindings[ii].add_vpp_config()
1463 pkts.append(Ether(dst=self.pg0.local_mac,
1464 src=self.pg0.remote_mac) /
1465 MPLS(label=local_label, ttl=64) /
1466 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1467 UDP(sport=1234, dport=1234) /
1470 self.pg0.add_stream(pkts)
1471 self.pg_enable_capture(self.pg_interfaces)
1474 rx0 = self.pg2._get_capture(1)
1475 rx1 = self.pg3._get_capture(1)
1476 self.assertNotEqual(0, len(rx0))
1477 self.assertNotEqual(0, len(rx1))
1480 # use a test CLI command to stop the FIB walk process, this
1481 # will prevent the FIB converging the VPN routes and thus allow
1482 # us to probe the interim (psot-fail, pre-converge) state
1484 self.vapi.ppcli("test fib-walk-process disable")
1487 # withdraw the connected prefix on the interface.
1488 # and shutdown the interface so the ND cache is flushed.
1490 self.pg2.unconfig_ip6()
1491 self.pg2.admin_down()
1494 # now all packets should be forwarded through the remaining peer
1496 self.pg0.add_stream(pkts)
1497 self.pg_enable_capture(self.pg_interfaces)
1500 rx0 = self.pg3.get_capture(len(pkts))
1503 # enable the FIB walk process to converge the FIB
1505 self.vapi.ppcli("test fib-walk-process enable")
1506 self.pg0.add_stream(pkts)
1507 self.pg_enable_capture(self.pg_interfaces)
1510 rx0 = self.pg3.get_capture(len(pkts))
1513 # put the connecteds back
1516 self.pg2.config_ip6()
1518 self.pg0.add_stream(pkts)
1519 self.pg_enable_capture(self.pg_interfaces)
1522 rx0 = self.pg2._get_capture(1)
1523 rx1 = self.pg3._get_capture(1)
1524 self.assertNotEqual(0, len(rx0))
1525 self.assertNotEqual(0, len(rx1))
1528 class TestMPLSL2(VppTestCase):
1532 super(TestMPLSL2, self).setUp()
1534 # create 2 pg interfaces
1535 self.create_pg_interfaces(range(2))
1537 # use pg0 as the core facing interface
1539 self.pg0.config_ip4()
1540 self.pg0.resolve_arp()
1541 self.pg0.enable_mpls()
1543 # use the other 2 for customer facg L2 links
1544 for i in self.pg_interfaces[1:]:
1548 super(TestMPLSL2, self).tearDown()
1549 for i in self.pg_interfaces[1:]:
1552 self.pg0.disable_mpls()
1553 self.pg0.unconfig_ip4()
1554 self.pg0.admin_down()
1556 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1559 top = len(mpls_labels) - 1
1561 capture = verify_filter(capture, sent)
1563 self.assertEqual(len(capture), len(sent))
1565 for i in range(len(capture)):
1569 # the MPLS TTL is 255 since it enters a new tunnel
1570 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1573 rx_eth = Ether(str(rx[MPLS].payload))
1575 self.assertEqual(rx_eth.src, tx_eth.src)
1576 self.assertEqual(rx_eth.dst, tx_eth.dst)
1578 def test_vpws(self):
1579 """ Virtual Private Wire Service """
1582 # Create an MPLS tunnel that pushes 1 label
1584 mpls_tun_1 = VppMPLSTunnelInterface(self,
1585 [VppRoutePath(self.pg0.remote_ip4,
1586 self.pg0.sw_if_index,
1589 mpls_tun_1.add_vpp_config()
1590 mpls_tun_1.admin_up()
1593 # Create a label entry to for 55 that does L2 input to the tunnel
1595 route_55_eos = VppMplsRoute(
1597 [VppRoutePath("0.0.0.0",
1598 mpls_tun_1.sw_if_index,
1600 proto=DpoProto.DPO_PROTO_ETHERNET)])
1601 route_55_eos.add_vpp_config()
1604 # Cross-connect the tunnel with one of the customers L2 interfaces
1606 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1607 mpls_tun_1.sw_if_index,
1609 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1610 self.pg1.sw_if_index,
1614 # inject a packet from the core
1616 pcore = (Ether(dst=self.pg0.local_mac,
1617 src=self.pg0.remote_mac) /
1618 MPLS(label=55, ttl=64) /
1619 Ether(dst="00:00:de:ad:ba:be",
1620 src="00:00:de:ad:be:ef") /
1621 IP(src="10.10.10.10", dst="11.11.11.11") /
1622 UDP(sport=1234, dport=1234) /
1625 self.pg0.add_stream(pcore * 65)
1626 self.pg_enable_capture(self.pg_interfaces)
1629 rx0 = self.pg1.get_capture(65)
1630 tx = pcore[MPLS].payload
1632 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1633 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1636 # Inject a packet from the custoer/L2 side
1638 self.pg1.add_stream(tx * 65)
1639 self.pg_enable_capture(self.pg_interfaces)
1642 rx0 = self.pg0.get_capture(65)
1644 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1646 def test_vpls(self):
1647 """ Virtual Private LAN Service """
1649 # Create an L2 MPLS tunnel
1651 mpls_tun = VppMPLSTunnelInterface(self,
1652 [VppRoutePath(self.pg0.remote_ip4,
1653 self.pg0.sw_if_index,
1656 mpls_tun.add_vpp_config()
1660 # Create a label entry to for 55 that does L2 input to the tunnel
1662 route_55_eos = VppMplsRoute(
1664 [VppRoutePath("0.0.0.0",
1665 mpls_tun.sw_if_index,
1667 proto=DpoProto.DPO_PROTO_ETHERNET)])
1668 route_55_eos.add_vpp_config()
1671 # add to tunnel to the customers bridge-domain
1673 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1675 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1679 # Packet from the customer interface and from the core
1681 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1682 src="00:00:de:ad:be:ef") /
1683 IP(src="10.10.10.10", dst="11.11.11.11") /
1684 UDP(sport=1234, dport=1234) /
1686 p_core = (Ether(src="00:00:de:ad:ba:be",
1687 dst="00:00:de:ad:be:ef") /
1688 IP(dst="10.10.10.10", src="11.11.11.11") /
1689 UDP(sport=1234, dport=1234) /
1693 # The BD is learning, so send in one of each packet to learn
1695 p_core_encap = (Ether(dst=self.pg0.local_mac,
1696 src=self.pg0.remote_mac) /
1697 MPLS(label=55, ttl=64) /
1700 self.pg1.add_stream(p_cust)
1701 self.pg_enable_capture(self.pg_interfaces)
1703 self.pg0.add_stream(p_core_encap)
1704 self.pg_enable_capture(self.pg_interfaces)
1707 # we've learnt this so expect it be be forwarded
1708 rx0 = self.pg1.get_capture(1)
1710 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1711 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1714 # now a stream in each direction
1716 self.pg1.add_stream(p_cust * 65)
1717 self.pg_enable_capture(self.pg_interfaces)
1720 rx0 = self.pg0.get_capture(65)
1722 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1725 # remove interfaces from customers bridge-domain
1727 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 if __name__ == '__main__':
1735 unittest.main(testRunner=VppTestRunner)