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(
110 self.reset_packet_infos()
112 for i in range(0, n):
113 info = self.create_packet_info(src_if, src_if)
114 payload = self.info_to_payload(info)
115 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
117 for ii in range(len(mpls_labels)):
118 if ii == len(mpls_labels) - 1:
119 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
121 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
124 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
125 UDP(sport=1234, dport=1234) /
128 p = (p / IP(src=src_if.local_ip4, dst=dst_ip) /
129 UDP(sport=1234, dport=1234) /
132 p = (p / IP(src=ip_itf.remote_ip4,
133 dst=ip_itf.local_ip4) /
140 def create_stream_ip4(self, src_if, dst_ip):
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 IP(src=src_if.remote_ip4, dst=dst_ip) /
148 UDP(sport=1234, dport=1234) /
154 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl,
157 dst_ip = src_if.remote_ip6
158 self.reset_packet_infos()
160 for i in range(0, 257):
161 info = self.create_packet_info(src_if, src_if)
162 payload = self.info_to_payload(info)
163 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
164 MPLS(label=mpls_label, ttl=mpls_ttl) /
165 IPv6(src=src_if.remote_ip6, dst=dst_ip) /
166 UDP(sport=1234, dport=1234) /
172 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
174 capture = verify_filter(capture, sent)
176 self.assertEqual(len(capture), len(sent))
178 for i in range(len(capture)):
182 # the rx'd packet has the MPLS label popped
184 self.assertEqual(eth.type, 0x800)
190 self.assertEqual(rx_ip.src, tx_ip.src)
191 self.assertEqual(rx_ip.dst, tx_ip.dst)
192 # IP processing post pop has decremented the TTL
193 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
195 self.assertEqual(rx_ip.src, tx_ip.dst)
196 self.assertEqual(rx_ip.dst, tx_ip.src)
201 def verify_capture_labelled_ip4(self, src_if, capture, sent,
204 capture = verify_filter(capture, sent)
206 self.assertEqual(len(capture), len(sent))
208 for i in range(len(capture)):
214 # the MPLS TTL is copied from the IP
215 verify_mpls_stack(self, rx, mpls_labels, rx_ip.ttl,
216 len(mpls_labels) - 1)
218 self.assertEqual(rx_ip.src, tx_ip.src)
219 self.assertEqual(rx_ip.dst, tx_ip.dst)
220 # IP processing post pop has decremented the TTL
221 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
226 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
229 top = len(mpls_labels) - 1
231 capture = verify_filter(capture, sent)
233 self.assertEqual(len(capture), len(sent))
235 for i in range(len(capture)):
241 # the MPLS TTL is 255 since it enters a new tunnel
242 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
244 self.assertEqual(rx_ip.src, tx_ip.src)
245 self.assertEqual(rx_ip.dst, tx_ip.dst)
246 # IP processing post pop has decremented the TTL
247 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
252 def verify_capture_labelled(self, src_if, capture, sent,
253 mpls_labels, ttl=254, num=0):
255 capture = verify_filter(capture, sent)
257 self.assertEqual(len(capture), len(sent))
259 for i in range(len(capture)):
261 verify_mpls_stack(self, rx, mpls_labels, ttl, num)
265 def verify_capture_ip6(self, src_if, capture, sent):
267 self.assertEqual(len(capture), len(sent))
269 for i in range(len(capture)):
273 # the rx'd packet has the MPLS label popped
275 self.assertEqual(eth.type, 0x86DD)
280 self.assertEqual(rx_ip.src, tx_ip.src)
281 self.assertEqual(rx_ip.dst, tx_ip.dst)
282 # IP processing post pop has decremented the TTL
283 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
288 def send_and_assert_no_replies(self, intf, pkts, remark):
289 intf.add_stream(pkts)
290 self.pg_enable_capture(self.pg_interfaces)
292 for i in self.pg_interfaces:
293 i.assert_nothing_captured(remark=remark)
296 """ MPLS label swap tests """
299 # A simple MPLS xconnect - eos label in label out
301 route_32_eos = VppMplsRoute(self, 32, 1,
302 [VppRoutePath(self.pg0.remote_ip4,
303 self.pg0.sw_if_index,
305 route_32_eos.add_vpp_config()
308 # a stream that matches the route for 10.0.0.1
309 # PG0 is in the default table
311 self.vapi.cli("clear trace")
312 tx = self.create_stream_labelled_ip4(self.pg0, [32])
313 self.pg0.add_stream(tx)
315 self.pg_enable_capture(self.pg_interfaces)
318 rx = self.pg0.get_capture()
319 self.verify_capture_labelled(self.pg0, rx, tx, [33])
322 # A simple MPLS xconnect - non-eos label in label out
324 route_32_neos = VppMplsRoute(self, 32, 0,
325 [VppRoutePath(self.pg0.remote_ip4,
326 self.pg0.sw_if_index,
328 route_32_neos.add_vpp_config()
331 # a stream that matches the route for 10.0.0.1
332 # PG0 is in the default table
334 self.vapi.cli("clear trace")
335 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
336 self.pg0.add_stream(tx)
338 self.pg_enable_capture(self.pg_interfaces)
341 rx = self.pg0.get_capture()
342 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
345 # An MPLS xconnect - EOS label in IP out
347 route_33_eos = VppMplsRoute(self, 33, 1,
348 [VppRoutePath(self.pg0.remote_ip4,
349 self.pg0.sw_if_index,
351 route_33_eos.add_vpp_config()
353 self.vapi.cli("clear trace")
354 tx = self.create_stream_labelled_ip4(self.pg0, [33])
355 self.pg0.add_stream(tx)
357 self.pg_enable_capture(self.pg_interfaces)
360 rx = self.pg0.get_capture()
361 self.verify_capture_ip4(self.pg0, rx, tx)
364 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
365 # so this traffic should be dropped.
367 route_33_neos = VppMplsRoute(self, 33, 0,
368 [VppRoutePath(self.pg0.remote_ip4,
369 self.pg0.sw_if_index,
371 route_33_neos.add_vpp_config()
373 self.vapi.cli("clear trace")
374 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
375 self.pg0.add_stream(tx)
377 self.pg_enable_capture(self.pg_interfaces)
379 self.pg0.assert_nothing_captured(
380 remark="MPLS non-EOS packets popped and forwarded")
383 # A recursive EOS x-connect, which resolves through another x-connect
385 route_34_eos = VppMplsRoute(self, 34, 1,
386 [VppRoutePath("0.0.0.0",
390 route_34_eos.add_vpp_config()
392 tx = self.create_stream_labelled_ip4(self.pg0, [34])
393 self.pg0.add_stream(tx)
395 self.pg_enable_capture(self.pg_interfaces)
398 rx = self.pg0.get_capture()
399 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
402 # A recursive non-EOS x-connect, which resolves through another
405 route_34_neos = VppMplsRoute(self, 34, 0,
406 [VppRoutePath("0.0.0.0",
410 route_34_neos.add_vpp_config()
412 self.vapi.cli("clear trace")
413 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
414 self.pg0.add_stream(tx)
416 self.pg_enable_capture(self.pg_interfaces)
419 rx = self.pg0.get_capture()
420 # it's the 2nd (counting from 0) label in the stack that is swapped
421 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
424 # an recursive IP route that resolves through the recursive non-eos
427 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
428 [VppRoutePath("0.0.0.0",
432 ip_10_0_0_1.add_vpp_config()
434 self.vapi.cli("clear trace")
435 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
436 self.pg0.add_stream(tx)
438 self.pg_enable_capture(self.pg_interfaces)
441 rx = self.pg0.get_capture()
442 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
444 ip_10_0_0_1.remove_vpp_config()
445 route_34_neos.remove_vpp_config()
446 route_34_eos.remove_vpp_config()
447 route_33_neos.remove_vpp_config()
448 route_33_eos.remove_vpp_config()
449 route_32_neos.remove_vpp_config()
450 route_32_eos.remove_vpp_config()
453 """ MPLS Local Label Binding test """
456 # Add a non-recursive route with a single out label
458 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
459 [VppRoutePath(self.pg0.remote_ip4,
460 self.pg0.sw_if_index,
462 route_10_0_0_1.add_vpp_config()
464 # bind a local label to the route
465 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
466 binding.add_vpp_config()
469 self.vapi.cli("clear trace")
470 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
471 self.pg0.add_stream(tx)
473 self.pg_enable_capture(self.pg_interfaces)
476 rx = self.pg0.get_capture()
477 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
480 self.vapi.cli("clear trace")
481 tx = self.create_stream_labelled_ip4(self.pg0, [44])
482 self.pg0.add_stream(tx)
484 self.pg_enable_capture(self.pg_interfaces)
487 rx = self.pg0.get_capture()
488 self.verify_capture_labelled(self.pg0, rx, tx, [45])
491 self.vapi.cli("clear trace")
492 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
493 self.pg0.add_stream(tx)
495 self.pg_enable_capture(self.pg_interfaces)
498 rx = self.pg0.get_capture()
499 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
504 binding.remove_vpp_config()
505 route_10_0_0_1.remove_vpp_config()
507 def test_imposition(self):
508 """ MPLS label imposition test """
511 # Add a non-recursive route with a single out label
513 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
514 [VppRoutePath(self.pg0.remote_ip4,
515 self.pg0.sw_if_index,
517 route_10_0_0_1.add_vpp_config()
520 # a stream that matches the route for 10.0.0.1
521 # PG0 is in the default table
523 self.vapi.cli("clear trace")
524 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
525 self.pg0.add_stream(tx)
527 self.pg_enable_capture(self.pg_interfaces)
530 rx = self.pg0.get_capture()
531 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
534 # Add a non-recursive route with a 3 out labels
536 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
537 [VppRoutePath(self.pg0.remote_ip4,
538 self.pg0.sw_if_index,
539 labels=[32, 33, 34])])
540 route_10_0_0_2.add_vpp_config()
543 # a stream that matches the route for 10.0.0.1
544 # PG0 is in the default table
546 self.vapi.cli("clear trace")
547 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
548 self.pg0.add_stream(tx)
550 self.pg_enable_capture(self.pg_interfaces)
553 rx = self.pg0.get_capture()
554 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
557 # add a recursive path, with output label, via the 1 label route
559 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
560 [VppRoutePath("10.0.0.1",
563 route_11_0_0_1.add_vpp_config()
566 # a stream that matches the route for 11.0.0.1, should pick up
567 # the label stack for 11.0.0.1 and 10.0.0.1
569 self.vapi.cli("clear trace")
570 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
571 self.pg0.add_stream(tx)
573 self.pg_enable_capture(self.pg_interfaces)
576 rx = self.pg0.get_capture()
577 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
580 # add a recursive path, with 2 labels, via the 3 label route
582 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
583 [VppRoutePath("10.0.0.2",
586 route_11_0_0_2.add_vpp_config()
589 # a stream that matches the route for 11.0.0.1, should pick up
590 # the label stack for 11.0.0.1 and 10.0.0.1
592 self.vapi.cli("clear trace")
593 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
594 self.pg0.add_stream(tx)
596 self.pg_enable_capture(self.pg_interfaces)
599 rx = self.pg0.get_capture()
600 self.verify_capture_labelled_ip4(
601 self.pg0, rx, tx, [32, 33, 34, 44, 45])
606 route_11_0_0_2.remove_vpp_config()
607 route_11_0_0_1.remove_vpp_config()
608 route_10_0_0_2.remove_vpp_config()
609 route_10_0_0_1.remove_vpp_config()
611 def test_tunnel(self):
612 """ MPLS Tunnel Tests """
615 # Create a tunnel with a single out label
617 mpls_tun = VppMPLSTunnelInterface(self,
618 [VppRoutePath(self.pg0.remote_ip4,
619 self.pg0.sw_if_index,
621 mpls_tun.add_vpp_config()
625 # add an unlabelled route through the new tunnel
627 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
628 [VppRoutePath("0.0.0.0",
629 mpls_tun._sw_if_index)])
630 route_10_0_0_3.add_vpp_config()
632 self.vapi.cli("clear trace")
633 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
634 self.pg0.add_stream(tx)
636 self.pg_enable_capture(self.pg_interfaces)
639 rx = self.pg0.get_capture()
640 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
643 # add a labelled route through the new tunnel
645 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
646 [VppRoutePath("0.0.0.0",
647 mpls_tun._sw_if_index,
649 route_10_0_0_4.add_vpp_config()
651 self.vapi.cli("clear trace")
652 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
653 self.pg0.add_stream(tx)
655 self.pg_enable_capture(self.pg_interfaces)
658 rx = self.pg0.get_capture()
659 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
662 def test_v4_exp_null(self):
663 """ MPLS V4 Explicit NULL test """
666 # The first test case has an MPLS TTL of 0
667 # all packet should be dropped
669 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
670 self.pg0.add_stream(tx)
672 self.pg_enable_capture(self.pg_interfaces)
675 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
678 # a stream with a non-zero MPLS TTL
679 # PG0 is in the default table
681 tx = self.create_stream_labelled_ip4(self.pg0, [0])
682 self.pg0.add_stream(tx)
684 self.pg_enable_capture(self.pg_interfaces)
687 rx = self.pg0.get_capture()
688 self.verify_capture_ip4(self.pg0, rx, tx)
691 # a stream with a non-zero MPLS TTL
693 # we are ensuring the post-pop lookup occurs in the VRF table
695 self.vapi.cli("clear trace")
696 tx = self.create_stream_labelled_ip4(self.pg1, [0])
697 self.pg1.add_stream(tx)
699 self.pg_enable_capture(self.pg_interfaces)
702 rx = self.pg1.get_capture()
703 self.verify_capture_ip4(self.pg0, rx, tx)
705 def test_v6_exp_null(self):
706 """ MPLS V6 Explicit NULL test """
709 # a stream with a non-zero MPLS TTL
710 # PG0 is in the default table
712 self.vapi.cli("clear trace")
713 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
714 self.pg0.add_stream(tx)
716 self.pg_enable_capture(self.pg_interfaces)
719 rx = self.pg0.get_capture()
720 self.verify_capture_ip6(self.pg0, rx, tx)
723 # a stream with a non-zero MPLS TTL
725 # we are ensuring the post-pop lookup occurs in the VRF table
727 self.vapi.cli("clear trace")
728 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
729 self.pg1.add_stream(tx)
731 self.pg_enable_capture(self.pg_interfaces)
734 rx = self.pg1.get_capture()
735 self.verify_capture_ip6(self.pg0, rx, tx)
741 # A de-agg route - next-hop lookup in default table
743 route_34_eos = VppMplsRoute(self, 34, 1,
744 [VppRoutePath("0.0.0.0",
747 route_34_eos.add_vpp_config()
750 # ping an interface in the default table
751 # PG0 is in the default table
753 self.vapi.cli("clear trace")
754 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
756 self.pg0.add_stream(tx)
758 self.pg_enable_capture(self.pg_interfaces)
761 rx = self.pg0.get_capture()
762 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
765 # A de-agg route - next-hop lookup in non-default table
767 route_35_eos = VppMplsRoute(self, 35, 1,
768 [VppRoutePath("0.0.0.0",
771 route_35_eos.add_vpp_config()
774 # ping an interface in the non-default table
775 # PG0 is in the default table. packet arrive labelled in the
776 # default table and egress unlabelled in the non-default
778 self.vapi.cli("clear trace")
779 tx = self.create_stream_labelled_ip4(
780 self.pg0, [35], ping=1, ip_itf=self.pg1)
781 self.pg0.add_stream(tx)
783 self.pg_enable_capture(self.pg_interfaces)
786 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
787 rx = self.pg1.get_capture(packet_count)
788 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
793 route_36_neos = VppMplsRoute(self, 36, 0,
794 [VppRoutePath("0.0.0.0",
796 route_36_neos.add_vpp_config()
798 self.vapi.cli("clear trace")
799 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
800 ping=1, ip_itf=self.pg1)
801 self.pg0.add_stream(tx)
803 self.pg_enable_capture(self.pg_interfaces)
806 rx = self.pg1.get_capture(len(tx))
807 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
809 route_36_neos.remove_vpp_config()
810 route_35_eos.remove_vpp_config()
811 route_34_eos.remove_vpp_config()
813 def test_interface_rx(self):
814 """ MPLS Interface Receive """
817 # Add a non-recursive route that will forward the traffic
820 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
822 paths=[VppRoutePath(self.pg1.remote_ip4,
823 self.pg1.sw_if_index)])
824 route_10_0_0_1.add_vpp_config()
827 # An interface receive label that maps traffic to RX on interface
829 # by injecting the packet in on pg0, which is in table 0
830 # doing an interface-rx on pg1 and matching a route in table 1
831 # if the packet egresses, then we must have swapped to pg1
832 # so as to have matched the route in table 1
834 route_34_eos = VppMplsRoute(self, 34, 1,
835 [VppRoutePath("0.0.0.0",
836 self.pg1.sw_if_index,
838 route_34_eos.add_vpp_config()
841 # ping an interface in the default table
842 # PG0 is in the default table
844 self.vapi.cli("clear trace")
845 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
847 self.pg0.add_stream(tx)
849 self.pg_enable_capture(self.pg_interfaces)
852 rx = self.pg1.get_capture(257)
853 self.verify_capture_ip4(self.pg1, rx, tx)
855 def test_mcast_mid_point(self):
856 """ MPLS Multicast Mid Point """
859 # Add a non-recursive route that will forward the traffic
862 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
864 paths=[VppRoutePath(self.pg1.remote_ip4,
865 self.pg1.sw_if_index)])
866 route_10_0_0_1.add_vpp_config()
869 # Add a mcast entry that replicate to pg2 and pg3
870 # and replicate to a interface-rx (like a bud node would)
872 route_3400_eos = VppMplsRoute(self, 3400, 1,
873 [VppRoutePath(self.pg2.remote_ip4,
874 self.pg2.sw_if_index,
876 VppRoutePath(self.pg3.remote_ip4,
877 self.pg3.sw_if_index,
879 VppRoutePath("0.0.0.0",
880 self.pg1.sw_if_index,
883 route_3400_eos.add_vpp_config()
886 # ping an interface in the default table
887 # PG0 is in the default table
889 self.vapi.cli("clear trace")
890 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
892 self.pg0.add_stream(tx)
894 self.pg_enable_capture(self.pg_interfaces)
897 rx = self.pg1.get_capture(257)
898 self.verify_capture_ip4(self.pg1, rx, tx)
900 rx = self.pg2.get_capture(257)
901 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
902 rx = self.pg3.get_capture(257)
903 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
905 def test_mcast_head(self):
906 """ MPLS Multicast Head-end """
909 # Create a multicast tunnel with two replications
911 mpls_tun = VppMPLSTunnelInterface(self,
912 [VppRoutePath(self.pg2.remote_ip4,
913 self.pg2.sw_if_index,
915 VppRoutePath(self.pg3.remote_ip4,
916 self.pg3.sw_if_index,
919 mpls_tun.add_vpp_config()
923 # add an unlabelled route through the new tunnel
925 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
926 [VppRoutePath("0.0.0.0",
927 mpls_tun._sw_if_index)])
928 route_10_0_0_3.add_vpp_config()
930 self.vapi.cli("clear trace")
931 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
932 self.pg0.add_stream(tx)
934 self.pg_enable_capture(self.pg_interfaces)
937 rx = self.pg2.get_capture(257)
938 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
939 rx = self.pg3.get_capture(257)
940 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
943 # An an IP multicast route via the tunnel
945 # one accepting interface, pg0, 1 forwarding interface via the tunnel
947 route_232_1_1_1 = VppIpMRoute(
951 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
952 [VppMRoutePath(self.pg0.sw_if_index,
953 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
954 VppMRoutePath(mpls_tun._sw_if_index,
955 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
956 route_232_1_1_1.add_vpp_config()
958 self.vapi.cli("clear trace")
959 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
960 self.pg0.add_stream(tx)
962 self.pg_enable_capture(self.pg_interfaces)
965 rx = self.pg2.get_capture(257)
966 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
967 rx = self.pg3.get_capture(257)
968 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
970 def test_mcast_ip4_tail(self):
971 """ MPLS IPv4 Multicast Tail """
974 # Add a multicast route that will forward the traffic
977 route_232_1_1_1 = VppIpMRoute(
981 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
983 paths=[VppMRoutePath(self.pg1.sw_if_index,
984 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
985 route_232_1_1_1.add_vpp_config()
988 # An interface receive label that maps traffic to RX on interface
990 # by injecting the packet in on pg0, which is in table 0
991 # doing an rpf-id and matching a route in table 1
992 # if the packet egresses, then we must have matched the route in
995 route_34_eos = VppMplsRoute(self, 34, 1,
996 [VppRoutePath("0.0.0.0",
997 self.pg1.sw_if_index,
1002 route_34_eos.add_vpp_config()
1005 # Drop due to interface lookup miss
1007 self.vapi.cli("clear trace")
1008 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1009 dst_ip="232.1.1.1", n=1)
1010 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1013 # set the RPF-ID of the enrtry to match the input packet's
1015 route_232_1_1_1.update_rpf_id(55)
1017 self.vapi.cli("clear trace")
1018 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1019 dst_ip="232.1.1.1", n=257)
1020 self.pg0.add_stream(tx)
1022 self.pg_enable_capture(self.pg_interfaces)
1025 rx = self.pg1.get_capture(257)
1026 self.verify_capture_ip4(self.pg1, rx, tx)
1029 # set the RPF-ID of the enrtry to not match the input packet's
1031 route_232_1_1_1.update_rpf_id(56)
1032 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1034 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1036 def test_mcast_ip6_tail(self):
1037 """ MPLS IPv6 Multicast Tail """
1040 # Add a multicast route that will forward the traffic
1043 route_ff = VppIpMRoute(
1047 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1049 paths=[VppMRoutePath(self.pg1.sw_if_index,
1050 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1052 route_ff.add_vpp_config()
1055 # An interface receive label that maps traffic to RX on interface
1057 # by injecting the packet in on pg0, which is in table 0
1058 # doing an rpf-id and matching a route in table 1
1059 # if the packet egresses, then we must have matched the route in
1062 route_34_eos = VppMplsRoute(
1065 self.pg1.sw_if_index,
1068 proto=DpoProto.DPO_PROTO_IP6)],
1071 route_34_eos.add_vpp_config()
1074 # Drop due to interface lookup miss
1076 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1080 # set the RPF-ID of the enrtry to match the input packet's
1082 route_ff.update_rpf_id(55)
1084 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1086 self.pg0.add_stream(tx)
1088 self.pg_enable_capture(self.pg_interfaces)
1091 rx = self.pg1.get_capture(257)
1092 self.verify_capture_ip6(self.pg1, rx, tx)
1095 # set the RPF-ID of the enrtry to not match the input packet's
1097 route_ff.update_rpf_id(56)
1098 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1100 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1103 class TestMPLSDisabled(VppTestCase):
1104 """ MPLS disabled """
1107 super(TestMPLSDisabled, self).setUp()
1109 # create 2 pg interfaces
1110 self.create_pg_interfaces(range(2))
1112 self.tbl = VppMplsTable(self, 0)
1113 self.tbl.add_vpp_config()
1115 # PG0 is MPLS enalbed
1117 self.pg0.config_ip4()
1118 self.pg0.resolve_arp()
1119 self.pg0.enable_mpls()
1121 # PG 1 is not MPLS enabled
1125 for i in self.pg_interfaces:
1129 self.pg0.disable_mpls()
1130 super(TestMPLSDisabled, self).tearDown()
1132 def send_and_assert_no_replies(self, intf, pkts, remark):
1133 intf.add_stream(pkts)
1134 self.pg_enable_capture(self.pg_interfaces)
1136 for i in self.pg_interfaces:
1138 i.assert_nothing_captured(remark=remark)
1140 def test_mpls_disabled(self):
1141 """ MPLS Disabled """
1143 tx = (Ether(src=self.pg1.remote_mac,
1144 dst=self.pg1.local_mac) /
1145 MPLS(label=32, ttl=64) /
1146 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1147 UDP(sport=1234, dport=1234) /
1151 # A simple MPLS xconnect - eos label in label out
1153 route_32_eos = VppMplsRoute(self, 32, 1,
1154 [VppRoutePath(self.pg0.remote_ip4,
1155 self.pg0.sw_if_index,
1157 route_32_eos.add_vpp_config()
1160 # PG1 does not forward IP traffic
1162 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1167 self.pg1.enable_mpls()
1170 # Now we get packets through
1172 self.pg1.add_stream(tx)
1173 self.pg_enable_capture(self.pg_interfaces)
1176 rx = self.pg0.get_capture(1)
1181 self.pg1.disable_mpls()
1184 # PG1 does not forward IP traffic
1186 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1187 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1190 class TestMPLSPIC(VppTestCase):
1191 """ MPLS PIC edge convergence """
1194 super(TestMPLSPIC, self).setUp()
1196 # create 2 pg interfaces
1197 self.create_pg_interfaces(range(4))
1199 mpls_tbl = VppMplsTable(self, 0)
1200 mpls_tbl.add_vpp_config()
1201 tbl4 = VppIpTable(self, 1)
1202 tbl4.add_vpp_config()
1203 tbl6 = VppIpTable(self, 1, is_ip6=1)
1204 tbl6.add_vpp_config()
1208 self.pg0.config_ip4()
1209 self.pg0.resolve_arp()
1210 self.pg0.enable_mpls()
1212 self.pg1.config_ip4()
1213 self.pg1.resolve_arp()
1214 self.pg1.enable_mpls()
1216 # VRF (customer facing) link
1218 self.pg2.set_table_ip4(1)
1219 self.pg2.config_ip4()
1220 self.pg2.resolve_arp()
1221 self.pg2.set_table_ip6(1)
1222 self.pg2.config_ip6()
1223 self.pg2.resolve_ndp()
1225 self.pg3.set_table_ip4(1)
1226 self.pg3.config_ip4()
1227 self.pg3.resolve_arp()
1228 self.pg3.set_table_ip6(1)
1229 self.pg3.config_ip6()
1230 self.pg3.resolve_ndp()
1233 self.pg0.disable_mpls()
1234 self.pg1.disable_mpls()
1235 for i in self.pg_interfaces:
1241 super(TestMPLSPIC, self).tearDown()
1243 def test_mpls_ibgp_pic(self):
1244 """ MPLS iBGP PIC edge convergence
1246 1) setup many iBGP VPN routes via a pair of iBGP peers.
1247 2) Check EMCP forwarding to these peers
1248 3) withdraw the IGP route to one of these peers.
1249 4) check forwarding continues to the remaining peer
1253 # IGP+LDP core routes
1255 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1256 [VppRoutePath(self.pg0.remote_ip4,
1257 self.pg0.sw_if_index,
1259 core_10_0_0_45.add_vpp_config()
1261 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1262 [VppRoutePath(self.pg1.remote_ip4,
1263 self.pg1.sw_if_index,
1265 core_10_0_0_46.add_vpp_config()
1268 # Lot's of VPN routes. We need more the 64 so VPP will build
1269 # the fast convergence indirection
1273 for ii in range(64):
1274 dst = "192.168.1.%d" % ii
1275 vpn_routes.append(VppIpRoute(self, dst, 32,
1276 [VppRoutePath("10.0.0.45",
1280 VppRoutePath("10.0.0.46",
1283 is_resolve_host=1)],
1285 vpn_routes[ii].add_vpp_config()
1287 pkts.append(Ether(dst=self.pg2.local_mac,
1288 src=self.pg2.remote_mac) /
1289 IP(src=self.pg2.remote_ip4, dst=dst) /
1290 UDP(sport=1234, dport=1234) /
1294 # Send the packet stream (one pkt to each VPN route)
1295 # - expect a 50-50 split of the traffic
1297 self.pg2.add_stream(pkts)
1298 self.pg_enable_capture(self.pg_interfaces)
1301 rx0 = self.pg0._get_capture(1)
1302 rx1 = self.pg1._get_capture(1)
1304 # not testig the LB hashing algorithm so we're not concerned
1305 # with the split ratio, just as long as neither is 0
1306 self.assertNotEqual(0, len(rx0))
1307 self.assertNotEqual(0, len(rx1))
1310 # use a test CLI command to stop the FIB walk process, this
1311 # will prevent the FIB converging the VPN routes and thus allow
1312 # us to probe the interim (psot-fail, pre-converge) state
1314 self.vapi.ppcli("test fib-walk-process disable")
1317 # Withdraw one of the IGP routes
1319 core_10_0_0_46.remove_vpp_config()
1322 # now all packets should be forwarded through the remaining peer
1324 self.vapi.ppcli("clear trace")
1325 self.pg2.add_stream(pkts)
1326 self.pg_enable_capture(self.pg_interfaces)
1329 rx0 = self.pg0.get_capture(len(pkts))
1332 # enable the FIB walk process to converge the FIB
1334 self.vapi.ppcli("test fib-walk-process enable")
1337 # packets should still be forwarded through the remaining peer
1339 self.pg2.add_stream(pkts)
1340 self.pg_enable_capture(self.pg_interfaces)
1343 rx0 = self.pg0.get_capture(64)
1346 # Add the IGP route back and we return to load-balancing
1348 core_10_0_0_46.add_vpp_config()
1350 self.pg2.add_stream(pkts)
1351 self.pg_enable_capture(self.pg_interfaces)
1354 rx0 = self.pg0._get_capture(1)
1355 rx1 = self.pg1._get_capture(1)
1356 self.assertNotEqual(0, len(rx0))
1357 self.assertNotEqual(0, len(rx1))
1359 def test_mpls_ebgp_pic(self):
1360 """ MPLS eBGP PIC edge convergence
1362 1) setup many eBGP VPN routes via a pair of eBGP peers
1363 2) Check EMCP forwarding to these peers
1364 3) withdraw one eBGP path - expect LB across remaining eBGP
1368 # Lot's of VPN routes. We need more the 64 so VPP will build
1369 # the fast convergence indirection
1374 for ii in range(64):
1375 dst = "192.168.1.%d" % ii
1376 local_label = 1600 + ii
1377 vpn_routes.append(VppIpRoute(self, dst, 32,
1378 [VppRoutePath(self.pg2.remote_ip4,
1381 is_resolve_attached=1),
1382 VppRoutePath(self.pg3.remote_ip4,
1385 is_resolve_attached=1)],
1387 vpn_routes[ii].add_vpp_config()
1389 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1391 vpn_bindings[ii].add_vpp_config()
1393 pkts.append(Ether(dst=self.pg0.local_mac,
1394 src=self.pg0.remote_mac) /
1395 MPLS(label=local_label, ttl=64) /
1396 IP(src=self.pg0.remote_ip4, dst=dst) /
1397 UDP(sport=1234, dport=1234) /
1400 self.pg0.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1404 rx0 = self.pg2._get_capture(1)
1405 rx1 = self.pg3._get_capture(1)
1406 self.assertNotEqual(0, len(rx0))
1407 self.assertNotEqual(0, len(rx1))
1410 # use a test CLI command to stop the FIB walk process, this
1411 # will prevent the FIB converging the VPN routes and thus allow
1412 # us to probe the interim (psot-fail, pre-converge) state
1414 self.vapi.ppcli("test fib-walk-process disable")
1417 # withdraw the connected prefix on the interface.
1419 self.pg2.unconfig_ip4()
1422 # now all packets should be forwarded through the remaining peer
1424 self.pg0.add_stream(pkts)
1425 self.pg_enable_capture(self.pg_interfaces)
1428 rx0 = self.pg3.get_capture(len(pkts))
1431 # enable the FIB walk process to converge the FIB
1433 self.vapi.ppcli("test fib-walk-process enable")
1434 self.pg0.add_stream(pkts)
1435 self.pg_enable_capture(self.pg_interfaces)
1438 rx0 = self.pg3.get_capture(len(pkts))
1441 # put the connecteds back
1443 self.pg2.config_ip4()
1445 self.pg0.add_stream(pkts)
1446 self.pg_enable_capture(self.pg_interfaces)
1449 rx0 = self.pg2._get_capture(1)
1450 rx1 = self.pg3._get_capture(1)
1451 self.assertNotEqual(0, len(rx0))
1452 self.assertNotEqual(0, len(rx1))
1454 def test_mpls_v6_ebgp_pic(self):
1455 """ MPLSv6 eBGP PIC edge convergence
1457 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1458 2) Check EMCP forwarding to these peers
1459 3) withdraw one eBGP path - expect LB across remaining eBGP
1463 # Lot's of VPN routes. We need more the 64 so VPP will build
1464 # the fast convergence indirection
1469 for ii in range(64):
1470 dst = "3000::%d" % ii
1471 local_label = 1600 + ii
1472 vpn_routes.append(VppIpRoute(
1474 [VppRoutePath(self.pg2.remote_ip6,
1477 is_resolve_attached=1,
1478 proto=DpoProto.DPO_PROTO_IP6),
1479 VppRoutePath(self.pg3.remote_ip6,
1482 proto=DpoProto.DPO_PROTO_IP6,
1483 is_resolve_attached=1)],
1486 vpn_routes[ii].add_vpp_config()
1488 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1491 vpn_bindings[ii].add_vpp_config()
1493 pkts.append(Ether(dst=self.pg0.local_mac,
1494 src=self.pg0.remote_mac) /
1495 MPLS(label=local_label, ttl=64) /
1496 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1497 UDP(sport=1234, dport=1234) /
1500 self.pg0.add_stream(pkts)
1501 self.pg_enable_capture(self.pg_interfaces)
1504 rx0 = self.pg2._get_capture(1)
1505 rx1 = self.pg3._get_capture(1)
1506 self.assertNotEqual(0, len(rx0))
1507 self.assertNotEqual(0, len(rx1))
1510 # use a test CLI command to stop the FIB walk process, this
1511 # will prevent the FIB converging the VPN routes and thus allow
1512 # us to probe the interim (psot-fail, pre-converge) state
1514 self.vapi.ppcli("test fib-walk-process disable")
1517 # withdraw the connected prefix on the interface.
1518 # and shutdown the interface so the ND cache is flushed.
1520 self.pg2.unconfig_ip6()
1521 self.pg2.admin_down()
1524 # now all packets should be forwarded through the remaining peer
1526 self.pg0.add_stream(pkts)
1527 self.pg_enable_capture(self.pg_interfaces)
1530 rx0 = self.pg3.get_capture(len(pkts))
1533 # enable the FIB walk process to converge the FIB
1535 self.vapi.ppcli("test fib-walk-process enable")
1536 self.pg0.add_stream(pkts)
1537 self.pg_enable_capture(self.pg_interfaces)
1540 rx0 = self.pg3.get_capture(len(pkts))
1543 # put the connecteds back
1546 self.pg2.config_ip6()
1548 self.pg0.add_stream(pkts)
1549 self.pg_enable_capture(self.pg_interfaces)
1552 rx0 = self.pg2._get_capture(1)
1553 rx1 = self.pg3._get_capture(1)
1554 self.assertNotEqual(0, len(rx0))
1555 self.assertNotEqual(0, len(rx1))
1558 class TestMPLSL2(VppTestCase):
1562 super(TestMPLSL2, self).setUp()
1564 # create 2 pg interfaces
1565 self.create_pg_interfaces(range(2))
1567 # create the default MPLS table
1569 tbl = VppMplsTable(self, 0)
1570 tbl.add_vpp_config()
1571 self.tables.append(tbl)
1573 # use pg0 as the core facing interface
1575 self.pg0.config_ip4()
1576 self.pg0.resolve_arp()
1577 self.pg0.enable_mpls()
1579 # use the other 2 for customer facing L2 links
1580 for i in self.pg_interfaces[1:]:
1584 for i in self.pg_interfaces[1:]:
1587 self.pg0.disable_mpls()
1588 self.pg0.unconfig_ip4()
1589 self.pg0.admin_down()
1590 super(TestMPLSL2, self).tearDown()
1592 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1595 top = len(mpls_labels) - 1
1597 capture = verify_filter(capture, sent)
1599 self.assertEqual(len(capture), len(sent))
1601 for i in range(len(capture)):
1605 # the MPLS TTL is 255 since it enters a new tunnel
1606 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1609 rx_eth = Ether(str(rx[MPLS].payload))
1611 self.assertEqual(rx_eth.src, tx_eth.src)
1612 self.assertEqual(rx_eth.dst, tx_eth.dst)
1614 def test_vpws(self):
1615 """ Virtual Private Wire Service """
1618 # Create an MPLS tunnel that pushes 1 label
1620 mpls_tun_1 = VppMPLSTunnelInterface(self,
1621 [VppRoutePath(self.pg0.remote_ip4,
1622 self.pg0.sw_if_index,
1625 mpls_tun_1.add_vpp_config()
1626 mpls_tun_1.admin_up()
1629 # Create a label entry to for 55 that does L2 input to the tunnel
1631 route_55_eos = VppMplsRoute(
1633 [VppRoutePath("0.0.0.0",
1634 mpls_tun_1.sw_if_index,
1636 proto=DpoProto.DPO_PROTO_ETHERNET)])
1637 route_55_eos.add_vpp_config()
1640 # Cross-connect the tunnel with one of the customers L2 interfaces
1642 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1643 mpls_tun_1.sw_if_index,
1645 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1646 self.pg1.sw_if_index,
1650 # inject a packet from the core
1652 pcore = (Ether(dst=self.pg0.local_mac,
1653 src=self.pg0.remote_mac) /
1654 MPLS(label=55, ttl=64) /
1655 Ether(dst="00:00:de:ad:ba:be",
1656 src="00:00:de:ad:be:ef") /
1657 IP(src="10.10.10.10", dst="11.11.11.11") /
1658 UDP(sport=1234, dport=1234) /
1661 self.pg0.add_stream(pcore * 65)
1662 self.pg_enable_capture(self.pg_interfaces)
1665 rx0 = self.pg1.get_capture(65)
1666 tx = pcore[MPLS].payload
1668 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1669 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1672 # Inject a packet from the custoer/L2 side
1674 self.pg1.add_stream(tx * 65)
1675 self.pg_enable_capture(self.pg_interfaces)
1678 rx0 = self.pg0.get_capture(65)
1680 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1682 def test_vpls(self):
1683 """ Virtual Private LAN Service """
1685 # Create an L2 MPLS tunnel
1687 mpls_tun = VppMPLSTunnelInterface(self,
1688 [VppRoutePath(self.pg0.remote_ip4,
1689 self.pg0.sw_if_index,
1692 mpls_tun.add_vpp_config()
1696 # Create a label entry to for 55 that does L2 input to the tunnel
1698 route_55_eos = VppMplsRoute(
1700 [VppRoutePath("0.0.0.0",
1701 mpls_tun.sw_if_index,
1703 proto=DpoProto.DPO_PROTO_ETHERNET)])
1704 route_55_eos.add_vpp_config()
1707 # add to tunnel to the customers bridge-domain
1709 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1711 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1715 # Packet from the customer interface and from the core
1717 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1718 src="00:00:de:ad:be:ef") /
1719 IP(src="10.10.10.10", dst="11.11.11.11") /
1720 UDP(sport=1234, dport=1234) /
1722 p_core = (Ether(src="00:00:de:ad:ba:be",
1723 dst="00:00:de:ad:be:ef") /
1724 IP(dst="10.10.10.10", src="11.11.11.11") /
1725 UDP(sport=1234, dport=1234) /
1729 # The BD is learning, so send in one of each packet to learn
1731 p_core_encap = (Ether(dst=self.pg0.local_mac,
1732 src=self.pg0.remote_mac) /
1733 MPLS(label=55, ttl=64) /
1736 self.pg1.add_stream(p_cust)
1737 self.pg_enable_capture(self.pg_interfaces)
1739 self.pg0.add_stream(p_core_encap)
1740 self.pg_enable_capture(self.pg_interfaces)
1743 # we've learnt this so expect it be be forwarded
1744 rx0 = self.pg1.get_capture(1)
1746 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1747 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1750 # now a stream in each direction
1752 self.pg1.add_stream(p_cust * 65)
1753 self.pg_enable_capture(self.pg_interfaces)
1756 rx0 = self.pg0.get_capture(65)
1758 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1761 # remove interfaces from customers bridge-domain
1763 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1766 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1770 if __name__ == '__main__':
1771 unittest.main(testRunner=VppTestRunner)