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 VppMplsLabel, MplsLspMode
11 from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether
15 from scapy.layers.inet import IP, UDP, ICMP
16 from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
17 from scapy.contrib.mpls import MPLS
20 def verify_filter(capture, sent):
21 if not len(capture) == len(sent):
22 # filter out any IPv6 RAs from the capture
29 def verify_mpls_stack(tst, rx, mpls_labels):
30 # the rx'd packet has the MPLS label popped
32 tst.assertEqual(eth.type, 0x8847)
36 for ii in range(len(mpls_labels)):
37 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
38 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
39 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
41 if ii == len(mpls_labels) - 1:
42 tst.assertEqual(rx_mpls.s, 1)
45 tst.assertEqual(rx_mpls.s, 0)
46 # pop the label to expose the next
47 rx_mpls = rx_mpls[MPLS].payload
50 class TestMPLS(VppTestCase):
51 """ MPLS Test Case """
54 super(TestMPLS, self).setUp()
56 # create 2 pg interfaces
57 self.create_pg_interfaces(range(4))
59 # setup both interfaces
60 # assign them different tables.
64 tbl = VppMplsTable(self, 0)
66 self.tables.append(tbl)
68 for i in self.pg_interfaces:
72 tbl = VppIpTable(self, table_id)
74 self.tables.append(tbl)
75 tbl = VppIpTable(self, table_id, is_ip6=1)
77 self.tables.append(tbl)
79 i.set_table_ip4(table_id)
80 i.set_table_ip6(table_id)
89 for i in self.pg_interfaces:
97 super(TestMPLS, self).tearDown()
99 # the default of 64 matches the IP packet TTL default
100 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 p = p / MPLS(label=mpls_labels[ii].value,
119 ttl=mpls_labels[ii].ttl,
120 cos=mpls_labels[ii].exp)
123 p = (p / IP(src=src_if.local_ip4,
124 dst=src_if.remote_ip4,
126 UDP(sport=1234, dport=1234) /
129 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
130 UDP(sport=1234, dport=1234) /
133 p = (p / IP(src=ip_itf.remote_ip4,
134 dst=ip_itf.local_ip4,
139 p[IP].chksum = chksum
144 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
145 self.reset_packet_infos()
147 for i in range(0, 257):
148 info = self.create_packet_info(src_if, src_if)
149 payload = self.info_to_payload(info)
150 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
151 IP(src=src_if.remote_ip4, dst=dst_ip,
152 ttl=ip_ttl, tos=ip_dscp) /
153 UDP(sport=1234, dport=1234) /
159 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
160 self.reset_packet_infos()
162 for i in range(0, 257):
163 info = self.create_packet_info(src_if, src_if)
164 payload = self.info_to_payload(info)
165 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
166 IPv6(src=src_if.remote_ip6, dst=dst_ip,
167 hlim=ip_ttl, tc=ip_dscp) /
168 UDP(sport=1234, dport=1234) /
174 def create_stream_labelled_ip6(self, src_if, mpls_labels,
175 hlim=64, dst_ip=None):
177 dst_ip = src_if.remote_ip6
178 self.reset_packet_infos()
180 for i in range(0, 257):
181 info = self.create_packet_info(src_if, src_if)
182 payload = self.info_to_payload(info)
183 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
184 for l in mpls_labels:
185 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
187 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
188 UDP(sport=1234, dport=1234) /
194 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
195 ip_ttl=None, ip_dscp=0):
197 capture = verify_filter(capture, sent)
199 self.assertEqual(len(capture), len(sent))
201 for i in range(len(capture)):
205 # the rx'd packet has the MPLS label popped
207 self.assertEqual(eth.type, 0x800)
213 self.assertEqual(rx_ip.src, tx_ip.src)
214 self.assertEqual(rx_ip.dst, tx_ip.dst)
215 self.assertEqual(rx_ip.tos, ip_dscp)
217 # IP processing post pop has decremented the TTL
218 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
220 self.assertEqual(rx_ip.ttl, ip_ttl)
222 self.assertEqual(rx_ip.src, tx_ip.dst)
223 self.assertEqual(rx_ip.dst, tx_ip.src)
228 def verify_capture_labelled_ip4(self, src_if, capture, sent,
229 mpls_labels, ip_ttl=None):
231 capture = verify_filter(capture, sent)
233 self.assertEqual(len(capture), len(sent))
235 for i in range(len(capture)):
241 verify_mpls_stack(self, rx, mpls_labels)
243 self.assertEqual(rx_ip.src, tx_ip.src)
244 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)
249 self.assertEqual(rx_ip.ttl, ip_ttl)
254 def verify_capture_labelled_ip6(self, src_if, capture, sent,
255 mpls_labels, ip_ttl=None):
257 capture = verify_filter(capture, sent)
259 self.assertEqual(len(capture), len(sent))
261 for i in range(len(capture)):
267 verify_mpls_stack(self, rx, mpls_labels)
269 self.assertEqual(rx_ip.src, tx_ip.src)
270 self.assertEqual(rx_ip.dst, tx_ip.dst)
272 # IP processing post pop has decremented the TTL
273 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
275 self.assertEqual(rx_ip.hlim, ip_ttl)
280 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
282 capture = verify_filter(capture, sent)
284 self.assertEqual(len(capture), len(sent))
286 for i in range(len(capture)):
292 verify_mpls_stack(self, rx, mpls_labels)
294 self.assertEqual(rx_ip.src, tx_ip.src)
295 self.assertEqual(rx_ip.dst, tx_ip.dst)
296 # IP processing post pop has decremented the TTL
297 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
302 def verify_capture_labelled(self, src_if, capture, sent,
305 capture = verify_filter(capture, sent)
307 self.assertEqual(len(capture), len(sent))
309 for i in range(len(capture)):
311 verify_mpls_stack(self, rx, mpls_labels)
315 def verify_capture_ip6(self, src_if, capture, sent,
316 ip_hlim=None, ip_dscp=0):
318 self.assertEqual(len(capture), len(sent))
320 for i in range(len(capture)):
324 # the rx'd packet has the MPLS label popped
326 self.assertEqual(eth.type, 0x86DD)
331 self.assertEqual(rx_ip.src, tx_ip.src)
332 self.assertEqual(rx_ip.dst, tx_ip.dst)
333 self.assertEqual(rx_ip.tc, ip_dscp)
334 # IP processing post pop has decremented the TTL
336 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
338 self.assertEqual(rx_ip.hlim, ip_hlim)
343 def verify_capture_ip6_icmp(self, src_if, capture, sent):
345 self.assertEqual(len(capture), len(sent))
347 for i in range(len(capture)):
351 # the rx'd packet has the MPLS label popped
353 self.assertEqual(eth.type, 0x86DD)
358 self.assertEqual(rx_ip.dst, tx_ip.src)
359 # ICMP sourced from the interface's address
360 self.assertEqual(rx_ip.src, src_if.local_ip6)
361 # hop-limit reset to 255 for IMCP packet
362 self.assertEqual(rx_ip.hlim, 254)
364 icmp = rx[ICMPv6TimeExceeded]
370 """ MPLS label swap tests """
373 # A simple MPLS xconnect - eos label in label out
375 route_32_eos = VppMplsRoute(self, 32, 1,
376 [VppRoutePath(self.pg0.remote_ip4,
377 self.pg0.sw_if_index,
378 labels=[VppMplsLabel(33)])])
379 route_32_eos.add_vpp_config()
382 # a stream that matches the route for 10.0.0.1
383 # PG0 is in the default table
385 tx = self.create_stream_labelled_ip4(self.pg0,
386 [VppMplsLabel(32, ttl=32, exp=1)])
387 rx = self.send_and_expect(self.pg0, tx, self.pg0)
388 self.verify_capture_labelled(self.pg0, rx, tx,
389 [VppMplsLabel(33, ttl=31, exp=1)])
392 # A simple MPLS xconnect - non-eos label in label out
394 route_32_neos = VppMplsRoute(self, 32, 0,
395 [VppRoutePath(self.pg0.remote_ip4,
396 self.pg0.sw_if_index,
397 labels=[VppMplsLabel(33)])])
398 route_32_neos.add_vpp_config()
401 # a stream that matches the route for 10.0.0.1
402 # PG0 is in the default table
404 tx = self.create_stream_labelled_ip4(self.pg0,
405 [VppMplsLabel(32, ttl=21, exp=7),
407 rx = self.send_and_expect(self.pg0, tx, self.pg0)
408 self.verify_capture_labelled(self.pg0, rx, tx,
409 [VppMplsLabel(33, ttl=20, exp=7),
413 # A simple MPLS xconnect - non-eos label in label out, uniform mode
415 route_42_neos = VppMplsRoute(
417 [VppRoutePath(self.pg0.remote_ip4,
418 self.pg0.sw_if_index,
419 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
420 route_42_neos.add_vpp_config()
422 tx = self.create_stream_labelled_ip4(self.pg0,
423 [VppMplsLabel(42, ttl=21, exp=7),
425 rx = self.send_and_expect(self.pg0, tx, self.pg0)
426 self.verify_capture_labelled(self.pg0, rx, tx,
427 [VppMplsLabel(43, ttl=20, exp=7),
431 # An MPLS xconnect - EOS label in IP out
433 route_33_eos = VppMplsRoute(self, 33, 1,
434 [VppRoutePath(self.pg0.remote_ip4,
435 self.pg0.sw_if_index,
437 route_33_eos.add_vpp_config()
439 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
440 rx = self.send_and_expect(self.pg0, tx, self.pg0)
441 self.verify_capture_ip4(self.pg0, rx, tx)
444 # disposed packets have an invalid IPv4 checkusm
446 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
447 dst_ip=self.pg0.remote_ip4,
450 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
453 # An MPLS xconnect - EOS label in IP out, uniform mode
455 route_3333_eos = VppMplsRoute(
457 [VppRoutePath(self.pg0.remote_ip4,
458 self.pg0.sw_if_index,
459 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
460 route_3333_eos.add_vpp_config()
462 tx = self.create_stream_labelled_ip4(
464 [VppMplsLabel(3333, ttl=55, exp=3)])
465 rx = self.send_and_expect(self.pg0, tx, self.pg0)
466 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
467 tx = self.create_stream_labelled_ip4(
469 [VppMplsLabel(3333, ttl=66, exp=4)])
470 rx = self.send_and_expect(self.pg0, tx, self.pg0)
471 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
474 # An MPLS xconnect - EOS label in IPv6 out
476 route_333_eos = VppMplsRoute(
478 [VppRoutePath(self.pg0.remote_ip6,
479 self.pg0.sw_if_index,
481 proto=DpoProto.DPO_PROTO_IP6)])
482 route_333_eos.add_vpp_config()
484 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
485 rx = self.send_and_expect(self.pg0, tx, self.pg0)
486 self.verify_capture_ip6(self.pg0, rx, tx)
489 # disposed packets have an TTL expired
491 tx = self.create_stream_labelled_ip6(self.pg0,
492 [VppMplsLabel(333, ttl=64)],
493 dst_ip=self.pg1.remote_ip6,
495 rx = self.send_and_expect(self.pg0, tx, self.pg0)
496 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
499 # An MPLS xconnect - EOS label in IPv6 out w imp-null
501 route_334_eos = VppMplsRoute(
503 [VppRoutePath(self.pg0.remote_ip6,
504 self.pg0.sw_if_index,
505 labels=[VppMplsLabel(3)],
506 proto=DpoProto.DPO_PROTO_IP6)])
507 route_334_eos.add_vpp_config()
509 tx = self.create_stream_labelled_ip6(self.pg0,
510 [VppMplsLabel(334, ttl=64)])
511 rx = self.send_and_expect(self.pg0, tx, self.pg0)
512 self.verify_capture_ip6(self.pg0, rx, tx)
515 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
517 route_335_eos = VppMplsRoute(
519 [VppRoutePath(self.pg0.remote_ip6,
520 self.pg0.sw_if_index,
521 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
522 proto=DpoProto.DPO_PROTO_IP6)])
523 route_335_eos.add_vpp_config()
525 tx = self.create_stream_labelled_ip6(
527 [VppMplsLabel(335, ttl=27, exp=4)])
528 rx = self.send_and_expect(self.pg0, tx, self.pg0)
529 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
532 # disposed packets have an TTL expired
534 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
535 dst_ip=self.pg1.remote_ip6,
537 rx = self.send_and_expect(self.pg0, tx, self.pg0)
538 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
541 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
542 # so this traffic should be dropped.
544 route_33_neos = VppMplsRoute(self, 33, 0,
545 [VppRoutePath(self.pg0.remote_ip4,
546 self.pg0.sw_if_index,
548 route_33_neos.add_vpp_config()
550 tx = self.create_stream_labelled_ip4(self.pg0,
553 self.send_and_assert_no_replies(
555 "MPLS non-EOS packets popped and forwarded")
558 # A recursive EOS x-connect, which resolves through another x-connect
561 route_34_eos = VppMplsRoute(self, 34, 1,
562 [VppRoutePath("0.0.0.0",
565 labels=[VppMplsLabel(44),
567 route_34_eos.add_vpp_config()
569 tx = self.create_stream_labelled_ip4(self.pg0,
570 [VppMplsLabel(34, ttl=3)])
571 rx = self.send_and_expect(self.pg0, tx, self.pg0)
572 self.verify_capture_labelled(self.pg0, rx, tx,
575 VppMplsLabel(45, ttl=2)])
578 # A recursive EOS x-connect, which resolves through another x-connect
581 route_35_eos = VppMplsRoute(
583 [VppRoutePath("0.0.0.0",
586 labels=[VppMplsLabel(44)])])
587 route_35_eos.add_vpp_config()
589 tx = self.create_stream_labelled_ip4(self.pg0,
590 [VppMplsLabel(35, ttl=3)])
591 rx = self.send_and_expect(self.pg0, tx, self.pg0)
592 self.verify_capture_labelled(self.pg0, rx, tx,
593 [VppMplsLabel(43, ttl=2),
594 VppMplsLabel(44, ttl=2)])
597 # A recursive non-EOS x-connect, which resolves through another
600 route_34_neos = VppMplsRoute(self, 34, 0,
601 [VppRoutePath("0.0.0.0",
604 labels=[VppMplsLabel(44),
606 route_34_neos.add_vpp_config()
608 tx = self.create_stream_labelled_ip4(self.pg0,
609 [VppMplsLabel(34, ttl=45),
611 rx = self.send_and_expect(self.pg0, tx, self.pg0)
612 # it's the 2nd (counting from 0) label in the stack that is swapped
613 self.verify_capture_labelled(self.pg0, rx, tx,
616 VppMplsLabel(46, ttl=44),
620 # an recursive IP route that resolves through the recursive non-eos
623 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
624 [VppRoutePath("0.0.0.0",
627 labels=[VppMplsLabel(55)])])
628 ip_10_0_0_1.add_vpp_config()
630 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
631 rx = self.send_and_expect(self.pg0, tx, self.pg0)
632 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
638 ip_10_0_0_1.remove_vpp_config()
639 route_34_neos.remove_vpp_config()
640 route_34_eos.remove_vpp_config()
641 route_33_neos.remove_vpp_config()
642 route_33_eos.remove_vpp_config()
643 route_32_neos.remove_vpp_config()
644 route_32_eos.remove_vpp_config()
647 """ MPLS Local Label Binding test """
650 # Add a non-recursive route with a single out label
652 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
653 [VppRoutePath(self.pg0.remote_ip4,
654 self.pg0.sw_if_index,
655 labels=[VppMplsLabel(45)])])
656 route_10_0_0_1.add_vpp_config()
658 # bind a local label to the route
659 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
660 binding.add_vpp_config()
663 tx = self.create_stream_labelled_ip4(self.pg0,
666 rx = self.send_and_expect(self.pg0, tx, self.pg0)
667 self.verify_capture_labelled(self.pg0, rx, tx,
668 [VppMplsLabel(45, ttl=63),
672 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
673 rx = self.send_and_expect(self.pg0, tx, self.pg0)
674 self.verify_capture_labelled(self.pg0, rx, tx,
675 [VppMplsLabel(45, ttl=63)])
678 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
679 rx = self.send_and_expect(self.pg0, tx, self.pg0)
680 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
685 binding.remove_vpp_config()
686 route_10_0_0_1.remove_vpp_config()
688 def test_imposition(self):
689 """ MPLS label imposition test """
692 # Add a non-recursive route with a single out label
694 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
695 [VppRoutePath(self.pg0.remote_ip4,
696 self.pg0.sw_if_index,
697 labels=[VppMplsLabel(32)])])
698 route_10_0_0_1.add_vpp_config()
701 # a stream that matches the route for 10.0.0.1
702 # PG0 is in the default table
704 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
705 rx = self.send_and_expect(self.pg0, tx, self.pg0)
706 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
709 # Add a non-recursive route with a 3 out labels
711 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
712 [VppRoutePath(self.pg0.remote_ip4,
713 self.pg0.sw_if_index,
714 labels=[VppMplsLabel(32),
717 route_10_0_0_2.add_vpp_config()
719 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
720 ip_ttl=44, ip_dscp=0xff)
721 rx = self.send_and_expect(self.pg0, tx, self.pg0)
722 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
729 # Add a non-recursive route with a single out label in uniform mode
731 route_10_0_0_3 = VppIpRoute(
732 self, "10.0.0.3", 32,
733 [VppRoutePath(self.pg0.remote_ip4,
734 self.pg0.sw_if_index,
735 labels=[VppMplsLabel(32,
736 mode=MplsLspMode.UNIFORM)])])
737 route_10_0_0_3.add_vpp_config()
739 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
740 ip_ttl=54, ip_dscp=0xbe)
741 rx = self.send_and_expect(self.pg0, tx, self.pg0)
742 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
743 [VppMplsLabel(32, ttl=53, exp=5)])
746 # Add a IPv6 non-recursive route with a single out label in
749 route_2001_3 = VppIpRoute(
750 self, "2001::3", 128,
751 [VppRoutePath(self.pg0.remote_ip6,
752 self.pg0.sw_if_index,
753 proto=DpoProto.DPO_PROTO_IP6,
754 labels=[VppMplsLabel(32,
755 mode=MplsLspMode.UNIFORM)])],
757 route_2001_3.add_vpp_config()
759 tx = self.create_stream_ip6(self.pg0, "2001::3",
760 ip_ttl=54, ip_dscp=0xbe)
761 rx = self.send_and_expect(self.pg0, tx, self.pg0)
762 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
763 [VppMplsLabel(32, ttl=53, exp=5)])
766 # add a recursive path, with output label, via the 1 label route
768 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
769 [VppRoutePath("10.0.0.1",
771 labels=[VppMplsLabel(44)])])
772 route_11_0_0_1.add_vpp_config()
775 # a stream that matches the route for 11.0.0.1, should pick up
776 # the label stack for 11.0.0.1 and 10.0.0.1
778 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
779 rx = self.send_and_expect(self.pg0, tx, self.pg0)
780 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
785 # add a recursive path, with 2 labels, via the 3 label route
787 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
788 [VppRoutePath("10.0.0.2",
790 labels=[VppMplsLabel(44),
792 route_11_0_0_2.add_vpp_config()
795 # a stream that matches the route for 11.0.0.1, should pick up
796 # the label stack for 11.0.0.1 and 10.0.0.1
798 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
799 rx = self.send_and_expect(self.pg0, tx, self.pg0)
800 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
810 route_11_0_0_2.remove_vpp_config()
811 route_11_0_0_1.remove_vpp_config()
812 route_10_0_0_2.remove_vpp_config()
813 route_10_0_0_1.remove_vpp_config()
815 def test_tunnel_pipe(self):
816 """ MPLS Tunnel Tests - Pipe """
819 # Create a tunnel with a single out label
821 mpls_tun = VppMPLSTunnelInterface(
823 [VppRoutePath(self.pg0.remote_ip4,
824 self.pg0.sw_if_index,
825 labels=[VppMplsLabel(44),
827 mpls_tun.add_vpp_config()
831 # add an unlabelled route through the new tunnel
833 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
834 [VppRoutePath("0.0.0.0",
835 mpls_tun._sw_if_index)])
836 route_10_0_0_3.add_vpp_config()
838 self.vapi.cli("clear trace")
839 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
840 self.pg0.add_stream(tx)
842 self.pg_enable_capture(self.pg_interfaces)
845 rx = self.pg0.get_capture()
846 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
851 # add a labelled route through the new tunnel
853 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
854 [VppRoutePath("0.0.0.0",
855 mpls_tun._sw_if_index,
857 route_10_0_0_4.add_vpp_config()
859 self.vapi.cli("clear trace")
860 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
861 self.pg0.add_stream(tx)
863 self.pg_enable_capture(self.pg_interfaces)
866 rx = self.pg0.get_capture()
867 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
870 VppMplsLabel(33, ttl=255)])
872 def test_tunnel_uniform(self):
873 """ MPLS Tunnel Tests - Uniform """
876 # Create a tunnel with a single out label
877 # The label stack is specified here from outer to inner
879 mpls_tun = VppMPLSTunnelInterface(
881 [VppRoutePath(self.pg0.remote_ip4,
882 self.pg0.sw_if_index,
883 labels=[VppMplsLabel(44, ttl=32),
884 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
885 mpls_tun.add_vpp_config()
889 # add an unlabelled route through the new tunnel
891 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
892 [VppRoutePath("0.0.0.0",
893 mpls_tun._sw_if_index)])
894 route_10_0_0_3.add_vpp_config()
896 self.vapi.cli("clear trace")
897 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
898 self.pg0.add_stream(tx)
900 self.pg_enable_capture(self.pg_interfaces)
903 rx = self.pg0.get_capture()
904 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
905 [VppMplsLabel(44, ttl=32),
906 VppMplsLabel(46, ttl=23)])
909 # add a labelled route through the new tunnel
911 route_10_0_0_4 = VppIpRoute(
912 self, "10.0.0.4", 32,
913 [VppRoutePath("0.0.0.0",
914 mpls_tun._sw_if_index,
915 labels=[VppMplsLabel(33, ttl=47)])])
916 route_10_0_0_4.add_vpp_config()
918 self.vapi.cli("clear trace")
919 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
920 self.pg0.add_stream(tx)
922 self.pg_enable_capture(self.pg_interfaces)
925 rx = self.pg0.get_capture()
926 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
927 [VppMplsLabel(44, ttl=32),
928 VppMplsLabel(46, ttl=47),
929 VppMplsLabel(33, ttl=47)])
931 def test_v4_exp_null(self):
932 """ MPLS V4 Explicit NULL test """
935 # The first test case has an MPLS TTL of 0
936 # all packet should be dropped
938 tx = self.create_stream_labelled_ip4(self.pg0,
939 [VppMplsLabel(0, ttl=0)])
940 self.send_and_assert_no_replies(self.pg0, tx,
941 "MPLS TTL=0 packets forwarded")
944 # a stream with a non-zero MPLS TTL
945 # PG0 is in the default table
947 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
948 rx = self.send_and_expect(self.pg0, tx, self.pg0)
949 self.verify_capture_ip4(self.pg0, rx, tx)
952 # a stream with a non-zero MPLS TTL
954 # we are ensuring the post-pop lookup occurs in the VRF table
956 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
957 rx = self.send_and_expect(self.pg1, tx, self.pg1)
958 self.verify_capture_ip4(self.pg1, rx, tx)
960 def test_v6_exp_null(self):
961 """ MPLS V6 Explicit NULL test """
964 # a stream with a non-zero MPLS TTL
965 # PG0 is in the default table
967 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
968 rx = self.send_and_expect(self.pg0, tx, self.pg0)
969 self.verify_capture_ip6(self.pg0, rx, tx)
972 # a stream with a non-zero MPLS TTL
974 # we are ensuring the post-pop lookup occurs in the VRF table
976 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
977 rx = self.send_and_expect(self.pg1, tx, self.pg1)
978 self.verify_capture_ip6(self.pg0, rx, tx)
984 # A de-agg route - next-hop lookup in default table
986 route_34_eos = VppMplsRoute(self, 34, 1,
987 [VppRoutePath("0.0.0.0",
990 route_34_eos.add_vpp_config()
993 # ping an interface in the default table
994 # PG0 is in the default table
996 tx = self.create_stream_labelled_ip4(self.pg0,
1000 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1001 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1004 # A de-agg route - next-hop lookup in non-default table
1006 route_35_eos = VppMplsRoute(self, 35, 1,
1007 [VppRoutePath("0.0.0.0",
1010 route_35_eos.add_vpp_config()
1013 # ping an interface in the non-default table
1014 # PG0 is in the default table. packet arrive labelled in the
1015 # default table and egress unlabelled in the non-default
1017 tx = self.create_stream_labelled_ip4(
1018 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1019 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1020 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1025 route_36_neos = VppMplsRoute(self, 36, 0,
1026 [VppRoutePath("0.0.0.0",
1028 route_36_neos.add_vpp_config()
1030 tx = self.create_stream_labelled_ip4(self.pg0,
1033 ping=1, ip_itf=self.pg1)
1034 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1035 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1037 route_36_neos.remove_vpp_config()
1038 route_35_eos.remove_vpp_config()
1039 route_34_eos.remove_vpp_config()
1041 def test_interface_rx(self):
1042 """ MPLS Interface Receive """
1045 # Add a non-recursive route that will forward the traffic
1048 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1050 paths=[VppRoutePath(self.pg1.remote_ip4,
1051 self.pg1.sw_if_index)])
1052 route_10_0_0_1.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 interface-rx on pg1 and matching a route in table 1
1059 # if the packet egresses, then we must have swapped to pg1
1060 # so as to have matched the route in table 1
1062 route_34_eos = VppMplsRoute(self, 34, 1,
1063 [VppRoutePath("0.0.0.0",
1064 self.pg1.sw_if_index,
1065 is_interface_rx=1)])
1066 route_34_eos.add_vpp_config()
1069 # ping an interface in the default table
1070 # PG0 is in the default table
1072 tx = self.create_stream_labelled_ip4(self.pg0,
1075 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1076 self.verify_capture_ip4(self.pg1, rx, tx)
1078 def test_mcast_mid_point(self):
1079 """ MPLS Multicast Mid Point """
1082 # Add a non-recursive route that will forward the traffic
1085 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1087 paths=[VppRoutePath(self.pg1.remote_ip4,
1088 self.pg1.sw_if_index)])
1089 route_10_0_0_1.add_vpp_config()
1092 # Add a mcast entry that replicate to pg2 and pg3
1093 # and replicate to a interface-rx (like a bud node would)
1095 route_3400_eos = VppMplsRoute(
1097 [VppRoutePath(self.pg2.remote_ip4,
1098 self.pg2.sw_if_index,
1099 labels=[VppMplsLabel(3401)]),
1100 VppRoutePath(self.pg3.remote_ip4,
1101 self.pg3.sw_if_index,
1102 labels=[VppMplsLabel(3402)]),
1103 VppRoutePath("0.0.0.0",
1104 self.pg1.sw_if_index,
1105 is_interface_rx=1)],
1107 route_3400_eos.add_vpp_config()
1110 # ping an interface in the default table
1111 # PG0 is in the default table
1113 self.vapi.cli("clear trace")
1114 tx = self.create_stream_labelled_ip4(self.pg0,
1115 [VppMplsLabel(3400, ttl=64)],
1118 self.pg0.add_stream(tx)
1120 self.pg_enable_capture(self.pg_interfaces)
1123 rx = self.pg1.get_capture(257)
1124 self.verify_capture_ip4(self.pg1, rx, tx)
1126 rx = self.pg2.get_capture(257)
1127 self.verify_capture_labelled(self.pg2, rx, tx,
1128 [VppMplsLabel(3401, ttl=63)])
1129 rx = self.pg3.get_capture(257)
1130 self.verify_capture_labelled(self.pg3, rx, tx,
1131 [VppMplsLabel(3402, ttl=63)])
1133 def test_mcast_head(self):
1134 """ MPLS Multicast Head-end """
1137 # Create a multicast tunnel with two replications
1139 mpls_tun = VppMPLSTunnelInterface(
1141 [VppRoutePath(self.pg2.remote_ip4,
1142 self.pg2.sw_if_index,
1143 labels=[VppMplsLabel(42)]),
1144 VppRoutePath(self.pg3.remote_ip4,
1145 self.pg3.sw_if_index,
1146 labels=[VppMplsLabel(43)])],
1148 mpls_tun.add_vpp_config()
1152 # add an unlabelled route through the new tunnel
1154 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1155 [VppRoutePath("0.0.0.0",
1156 mpls_tun._sw_if_index)])
1157 route_10_0_0_3.add_vpp_config()
1159 self.vapi.cli("clear trace")
1160 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1161 self.pg0.add_stream(tx)
1163 self.pg_enable_capture(self.pg_interfaces)
1166 rx = self.pg2.get_capture(257)
1167 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
1168 rx = self.pg3.get_capture(257)
1169 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
1172 # An an IP multicast route via the tunnel
1174 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1176 route_232_1_1_1 = VppIpMRoute(
1180 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1181 [VppMRoutePath(self.pg0.sw_if_index,
1182 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1183 VppMRoutePath(mpls_tun._sw_if_index,
1184 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1185 route_232_1_1_1.add_vpp_config()
1187 self.vapi.cli("clear trace")
1188 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1189 self.pg0.add_stream(tx)
1191 self.pg_enable_capture(self.pg_interfaces)
1194 rx = self.pg2.get_capture(257)
1195 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
1196 rx = self.pg3.get_capture(257)
1197 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
1199 def test_mcast_ip4_tail(self):
1200 """ MPLS IPv4 Multicast Tail """
1203 # Add a multicast route that will forward the traffic
1206 route_232_1_1_1 = VppIpMRoute(
1210 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1212 paths=[VppMRoutePath(self.pg1.sw_if_index,
1213 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1214 route_232_1_1_1.add_vpp_config()
1217 # An interface receive label that maps traffic to RX on interface
1219 # by injecting the packet in on pg0, which is in table 0
1220 # doing an rpf-id and matching a route in table 1
1221 # if the packet egresses, then we must have matched the route in
1224 route_34_eos = VppMplsRoute(self, 34, 1,
1225 [VppRoutePath("0.0.0.0",
1226 self.pg1.sw_if_index,
1231 route_34_eos.add_vpp_config()
1234 # Drop due to interface lookup miss
1236 self.vapi.cli("clear trace")
1237 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1238 dst_ip="232.1.1.1", n=1)
1239 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1242 # set the RPF-ID of the enrtry to match the input packet's
1244 route_232_1_1_1.update_rpf_id(55)
1246 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1248 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1249 self.verify_capture_ip4(self.pg1, rx, tx)
1252 # disposed packets have an invalid IPv4 checkusm
1254 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1255 dst_ip="232.1.1.1", n=65,
1257 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1260 # set the RPF-ID of the entry to not match the input packet's
1262 route_232_1_1_1.update_rpf_id(56)
1263 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1265 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1267 def test_mcast_ip6_tail(self):
1268 """ MPLS IPv6 Multicast Tail """
1271 # Add a multicast route that will forward the traffic
1274 route_ff = VppIpMRoute(
1278 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1280 paths=[VppMRoutePath(self.pg1.sw_if_index,
1281 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1283 route_ff.add_vpp_config()
1286 # An interface receive label that maps traffic to RX on interface
1288 # by injecting the packet in on pg0, which is in table 0
1289 # doing an rpf-id and matching a route in table 1
1290 # if the packet egresses, then we must have matched the route in
1293 route_34_eos = VppMplsRoute(
1296 self.pg1.sw_if_index,
1299 proto=DpoProto.DPO_PROTO_IP6)],
1302 route_34_eos.add_vpp_config()
1305 # Drop due to interface lookup miss
1307 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
1309 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
1312 # set the RPF-ID of the enrtry to match the input packet's
1314 route_ff.update_rpf_id(55)
1316 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
1318 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1319 self.verify_capture_ip6(self.pg1, rx, tx)
1322 # disposed packets have hop-limit = 1
1324 tx = self.create_stream_labelled_ip6(self.pg0,
1328 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1329 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
1332 # set the RPF-ID of the enrtry to not match the input packet's
1334 route_ff.update_rpf_id(56)
1335 tx = self.create_stream_labelled_ip6(self.pg0,
1338 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1341 class TestMPLSDisabled(VppTestCase):
1342 """ MPLS disabled """
1345 super(TestMPLSDisabled, self).setUp()
1347 # create 2 pg interfaces
1348 self.create_pg_interfaces(range(2))
1350 self.tbl = VppMplsTable(self, 0)
1351 self.tbl.add_vpp_config()
1353 # PG0 is MPLS enalbed
1355 self.pg0.config_ip4()
1356 self.pg0.resolve_arp()
1357 self.pg0.enable_mpls()
1359 # PG 1 is not MPLS enabled
1363 for i in self.pg_interfaces:
1367 self.pg0.disable_mpls()
1368 super(TestMPLSDisabled, self).tearDown()
1370 def test_mpls_disabled(self):
1371 """ MPLS Disabled """
1373 tx = (Ether(src=self.pg1.remote_mac,
1374 dst=self.pg1.local_mac) /
1375 MPLS(label=32, ttl=64) /
1376 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1377 UDP(sport=1234, dport=1234) /
1381 # A simple MPLS xconnect - eos label in label out
1383 route_32_eos = VppMplsRoute(self, 32, 1,
1384 [VppRoutePath(self.pg0.remote_ip4,
1385 self.pg0.sw_if_index,
1387 route_32_eos.add_vpp_config()
1390 # PG1 does not forward IP traffic
1392 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1397 self.pg1.enable_mpls()
1400 # Now we get packets through
1402 self.pg1.add_stream(tx)
1403 self.pg_enable_capture(self.pg_interfaces)
1406 rx = self.pg0.get_capture(1)
1411 self.pg1.disable_mpls()
1414 # PG1 does not forward IP traffic
1416 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1417 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1420 class TestMPLSPIC(VppTestCase):
1421 """ MPLS PIC edge convergence """
1424 super(TestMPLSPIC, self).setUp()
1426 # create 2 pg interfaces
1427 self.create_pg_interfaces(range(4))
1429 mpls_tbl = VppMplsTable(self, 0)
1430 mpls_tbl.add_vpp_config()
1431 tbl4 = VppIpTable(self, 1)
1432 tbl4.add_vpp_config()
1433 tbl6 = VppIpTable(self, 1, is_ip6=1)
1434 tbl6.add_vpp_config()
1438 self.pg0.config_ip4()
1439 self.pg0.resolve_arp()
1440 self.pg0.enable_mpls()
1442 self.pg1.config_ip4()
1443 self.pg1.resolve_arp()
1444 self.pg1.enable_mpls()
1446 # VRF (customer facing) link
1448 self.pg2.set_table_ip4(1)
1449 self.pg2.config_ip4()
1450 self.pg2.resolve_arp()
1451 self.pg2.set_table_ip6(1)
1452 self.pg2.config_ip6()
1453 self.pg2.resolve_ndp()
1455 self.pg3.set_table_ip4(1)
1456 self.pg3.config_ip4()
1457 self.pg3.resolve_arp()
1458 self.pg3.set_table_ip6(1)
1459 self.pg3.config_ip6()
1460 self.pg3.resolve_ndp()
1463 self.pg0.disable_mpls()
1464 self.pg1.disable_mpls()
1465 for i in self.pg_interfaces:
1471 super(TestMPLSPIC, self).tearDown()
1473 def test_mpls_ibgp_pic(self):
1474 """ MPLS iBGP PIC edge convergence
1476 1) setup many iBGP VPN routes via a pair of iBGP peers.
1477 2) Check EMCP forwarding to these peers
1478 3) withdraw the IGP route to one of these peers.
1479 4) check forwarding continues to the remaining peer
1483 # IGP+LDP core routes
1485 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1486 [VppRoutePath(self.pg0.remote_ip4,
1487 self.pg0.sw_if_index,
1489 core_10_0_0_45.add_vpp_config()
1491 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1492 [VppRoutePath(self.pg1.remote_ip4,
1493 self.pg1.sw_if_index,
1495 core_10_0_0_46.add_vpp_config()
1498 # Lot's of VPN routes. We need more the 64 so VPP will build
1499 # the fast convergence indirection
1503 for ii in range(64):
1504 dst = "192.168.1.%d" % ii
1505 vpn_routes.append(VppIpRoute(self, dst, 32,
1506 [VppRoutePath("10.0.0.45",
1510 VppRoutePath("10.0.0.46",
1513 is_resolve_host=1)],
1515 vpn_routes[ii].add_vpp_config()
1517 pkts.append(Ether(dst=self.pg2.local_mac,
1518 src=self.pg2.remote_mac) /
1519 IP(src=self.pg2.remote_ip4, dst=dst) /
1520 UDP(sport=1234, dport=1234) /
1524 # Send the packet stream (one pkt to each VPN route)
1525 # - expect a 50-50 split of the traffic
1527 self.pg2.add_stream(pkts)
1528 self.pg_enable_capture(self.pg_interfaces)
1531 rx0 = self.pg0._get_capture(1)
1532 rx1 = self.pg1._get_capture(1)
1534 # not testig the LB hashing algorithm so we're not concerned
1535 # with the split ratio, just as long as neither is 0
1536 self.assertNotEqual(0, len(rx0))
1537 self.assertNotEqual(0, len(rx1))
1540 # use a test CLI command to stop the FIB walk process, this
1541 # will prevent the FIB converging the VPN routes and thus allow
1542 # us to probe the interim (psot-fail, pre-converge) state
1544 self.vapi.ppcli("test fib-walk-process disable")
1547 # Withdraw one of the IGP routes
1549 core_10_0_0_46.remove_vpp_config()
1552 # now all packets should be forwarded through the remaining peer
1554 self.vapi.ppcli("clear trace")
1555 self.pg2.add_stream(pkts)
1556 self.pg_enable_capture(self.pg_interfaces)
1559 rx0 = self.pg0.get_capture(len(pkts))
1562 # enable the FIB walk process to converge the FIB
1564 self.vapi.ppcli("test fib-walk-process enable")
1567 # packets should still be forwarded through the remaining peer
1569 self.pg2.add_stream(pkts)
1570 self.pg_enable_capture(self.pg_interfaces)
1573 rx0 = self.pg0.get_capture(64)
1576 # Add the IGP route back and we return to load-balancing
1578 core_10_0_0_46.add_vpp_config()
1580 self.pg2.add_stream(pkts)
1581 self.pg_enable_capture(self.pg_interfaces)
1584 rx0 = self.pg0._get_capture(1)
1585 rx1 = self.pg1._get_capture(1)
1586 self.assertNotEqual(0, len(rx0))
1587 self.assertNotEqual(0, len(rx1))
1589 def test_mpls_ebgp_pic(self):
1590 """ MPLS eBGP PIC edge convergence
1592 1) setup many eBGP VPN routes via a pair of eBGP peers
1593 2) Check EMCP forwarding to these peers
1594 3) withdraw one eBGP path - expect LB across remaining eBGP
1598 # Lot's of VPN routes. We need more the 64 so VPP will build
1599 # the fast convergence indirection
1604 for ii in range(64):
1605 dst = "192.168.1.%d" % ii
1606 local_label = 1600 + ii
1607 vpn_routes.append(VppIpRoute(self, dst, 32,
1608 [VppRoutePath(self.pg2.remote_ip4,
1611 is_resolve_attached=1),
1612 VppRoutePath(self.pg3.remote_ip4,
1615 is_resolve_attached=1)],
1617 vpn_routes[ii].add_vpp_config()
1619 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1621 vpn_bindings[ii].add_vpp_config()
1623 pkts.append(Ether(dst=self.pg0.local_mac,
1624 src=self.pg0.remote_mac) /
1625 MPLS(label=local_label, ttl=64) /
1626 IP(src=self.pg0.remote_ip4, dst=dst) /
1627 UDP(sport=1234, dport=1234) /
1630 self.pg0.add_stream(pkts)
1631 self.pg_enable_capture(self.pg_interfaces)
1634 rx0 = self.pg2._get_capture(1)
1635 rx1 = self.pg3._get_capture(1)
1636 self.assertNotEqual(0, len(rx0))
1637 self.assertNotEqual(0, len(rx1))
1640 # use a test CLI command to stop the FIB walk process, this
1641 # will prevent the FIB converging the VPN routes and thus allow
1642 # us to probe the interim (psot-fail, pre-converge) state
1644 self.vapi.ppcli("test fib-walk-process disable")
1647 # withdraw the connected prefix on the interface.
1649 self.pg2.unconfig_ip4()
1652 # now all packets should be forwarded through the remaining peer
1654 self.pg0.add_stream(pkts)
1655 self.pg_enable_capture(self.pg_interfaces)
1658 rx0 = self.pg3.get_capture(len(pkts))
1661 # enable the FIB walk process to converge the FIB
1663 self.vapi.ppcli("test fib-walk-process enable")
1664 self.pg0.add_stream(pkts)
1665 self.pg_enable_capture(self.pg_interfaces)
1668 rx0 = self.pg3.get_capture(len(pkts))
1671 # put the connecteds back
1673 self.pg2.config_ip4()
1675 self.pg0.add_stream(pkts)
1676 self.pg_enable_capture(self.pg_interfaces)
1679 rx0 = self.pg2._get_capture(1)
1680 rx1 = self.pg3._get_capture(1)
1681 self.assertNotEqual(0, len(rx0))
1682 self.assertNotEqual(0, len(rx1))
1684 def test_mpls_v6_ebgp_pic(self):
1685 """ MPLSv6 eBGP PIC edge convergence
1687 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1688 2) Check EMCP forwarding to these peers
1689 3) withdraw one eBGP path - expect LB across remaining eBGP
1693 # Lot's of VPN routes. We need more the 64 so VPP will build
1694 # the fast convergence indirection
1699 for ii in range(64):
1700 dst = "3000::%d" % ii
1701 local_label = 1600 + ii
1702 vpn_routes.append(VppIpRoute(
1704 [VppRoutePath(self.pg2.remote_ip6,
1707 is_resolve_attached=1,
1708 proto=DpoProto.DPO_PROTO_IP6),
1709 VppRoutePath(self.pg3.remote_ip6,
1712 proto=DpoProto.DPO_PROTO_IP6,
1713 is_resolve_attached=1)],
1716 vpn_routes[ii].add_vpp_config()
1718 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1721 vpn_bindings[ii].add_vpp_config()
1723 pkts.append(Ether(dst=self.pg0.local_mac,
1724 src=self.pg0.remote_mac) /
1725 MPLS(label=local_label, ttl=64) /
1726 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1727 UDP(sport=1234, dport=1234) /
1730 self.pg0.add_stream(pkts)
1731 self.pg_enable_capture(self.pg_interfaces)
1734 rx0 = self.pg2._get_capture(1)
1735 rx1 = self.pg3._get_capture(1)
1736 self.assertNotEqual(0, len(rx0))
1737 self.assertNotEqual(0, len(rx1))
1740 # use a test CLI command to stop the FIB walk process, this
1741 # will prevent the FIB converging the VPN routes and thus allow
1742 # us to probe the interim (psot-fail, pre-converge) state
1744 self.vapi.ppcli("test fib-walk-process disable")
1747 # withdraw the connected prefix on the interface.
1748 # and shutdown the interface so the ND cache is flushed.
1750 self.pg2.unconfig_ip6()
1751 self.pg2.admin_down()
1754 # now all packets should be forwarded through the remaining peer
1756 self.pg0.add_stream(pkts)
1757 self.pg_enable_capture(self.pg_interfaces)
1760 rx0 = self.pg3.get_capture(len(pkts))
1763 # enable the FIB walk process to converge the FIB
1765 self.vapi.ppcli("test fib-walk-process enable")
1766 self.pg0.add_stream(pkts)
1767 self.pg_enable_capture(self.pg_interfaces)
1770 rx0 = self.pg3.get_capture(len(pkts))
1773 # put the connecteds back
1776 self.pg2.config_ip6()
1778 self.pg0.add_stream(pkts)
1779 self.pg_enable_capture(self.pg_interfaces)
1782 rx0 = self.pg2._get_capture(1)
1783 rx1 = self.pg3._get_capture(1)
1784 self.assertNotEqual(0, len(rx0))
1785 self.assertNotEqual(0, len(rx1))
1788 class TestMPLSL2(VppTestCase):
1792 super(TestMPLSL2, self).setUp()
1794 # create 2 pg interfaces
1795 self.create_pg_interfaces(range(2))
1797 # create the default MPLS table
1799 tbl = VppMplsTable(self, 0)
1800 tbl.add_vpp_config()
1801 self.tables.append(tbl)
1803 # use pg0 as the core facing interface
1805 self.pg0.config_ip4()
1806 self.pg0.resolve_arp()
1807 self.pg0.enable_mpls()
1809 # use the other 2 for customer facing L2 links
1810 for i in self.pg_interfaces[1:]:
1814 for i in self.pg_interfaces[1:]:
1817 self.pg0.disable_mpls()
1818 self.pg0.unconfig_ip4()
1819 self.pg0.admin_down()
1820 super(TestMPLSL2, self).tearDown()
1822 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
1823 capture = verify_filter(capture, sent)
1825 self.assertEqual(len(capture), len(sent))
1827 for i in range(len(capture)):
1831 # the MPLS TTL is 255 since it enters a new tunnel
1832 verify_mpls_stack(self, rx, mpls_labels)
1835 rx_eth = Ether(str(rx[MPLS].payload))
1837 self.assertEqual(rx_eth.src, tx_eth.src)
1838 self.assertEqual(rx_eth.dst, tx_eth.dst)
1840 def test_vpws(self):
1841 """ Virtual Private Wire Service """
1844 # Create an MPLS tunnel that pushes 1 label
1845 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
1846 # information is not in the packet, but we test it works anyway
1848 mpls_tun_1 = VppMPLSTunnelInterface(
1850 [VppRoutePath(self.pg0.remote_ip4,
1851 self.pg0.sw_if_index,
1852 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
1854 mpls_tun_1.add_vpp_config()
1855 mpls_tun_1.admin_up()
1858 # Create a label entry to for 55 that does L2 input to the tunnel
1860 route_55_eos = VppMplsRoute(
1862 [VppRoutePath("0.0.0.0",
1863 mpls_tun_1.sw_if_index,
1865 proto=DpoProto.DPO_PROTO_ETHERNET)])
1866 route_55_eos.add_vpp_config()
1869 # Cross-connect the tunnel with one of the customers L2 interfaces
1871 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1872 mpls_tun_1.sw_if_index,
1874 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1875 self.pg1.sw_if_index,
1879 # inject a packet from the core
1881 pcore = (Ether(dst=self.pg0.local_mac,
1882 src=self.pg0.remote_mac) /
1883 MPLS(label=55, ttl=64) /
1884 Ether(dst="00:00:de:ad:ba:be",
1885 src="00:00:de:ad:be:ef") /
1886 IP(src="10.10.10.10", dst="11.11.11.11") /
1887 UDP(sport=1234, dport=1234) /
1891 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
1892 payload = pcore[MPLS].payload
1894 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
1895 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
1898 # Inject a packet from the custoer/L2 side
1900 tx1 = pcore[MPLS].payload * 65
1901 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
1903 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
1905 def test_vpls(self):
1906 """ Virtual Private LAN Service """
1908 # Create an L2 MPLS tunnel
1910 mpls_tun = VppMPLSTunnelInterface(
1912 [VppRoutePath(self.pg0.remote_ip4,
1913 self.pg0.sw_if_index,
1914 labels=[VppMplsLabel(42)])],
1916 mpls_tun.add_vpp_config()
1920 # Create a label entry to for 55 that does L2 input to the tunnel
1922 route_55_eos = VppMplsRoute(
1924 [VppRoutePath("0.0.0.0",
1925 mpls_tun.sw_if_index,
1927 proto=DpoProto.DPO_PROTO_ETHERNET)])
1928 route_55_eos.add_vpp_config()
1931 # add to tunnel to the customers bridge-domain
1933 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1935 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1939 # Packet from the customer interface and from the core
1941 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1942 src="00:00:de:ad:be:ef") /
1943 IP(src="10.10.10.10", dst="11.11.11.11") /
1944 UDP(sport=1234, dport=1234) /
1946 p_core = (Ether(src="00:00:de:ad:ba:be",
1947 dst="00:00:de:ad:be:ef") /
1948 IP(dst="10.10.10.10", src="11.11.11.11") /
1949 UDP(sport=1234, dport=1234) /
1953 # The BD is learning, so send in one of each packet to learn
1955 p_core_encap = (Ether(dst=self.pg0.local_mac,
1956 src=self.pg0.remote_mac) /
1957 MPLS(label=55, ttl=64) /
1960 self.pg1.add_stream(p_cust)
1961 self.pg_enable_capture(self.pg_interfaces)
1963 self.pg0.add_stream(p_core_encap)
1964 self.pg_enable_capture(self.pg_interfaces)
1967 # we've learnt this so expect it be be forwarded
1968 rx0 = self.pg1.get_capture(1)
1970 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1971 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1974 # now a stream in each direction
1976 self.pg1.add_stream(p_cust * 65)
1977 self.pg_enable_capture(self.pg_interfaces)
1980 rx0 = self.pg0.get_capture(65)
1982 self.verify_capture_tunneled_ethernet(rx0, p_cust*65,
1986 # remove interfaces from customers bridge-domain
1988 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1991 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1995 if __name__ == '__main__':
1996 unittest.main(testRunner=VppTestRunner)