5 from config import config
6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip import DpoProto
8 from vpp_ip_route import (
20 from vpp_bier import (
29 from vpp_udp_encap import VppUdpEncap
30 from vpp_papi import VppEnum
33 from scapy.packet import Raw
34 from scapy.layers.l2 import Ether
35 from scapy.layers.inet import IP, UDP
36 from scapy.layers.inet6 import IPv6
37 from scapy.contrib.mpls import MPLS
38 from scapy.contrib.bier import BIER, BIERLength, BIFT
43 class TestBFIB(VppTestCase):
44 """BIER FIB Test Case"""
48 error = self.vapi.cli("test bier")
51 self.logger.critical(error)
52 self.assertNotIn("Failed", error)
55 class TestBier(VppTestCase):
59 super(TestBier, self).setUp()
61 # create 2 pg interfaces
62 self.create_pg_interfaces(range(3))
64 # create the default MPLS table
66 tbl = VppMplsTable(self, 0)
68 self.tables.append(tbl)
70 tbl = VppIpTable(self, 10)
72 self.tables.append(tbl)
74 # setup both interfaces
75 for i in self.pg_interfaces:
84 for i in self.pg_interfaces:
89 super(TestBier, self).tearDown()
91 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
95 # Add a BIER table for sub-domain 0, set 0, and BSL 256
97 bti = VppBierTableID(0, 0, hdr_len_id)
98 bt = VppBierTable(self, bti, 77)
102 # A packet with no bits set gets dropped
105 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
106 / MPLS(label=77, ttl=255)
107 / BIER(length=hdr_len_id)
108 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
109 / UDP(sport=1234, dport=1234)
114 self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String")
117 # Add a BIER route for each bit-position in the table via a different
118 # next-hop. Testing whether the BIER walk and replicate forwarding
119 # function works for all bit posisitons.
123 for i in range(1, max_bp + 1):
124 nh = "10.0.%d.%d" % (i / 255, i % 255)
133 self.pg1.sw_if_index,
134 labels=[VppMplsLabel(2000 + i)],
139 nh_routes[-1].add_vpp_config()
146 [VppRoutePath(nh, 0xFFFFFFFF, labels=[VppMplsLabel(100 + i)])],
149 bier_routes[-1].add_vpp_config()
152 # A packet with all bits set gets replicated once for each bit
154 pkt_sizes = [64, 1400]
156 for pkt_size in pkt_sizes:
158 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
159 / MPLS(label=77, ttl=255)
160 / BIER(length=hdr_len_id, BitString=scapy.compat.chb(255) * n_bytes)
161 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
162 / UDP(sport=1234, dport=1234)
163 / Raw(scapy.compat.chb(5) * pkt_size)
167 self.pg0.add_stream(pkts)
168 self.pg_enable_capture(self.pg_interfaces)
171 rx = self.pg1.get_capture(max_bp)
175 # The packets are not required to be sent in bit-position order
176 # when we setup the routes above we used the bit-position to
177 # construct the out-label. so use that here to determine the BP
180 bp = olabel.label - 2000
182 blabel = olabel[MPLS].payload
183 self.assertEqual(blabel.label, 100 + bp)
184 self.assertEqual(blabel.ttl, 254)
186 bier_hdr = blabel[MPLS].payload
188 self.assertEqual(bier_hdr.id, 5)
189 self.assertEqual(bier_hdr.version, 0)
190 self.assertEqual(bier_hdr.length, hdr_len_id)
191 self.assertEqual(bier_hdr.entropy, 0)
192 self.assertEqual(bier_hdr.OAM, 0)
193 self.assertEqual(bier_hdr.RSV, 0)
194 self.assertEqual(bier_hdr.DSCP, 0)
195 self.assertEqual(bier_hdr.Proto, 5)
197 # The bit-string should consist only of the BP given by i.
198 byte_array = [b"\0"] * (n_bytes)
199 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
200 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
201 byte_array[byte_pos] = byte_val
202 bitstring = b"".join(byte_array)
204 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
205 self.assertEqual(bitstring, bier_hdr.BitString)
208 # cleanup. not strictly necessary, but it's much quicker this way
209 # because the bier_fib_dump and ip_fib_dump will be empty when the
210 # auto-cleanup kicks in
212 for br in bier_routes:
213 br.remove_vpp_config()
214 for nhr in nh_routes:
215 nhr.remove_vpp_config()
217 @unittest.skipUnless(config.extended, "part of extended tests")
218 def test_bier_midpoint_1024(self):
219 """BIER midpoint BSL:1024"""
220 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
222 @unittest.skipUnless(config.extended, "part of extended tests")
223 def test_bier_midpoint_512(self):
224 """BIER midpoint BSL:512"""
225 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
227 @unittest.skipUnless(config.extended, "part of extended tests")
228 def test_bier_midpoint_256(self):
229 """BIER midpoint BSL:256"""
230 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
232 @unittest.skipUnless(config.extended, "part of extended tests")
233 def test_bier_midpoint_128(self):
234 """BIER midpoint BSL:128"""
235 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
237 def test_bier_midpoint_64(self):
238 """BIER midpoint BSL:64"""
239 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
241 def test_bier_load_balance(self):
242 """BIER load-balance"""
245 # Add a BIER table for sub-domain 0, set 0, and BSL 256
247 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
248 bt = VppBierTable(self, bti, 77)
252 # packets with varying entropy
255 for ii in range(257):
258 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
259 / MPLS(label=77, ttl=255)
261 length=BIERLength.BIER_LEN_64,
263 BitString=scapy.compat.chb(255) * 16,
265 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
266 / UDP(sport=1234, dport=1234)
275 {"ip": "10.0.0.1", "label": 201},
276 {"ip": "10.0.0.2", "label": 202},
277 {"ip": "10.0.0.3", "label": 203},
278 {"ip": "10.0.0.4", "label": 204},
289 self.pg1.sw_if_index,
290 labels=[VppMplsLabel(nh["label"])],
296 bier_route = VppBierRoute(
301 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
302 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
305 bier_route.add_vpp_config()
307 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
310 # we should have recieved a packet from each neighbor
313 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
316 # add the other paths
318 bier_route.update_paths(
320 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
321 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
322 VppRoutePath(nhs[2]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
323 VppRoutePath(nhs[3]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
327 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
330 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
333 # remove first two paths
335 bier_route.remove_path(
336 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)])
338 bier_route.remove_path(
339 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)])
342 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
344 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
347 # remove the last of the paths, deleteing the entry
349 bier_route.remove_all_paths()
351 self.send_and_assert_no_replies(self.pg0, pkts)
353 def test_bier_head(self):
356 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
357 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
360 # Add a BIER table for sub-domain 0, set 0, and BSL 256
362 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
363 bt = VppBierTable(self, bti, 77)
367 # 2 bit positions via two next hops
371 ip_route_1 = VppIpRoute(
378 self.pg1.sw_if_index,
379 labels=[VppMplsLabel(2001)],
383 ip_route_2 = VppIpRoute(
390 self.pg1.sw_if_index,
391 labels=[VppMplsLabel(2002)],
395 ip_route_1.add_vpp_config()
396 ip_route_2.add_vpp_config()
398 bier_route_1 = VppBierRoute(
399 self, bti, 1, [VppRoutePath(nh1, 0xFFFFFFFF, labels=[VppMplsLabel(101)])]
401 bier_route_2 = VppBierRoute(
402 self, bti, 2, [VppRoutePath(nh2, 0xFFFFFFFF, labels=[VppMplsLabel(102)])]
404 bier_route_1.add_vpp_config()
405 bier_route_2.add_vpp_config()
408 # An imposition object with both bit-positions set
410 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
414 # Add a multicast route that will forward into the BIER doamin
416 route_ing_232_1_1_1 = VppIpMRoute(
421 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
424 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
428 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
429 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
430 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
431 bier_imp=bi.bi_index,
435 route_ing_232_1_1_1.add_vpp_config()
438 # inject an IP packet. We expect it to be BIER encapped and
442 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
443 / IP(src="1.1.1.1", dst="232.1.1.1")
444 / UDP(sport=1234, dport=1234)
447 self.pg0.add_stream([p])
448 self.pg_enable_capture(self.pg_interfaces)
451 rx = self.pg1.get_capture(2)
454 # Encap Stack is; eth, MPLS, MPLS, BIER
456 igp_mpls = rx[0][MPLS]
457 self.assertEqual(igp_mpls.label, 2001)
458 self.assertEqual(igp_mpls.ttl, 64)
459 self.assertEqual(igp_mpls.s, 0)
460 bier_mpls = igp_mpls[MPLS].payload
461 self.assertEqual(bier_mpls.label, 101)
462 self.assertEqual(bier_mpls.ttl, 64)
463 self.assertEqual(bier_mpls.s, 1)
464 self.assertEqual(rx[0][BIER].length, 2)
466 igp_mpls = rx[1][MPLS]
467 self.assertEqual(igp_mpls.label, 2002)
468 self.assertEqual(igp_mpls.ttl, 64)
469 self.assertEqual(igp_mpls.s, 0)
470 bier_mpls = igp_mpls[MPLS].payload
471 self.assertEqual(bier_mpls.label, 102)
472 self.assertEqual(bier_mpls.ttl, 64)
473 self.assertEqual(bier_mpls.s, 1)
474 self.assertEqual(rx[0][BIER].length, 2)
476 def test_bier_tail(self):
479 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
480 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
483 # Add a BIER table for sub-domain 0, set 0, and BSL 256
485 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
486 bt = VppBierTable(self, bti, 77)
492 bdt = VppBierDispTable(self, 8)
496 # BIER route in table that's for-us
498 bier_route_1 = VppBierRoute(
506 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
511 bier_route_1.add_vpp_config()
514 # An entry in the disposition table
516 bier_de_1 = VppBierDispEntry(
520 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
521 FibPathProto.FIB_PATH_NH_PROTO_BIER,
526 bier_de_1.add_vpp_config()
529 # A multicast route to forward post BIER disposition
531 route_eg_232_1_1_1 = VppIpMRoute(
536 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
539 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
543 route_eg_232_1_1_1.add_vpp_config()
544 route_eg_232_1_1_1.update_rpf_id(8192)
547 # A packet with all bits set gets spat out to BP:1
550 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
551 / MPLS(label=77, ttl=255)
553 length=BIERLength.BIER_LEN_256,
554 BitString=scapy.compat.chb(255) * 32,
557 / IP(src="1.1.1.1", dst="232.1.1.1")
558 / UDP(sport=1234, dport=1234)
562 self.send_and_expect(self.pg0, [p], self.pg1)
565 # A packet that does not match the Disposition entry gets dropped
568 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
569 / MPLS(label=77, ttl=255)
571 length=BIERLength.BIER_LEN_256,
572 BitString=scapy.compat.chb(255) * 32,
575 / IP(src="1.1.1.1", dst="232.1.1.1")
576 / UDP(sport=1234, dport=1234)
579 self.send_and_assert_no_replies(
580 self.pg0, p * 2, "no matching disposition entry"
584 # Add the default route to the disposition table
586 bier_de_2 = VppBierDispEntry(
590 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
591 FibPathProto.FIB_PATH_NH_PROTO_BIER,
596 bier_de_2.add_vpp_config()
599 # now the previous packet is forwarded
601 self.send_and_expect(self.pg0, [p], self.pg1)
604 # A multicast route to forward post BIER disposition that needs
605 # a check against sending back into the BIER core
607 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
610 route_eg_232_1_1_2 = VppIpMRoute(
615 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
619 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
620 proto=DpoProto.DPO_PROTO_BIER,
621 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
622 bier_imp=bi.bi_index,
625 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
629 route_eg_232_1_1_2.add_vpp_config()
630 route_eg_232_1_1_2.update_rpf_id(8192)
633 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
634 / MPLS(label=77, ttl=255)
636 length=BIERLength.BIER_LEN_256,
637 BitString=scapy.compat.chb(255) * 32,
640 / IP(src="1.1.1.1", dst="232.1.1.2")
641 / UDP(sport=1234, dport=1234)
644 self.send_and_expect(self.pg0, [p], self.pg1)
646 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
647 """BIER end-to-end"""
649 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
650 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
653 # Add a BIER table for sub-domain 0, set 0, and BSL 256
655 bti = VppBierTableID(0, 0, hdr_len_id)
656 bt = VppBierTable(self, bti, 77)
659 lowest = [b"\0"] * (n_bytes)
660 lowest[-1] = scapy.compat.chb(1)
661 highest = [b"\0"] * (n_bytes)
662 highest[0] = scapy.compat.chb(128)
665 # Impostion Sets bit strings
667 bi_low = VppBierImp(self, bti, 333, lowest)
668 bi_low.add_vpp_config()
669 bi_high = VppBierImp(self, bti, 334, highest)
670 bi_high.add_vpp_config()
673 # Add a multicast route that will forward into the BIER doamin
675 route_ing_232_1_1_1 = VppIpMRoute(
680 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
683 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
687 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
688 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
689 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
690 bier_imp=bi_low.bi_index,
694 route_ing_232_1_1_1.add_vpp_config()
695 route_ing_232_1_1_2 = VppIpMRoute(
700 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
703 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
707 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
708 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
709 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
710 bier_imp=bi_high.bi_index,
714 route_ing_232_1_1_2.add_vpp_config()
717 # disposition table 8
719 bdt = VppBierDispTable(self, 8)
723 # BIER routes in table that are for-us, resolving through
726 bier_route_1 = VppBierRoute(
734 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
739 bier_route_1.add_vpp_config()
740 bier_route_max = VppBierRoute(
748 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
753 bier_route_max.add_vpp_config()
756 # An entry in the disposition table for sender 333
759 bier_de_1 = VppBierDispEntry(
763 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
764 FibPathProto.FIB_PATH_NH_PROTO_BIER,
769 bier_de_1.add_vpp_config()
770 bier_de_1 = VppBierDispEntry(
774 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
775 FibPathProto.FIB_PATH_NH_PROTO_BIER,
780 bier_de_1.add_vpp_config()
783 # Add a multicast routes that will forward the traffic
786 route_eg_232_1_1_1 = VppIpMRoute(
791 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
795 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
799 route_eg_232_1_1_1.add_vpp_config()
800 route_eg_232_1_1_1.update_rpf_id(8192)
801 route_eg_232_1_1_2 = VppIpMRoute(
806 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
810 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
814 route_eg_232_1_1_2.add_vpp_config()
815 route_eg_232_1_1_2.update_rpf_id(8193)
818 # inject a packet in VRF-0. We expect it to be BIER encapped,
819 # replicated, then hit the disposition and be forwarded
820 # out of VRF 10, i.e. on pg1
823 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
824 / IP(src="1.1.1.1", dst="232.1.1.1")
825 / UDP(sport=1234, dport=1234)
826 / Raw(scapy.compat.chb(5) * 32)
829 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
831 self.assertEqual(rx[0][IP].src, "1.1.1.1")
832 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
835 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
836 / IP(src="1.1.1.1", dst="232.1.1.2")
837 / UDP(sport=1234, dport=1234)
838 / Raw(scapy.compat.chb(5) * 512)
841 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
842 self.assertEqual(rx[0][IP].src, "1.1.1.1")
843 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
845 @unittest.skipUnless(config.extended, "part of extended tests")
846 def test_bier_e2e_1024(self):
847 """BIER end-to-end BSL:1024"""
848 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
850 @unittest.skipUnless(config.extended, "part of extended tests")
851 def test_bier_e2e_512(self):
852 """BIER end-to-end BSL:512"""
853 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
855 @unittest.skipUnless(config.extended, "part of extended tests")
856 def test_bier_e2e_256(self):
857 """BIER end-to-end BSL:256"""
858 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
860 @unittest.skipUnless(config.extended, "part of extended tests")
861 def test_bier_e2e_128(self):
862 """BIER end-to-end BSL:128"""
863 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
865 def test_bier_e2e_64(self):
866 """BIER end-to-end BSL:64"""
867 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
869 def test_bier_head_o_udp(self):
870 """BIER head over UDP"""
872 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
873 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
876 # Add a BIER table for sub-domain 1, set 0, and BSL 256
878 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
879 bt = VppBierTable(self, bti, 77)
883 # 1 bit positions via 1 next hops
886 ip_route = VppIpRoute(
893 self.pg1.sw_if_index,
894 labels=[VppMplsLabel(2001)],
898 ip_route.add_vpp_config()
900 udp_encap = VppUdpEncap(self, self.pg0.local_ip4, nh1, 330, 8138)
901 udp_encap.add_vpp_config()
903 bier_route = VppBierRoute(
911 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
912 next_hop_id=udp_encap.id,
916 bier_route.add_vpp_config()
919 # An 2 imposition objects with all bit-positions set
920 # only use the second, but creating 2 tests with a non-zero
921 # value index in the route add
923 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xFF) * 32)
925 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xFF) * 32)
929 # Add a multicast route that will forward into the BIER doamin
931 route_ing_232_1_1_1 = VppIpMRoute(
936 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
939 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
943 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
944 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
945 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
946 bier_imp=bi2.bi_index,
950 route_ing_232_1_1_1.add_vpp_config()
953 # inject a packet an IP. We expect it to be BIER and UDP encapped,
956 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
957 / IP(src="1.1.1.1", dst="232.1.1.1")
958 / UDP(sport=1234, dport=1234)
961 self.pg0.add_stream([p])
962 self.pg_enable_capture(self.pg_interfaces)
965 rx = self.pg1.get_capture(1)
968 # Encap Stack is, eth, IP, UDP, BIFT, BIER
970 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
971 self.assertEqual(rx[0][IP].dst, nh1)
972 self.assertEqual(rx[0][UDP].sport, 330)
973 self.assertEqual(rx[0][UDP].dport, 8138)
974 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
975 self.assertEqual(rx[0][BIFT].sd, 1)
976 self.assertEqual(rx[0][BIFT].set, 0)
977 self.assertEqual(rx[0][BIFT].ttl, 64)
978 self.assertEqual(rx[0][BIER].length, 2)
980 def test_bier_tail_o_udp(self):
981 """BIER Tail over UDP"""
983 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
984 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
987 # Add a BIER table for sub-domain 0, set 0, and BSL 256
989 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
990 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
996 bdt = VppBierDispTable(self, 8)
1000 # BIER route in table that's for-us
1002 bier_route_1 = VppBierRoute(
1010 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
1015 bier_route_1.add_vpp_config()
1018 # An entry in the disposition table
1020 bier_de_1 = VppBierDispEntry(
1024 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
1025 FibPathProto.FIB_PATH_NH_PROTO_BIER,
1030 bier_de_1.add_vpp_config()
1033 # A multicast route to forward post BIER disposition
1035 route_eg_232_1_1_1 = VppIpMRoute(
1040 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
1043 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1047 route_eg_232_1_1_1.add_vpp_config()
1048 route_eg_232_1_1_1.update_rpf_id(8192)
1051 # A packet with all bits set gets spat out to BP:1
1054 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1055 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1056 / UDP(sport=333, dport=8138)
1057 / BIFT(sd=1, set=0, bsl=2, ttl=255)
1059 length=BIERLength.BIER_LEN_256,
1060 BitString=scapy.compat.chb(255) * 32,
1063 / IP(src="1.1.1.1", dst="232.1.1.1")
1064 / UDP(sport=1234, dport=1234)
1068 rx = self.send_and_expect(self.pg0, [p], self.pg1)
1071 if __name__ == "__main__":
1072 unittest.main(testRunner=VppTestRunner)