5 from config import config
6 from framework import VppTestCase
7 from asfframework import VppTestRunner
8 from vpp_ip import DpoProto
9 from vpp_ip_route import (
21 from vpp_bier import (
30 from vpp_udp_encap import VppUdpEncap
31 from vpp_papi import VppEnum
34 from scapy.packet import Raw
35 from scapy.layers.l2 import Ether
36 from scapy.layers.inet import IP, UDP
37 from scapy.layers.inet6 import IPv6
38 from scapy.contrib.mpls import MPLS
39 from scapy.contrib.bier import BIER, BIERLength, BIFT
44 class TestBFIB(VppTestCase):
45 """BIER FIB Test Case"""
49 error = self.vapi.cli("test bier")
52 self.logger.critical(error)
53 self.assertNotIn("Failed", error)
56 class TestBier(VppTestCase):
60 super(TestBier, self).setUp()
62 # create 2 pg interfaces
63 self.create_pg_interfaces(range(3))
65 # create the default MPLS table
67 tbl = VppMplsTable(self, 0)
69 self.tables.append(tbl)
71 tbl = VppIpTable(self, 10)
73 self.tables.append(tbl)
75 # setup both interfaces
76 for i in self.pg_interfaces:
85 for i in self.pg_interfaces:
90 super(TestBier, self).tearDown()
92 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
96 # Add a BIER table for sub-domain 0, set 0, and BSL 256
98 bti = VppBierTableID(0, 0, hdr_len_id)
99 bt = VppBierTable(self, bti, 77)
103 # A packet with no bits set gets dropped
106 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
107 / MPLS(label=77, ttl=255)
108 / BIER(length=hdr_len_id)
109 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
110 / UDP(sport=1234, dport=1234)
115 self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String")
118 # Add a BIER route for each bit-position in the table via a different
119 # next-hop. Testing whether the BIER walk and replicate forwarding
120 # function works for all bit posisitons.
124 for i in range(1, max_bp + 1):
125 nh = "10.0.%d.%d" % (i / 255, i % 255)
134 self.pg1.sw_if_index,
135 labels=[VppMplsLabel(2000 + i)],
140 nh_routes[-1].add_vpp_config()
147 [VppRoutePath(nh, 0xFFFFFFFF, labels=[VppMplsLabel(100 + i)])],
150 bier_routes[-1].add_vpp_config()
153 # A packet with all bits set gets replicated once for each bit
155 pkt_sizes = [64, 1400]
157 for pkt_size in pkt_sizes:
159 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
160 / MPLS(label=77, ttl=255)
161 / BIER(length=hdr_len_id, BitString=scapy.compat.chb(255) * n_bytes)
162 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
163 / UDP(sport=1234, dport=1234)
164 / Raw(scapy.compat.chb(5) * pkt_size)
168 self.pg0.add_stream(pkts)
169 self.pg_enable_capture(self.pg_interfaces)
172 rx = self.pg1.get_capture(max_bp)
176 # The packets are not required to be sent in bit-position order
177 # when we setup the routes above we used the bit-position to
178 # construct the out-label. so use that here to determine the BP
181 bp = olabel.label - 2000
183 blabel = olabel[MPLS].payload
184 self.assertEqual(blabel.label, 100 + bp)
185 self.assertEqual(blabel.ttl, 254)
187 bier_hdr = blabel[MPLS].payload
189 self.assertEqual(bier_hdr.id, 5)
190 self.assertEqual(bier_hdr.version, 0)
191 self.assertEqual(bier_hdr.length, hdr_len_id)
192 self.assertEqual(bier_hdr.entropy, 0)
193 self.assertEqual(bier_hdr.OAM, 0)
194 self.assertEqual(bier_hdr.RSV, 0)
195 self.assertEqual(bier_hdr.DSCP, 0)
196 self.assertEqual(bier_hdr.Proto, 5)
198 # The bit-string should consist only of the BP given by i.
199 byte_array = [b"\0"] * (n_bytes)
200 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
201 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
202 byte_array[byte_pos] = byte_val
203 bitstring = b"".join(byte_array)
205 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
206 self.assertEqual(bitstring, bier_hdr.BitString)
209 # cleanup. not strictly necessary, but it's much quicker this way
210 # because the bier_fib_dump and ip_fib_dump will be empty when the
211 # auto-cleanup kicks in
213 for br in bier_routes:
214 br.remove_vpp_config()
215 for nhr in nh_routes:
216 nhr.remove_vpp_config()
218 @unittest.skipUnless(config.extended, "part of extended tests")
219 def test_bier_midpoint_1024(self):
220 """BIER midpoint BSL:1024"""
221 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
223 @unittest.skipUnless(config.extended, "part of extended tests")
224 def test_bier_midpoint_512(self):
225 """BIER midpoint BSL:512"""
226 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
228 @unittest.skipUnless(config.extended, "part of extended tests")
229 def test_bier_midpoint_256(self):
230 """BIER midpoint BSL:256"""
231 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
233 @unittest.skipUnless(config.extended, "part of extended tests")
234 def test_bier_midpoint_128(self):
235 """BIER midpoint BSL:128"""
236 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
238 def test_bier_midpoint_64(self):
239 """BIER midpoint BSL:64"""
240 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
242 def test_bier_load_balance(self):
243 """BIER load-balance"""
246 # Add a BIER table for sub-domain 0, set 0, and BSL 256
248 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
249 bt = VppBierTable(self, bti, 77)
253 # packets with varying entropy
256 for ii in range(257):
259 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
260 / MPLS(label=77, ttl=255)
262 length=BIERLength.BIER_LEN_64,
264 BitString=scapy.compat.chb(255) * 16,
266 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
267 / UDP(sport=1234, dport=1234)
276 {"ip": "10.0.0.1", "label": 201},
277 {"ip": "10.0.0.2", "label": 202},
278 {"ip": "10.0.0.3", "label": 203},
279 {"ip": "10.0.0.4", "label": 204},
290 self.pg1.sw_if_index,
291 labels=[VppMplsLabel(nh["label"])],
297 bier_route = VppBierRoute(
302 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
303 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
306 bier_route.add_vpp_config()
308 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
311 # we should have recieved a packet from each neighbor
314 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
317 # add the other paths
319 bier_route.update_paths(
321 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
322 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
323 VppRoutePath(nhs[2]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
324 VppRoutePath(nhs[3]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)]),
328 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
331 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
334 # remove first two paths
336 bier_route.remove_path(
337 VppRoutePath(nhs[0]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)])
339 bier_route.remove_path(
340 VppRoutePath(nhs[1]["ip"], 0xFFFFFFFF, labels=[VppMplsLabel(101)])
343 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
345 self.assertTrue(sum(p[MPLS].label == nh["label"] for p in rx))
348 # remove the last of the paths, deleteing the entry
350 bier_route.remove_all_paths()
352 self.send_and_assert_no_replies(self.pg0, pkts)
354 def test_bier_head(self):
357 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
358 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
361 # Add a BIER table for sub-domain 0, set 0, and BSL 256
363 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
364 bt = VppBierTable(self, bti, 77)
368 # 2 bit positions via two next hops
372 ip_route_1 = VppIpRoute(
379 self.pg1.sw_if_index,
380 labels=[VppMplsLabel(2001)],
384 ip_route_2 = VppIpRoute(
391 self.pg1.sw_if_index,
392 labels=[VppMplsLabel(2002)],
396 ip_route_1.add_vpp_config()
397 ip_route_2.add_vpp_config()
399 bier_route_1 = VppBierRoute(
400 self, bti, 1, [VppRoutePath(nh1, 0xFFFFFFFF, labels=[VppMplsLabel(101)])]
402 bier_route_2 = VppBierRoute(
403 self, bti, 2, [VppRoutePath(nh2, 0xFFFFFFFF, labels=[VppMplsLabel(102)])]
405 bier_route_1.add_vpp_config()
406 bier_route_2.add_vpp_config()
409 # An imposition object with both bit-positions set
411 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
415 # Add a multicast route that will forward into the BIER doamin
417 route_ing_232_1_1_1 = VppIpMRoute(
422 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
425 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
429 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
430 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
431 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
432 bier_imp=bi.bi_index,
436 route_ing_232_1_1_1.add_vpp_config()
439 # inject an IP packet. We expect it to be BIER encapped and
443 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
444 / IP(src="1.1.1.1", dst="232.1.1.1")
445 / UDP(sport=1234, dport=1234)
448 self.pg0.add_stream([p])
449 self.pg_enable_capture(self.pg_interfaces)
452 rx = self.pg1.get_capture(2)
455 # Encap Stack is; eth, MPLS, MPLS, BIER
457 igp_mpls = rx[0][MPLS]
458 self.assertEqual(igp_mpls.label, 2001)
459 self.assertEqual(igp_mpls.ttl, 64)
460 self.assertEqual(igp_mpls.s, 0)
461 bier_mpls = igp_mpls[MPLS].payload
462 self.assertEqual(bier_mpls.label, 101)
463 self.assertEqual(bier_mpls.ttl, 64)
464 self.assertEqual(bier_mpls.s, 1)
465 self.assertEqual(rx[0][BIER].length, 2)
467 igp_mpls = rx[1][MPLS]
468 self.assertEqual(igp_mpls.label, 2002)
469 self.assertEqual(igp_mpls.ttl, 64)
470 self.assertEqual(igp_mpls.s, 0)
471 bier_mpls = igp_mpls[MPLS].payload
472 self.assertEqual(bier_mpls.label, 102)
473 self.assertEqual(bier_mpls.ttl, 64)
474 self.assertEqual(bier_mpls.s, 1)
475 self.assertEqual(rx[0][BIER].length, 2)
477 def test_bier_tail(self):
480 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
481 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
484 # Add a BIER table for sub-domain 0, set 0, and BSL 256
486 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
487 bt = VppBierTable(self, bti, 77)
493 bdt = VppBierDispTable(self, 8)
497 # BIER route in table that's for-us
499 bier_route_1 = VppBierRoute(
507 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
512 bier_route_1.add_vpp_config()
515 # An entry in the disposition table
517 bier_de_1 = VppBierDispEntry(
521 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
522 FibPathProto.FIB_PATH_NH_PROTO_BIER,
527 bier_de_1.add_vpp_config()
530 # A multicast route to forward post BIER disposition
532 route_eg_232_1_1_1 = VppIpMRoute(
537 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
540 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
544 route_eg_232_1_1_1.add_vpp_config()
545 route_eg_232_1_1_1.update_rpf_id(8192)
548 # A packet with all bits set gets spat out to BP:1
551 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
552 / MPLS(label=77, ttl=255)
554 length=BIERLength.BIER_LEN_256,
555 BitString=scapy.compat.chb(255) * 32,
558 / IP(src="1.1.1.1", dst="232.1.1.1")
559 / UDP(sport=1234, dport=1234)
563 self.send_and_expect(self.pg0, [p], self.pg1)
566 # A packet that does not match the Disposition entry gets dropped
569 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
570 / MPLS(label=77, ttl=255)
572 length=BIERLength.BIER_LEN_256,
573 BitString=scapy.compat.chb(255) * 32,
576 / IP(src="1.1.1.1", dst="232.1.1.1")
577 / UDP(sport=1234, dport=1234)
580 self.send_and_assert_no_replies(
581 self.pg0, p * 2, "no matching disposition entry"
585 # Add the default route to the disposition table
587 bier_de_2 = VppBierDispEntry(
591 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
592 FibPathProto.FIB_PATH_NH_PROTO_BIER,
597 bier_de_2.add_vpp_config()
600 # now the previous packet is forwarded
602 self.send_and_expect(self.pg0, [p], self.pg1)
605 # A multicast route to forward post BIER disposition that needs
606 # a check against sending back into the BIER core
608 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
611 route_eg_232_1_1_2 = VppIpMRoute(
616 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
620 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
621 proto=DpoProto.DPO_PROTO_BIER,
622 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
623 bier_imp=bi.bi_index,
626 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
630 route_eg_232_1_1_2.add_vpp_config()
631 route_eg_232_1_1_2.update_rpf_id(8192)
634 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
635 / MPLS(label=77, ttl=255)
637 length=BIERLength.BIER_LEN_256,
638 BitString=scapy.compat.chb(255) * 32,
641 / IP(src="1.1.1.1", dst="232.1.1.2")
642 / UDP(sport=1234, dport=1234)
645 self.send_and_expect(self.pg0, [p], self.pg1)
647 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
648 """BIER end-to-end"""
650 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
651 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
654 # Add a BIER table for sub-domain 0, set 0, and BSL 256
656 bti = VppBierTableID(0, 0, hdr_len_id)
657 bt = VppBierTable(self, bti, 77)
660 lowest = [b"\0"] * (n_bytes)
661 lowest[-1] = scapy.compat.chb(1)
662 highest = [b"\0"] * (n_bytes)
663 highest[0] = scapy.compat.chb(128)
666 # Impostion Sets bit strings
668 bi_low = VppBierImp(self, bti, 333, lowest)
669 bi_low.add_vpp_config()
670 bi_high = VppBierImp(self, bti, 334, highest)
671 bi_high.add_vpp_config()
674 # Add a multicast route that will forward into the BIER doamin
676 route_ing_232_1_1_1 = VppIpMRoute(
681 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
684 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
688 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
689 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
690 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
691 bier_imp=bi_low.bi_index,
695 route_ing_232_1_1_1.add_vpp_config()
696 route_ing_232_1_1_2 = VppIpMRoute(
701 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
704 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
708 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
709 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
710 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
711 bier_imp=bi_high.bi_index,
715 route_ing_232_1_1_2.add_vpp_config()
718 # disposition table 8
720 bdt = VppBierDispTable(self, 8)
724 # BIER routes in table that are for-us, resolving through
727 bier_route_1 = VppBierRoute(
735 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
740 bier_route_1.add_vpp_config()
741 bier_route_max = VppBierRoute(
749 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
754 bier_route_max.add_vpp_config()
757 # An entry in the disposition table for sender 333
760 bier_de_1 = VppBierDispEntry(
764 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
765 FibPathProto.FIB_PATH_NH_PROTO_BIER,
770 bier_de_1.add_vpp_config()
771 bier_de_1 = VppBierDispEntry(
775 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
776 FibPathProto.FIB_PATH_NH_PROTO_BIER,
781 bier_de_1.add_vpp_config()
784 # Add a multicast routes that will forward the traffic
787 route_eg_232_1_1_1 = VppIpMRoute(
792 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
796 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
800 route_eg_232_1_1_1.add_vpp_config()
801 route_eg_232_1_1_1.update_rpf_id(8192)
802 route_eg_232_1_1_2 = VppIpMRoute(
807 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
811 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
815 route_eg_232_1_1_2.add_vpp_config()
816 route_eg_232_1_1_2.update_rpf_id(8193)
819 # inject a packet in VRF-0. We expect it to be BIER encapped,
820 # replicated, then hit the disposition and be forwarded
821 # out of VRF 10, i.e. on pg1
824 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
825 / IP(src="1.1.1.1", dst="232.1.1.1")
826 / UDP(sport=1234, dport=1234)
827 / Raw(scapy.compat.chb(5) * 32)
830 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
832 self.assertEqual(rx[0][IP].src, "1.1.1.1")
833 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
836 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
837 / IP(src="1.1.1.1", dst="232.1.1.2")
838 / UDP(sport=1234, dport=1234)
839 / Raw(scapy.compat.chb(5) * 512)
842 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
843 self.assertEqual(rx[0][IP].src, "1.1.1.1")
844 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
846 @unittest.skipUnless(config.extended, "part of extended tests")
847 def test_bier_e2e_1024(self):
848 """BIER end-to-end BSL:1024"""
849 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
851 @unittest.skipUnless(config.extended, "part of extended tests")
852 def test_bier_e2e_512(self):
853 """BIER end-to-end BSL:512"""
854 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
856 @unittest.skipUnless(config.extended, "part of extended tests")
857 def test_bier_e2e_256(self):
858 """BIER end-to-end BSL:256"""
859 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
861 @unittest.skipUnless(config.extended, "part of extended tests")
862 def test_bier_e2e_128(self):
863 """BIER end-to-end BSL:128"""
864 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
866 def test_bier_e2e_64(self):
867 """BIER end-to-end BSL:64"""
868 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
870 def test_bier_head_o_udp(self):
871 """BIER head over UDP"""
873 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
874 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
877 # Add a BIER table for sub-domain 1, set 0, and BSL 256
879 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
880 bt = VppBierTable(self, bti, 77)
884 # 1 bit positions via 1 next hops
887 ip_route = VppIpRoute(
894 self.pg1.sw_if_index,
895 labels=[VppMplsLabel(2001)],
899 ip_route.add_vpp_config()
901 udp_encap = VppUdpEncap(self, self.pg0.local_ip4, nh1, 330, 8138)
902 udp_encap.add_vpp_config()
904 bier_route = VppBierRoute(
912 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
913 next_hop_id=udp_encap.id,
917 bier_route.add_vpp_config()
920 # An 2 imposition objects with all bit-positions set
921 # only use the second, but creating 2 tests with a non-zero
922 # value index in the route add
924 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xFF) * 32)
926 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xFF) * 32)
930 # Add a multicast route that will forward into the BIER doamin
932 route_ing_232_1_1_1 = VppIpMRoute(
937 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
940 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
944 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
945 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
946 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
947 bier_imp=bi2.bi_index,
951 route_ing_232_1_1_1.add_vpp_config()
954 # inject a packet an IP. We expect it to be BIER and UDP encapped,
957 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
958 / IP(src="1.1.1.1", dst="232.1.1.1")
959 / UDP(sport=1234, dport=1234)
962 self.pg0.add_stream([p])
963 self.pg_enable_capture(self.pg_interfaces)
966 rx = self.pg1.get_capture(1)
969 # Encap Stack is, eth, IP, UDP, BIFT, BIER
971 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
972 self.assertEqual(rx[0][IP].dst, nh1)
973 self.assertEqual(rx[0][UDP].sport, 330)
974 self.assertEqual(rx[0][UDP].dport, 8138)
975 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
976 self.assertEqual(rx[0][BIFT].sd, 1)
977 self.assertEqual(rx[0][BIFT].set, 0)
978 self.assertEqual(rx[0][BIFT].ttl, 64)
979 self.assertEqual(rx[0][BIER].length, 2)
981 def test_bier_tail_o_udp(self):
982 """BIER Tail over UDP"""
984 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
985 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
988 # Add a BIER table for sub-domain 0, set 0, and BSL 256
990 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
991 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
997 bdt = VppBierDispTable(self, 8)
1001 # BIER route in table that's for-us
1003 bier_route_1 = VppBierRoute(
1011 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
1016 bier_route_1.add_vpp_config()
1019 # An entry in the disposition table
1021 bier_de_1 = VppBierDispEntry(
1025 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
1026 FibPathProto.FIB_PATH_NH_PROTO_BIER,
1031 bier_de_1.add_vpp_config()
1034 # A multicast route to forward post BIER disposition
1036 route_eg_232_1_1_1 = VppIpMRoute(
1041 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
1044 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1048 route_eg_232_1_1_1.add_vpp_config()
1049 route_eg_232_1_1_1.update_rpf_id(8192)
1052 # A packet with all bits set gets spat out to BP:1
1055 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1056 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1057 / UDP(sport=333, dport=8138)
1058 / BIFT(sd=1, set=0, bsl=2, ttl=255)
1060 length=BIERLength.BIER_LEN_256,
1061 BitString=scapy.compat.chb(255) * 32,
1064 / IP(src="1.1.1.1", dst="232.1.1.1")
1065 / UDP(sport=1234, dport=1234)
1069 rx = self.send_and_expect(self.pg0, [p], self.pg1)
1072 if __name__ == "__main__":
1073 unittest.main(testRunner=VppTestRunner)