5 from framework import VppTestCase, VppTestRunner, running_extended_tests
6 from vpp_ip import DpoProto
7 from vpp_ip_route import VppIpRoute, VppRoutePath, \
8 VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \
10 VppMplsLabel, FibPathProto, FibPathType
11 from vpp_bier import BIER_HDR_PAYLOAD, VppBierImp, VppBierDispEntry, \
12 VppBierDispTable, VppBierTable, VppBierTableID, VppBierRoute
13 from vpp_udp_encap import VppUdpEncap
14 from vpp_papi import VppEnum
17 from scapy.packet import Raw
18 from scapy.layers.l2 import Ether
19 from scapy.layers.inet import IP, UDP
20 from scapy.layers.inet6 import IPv6
21 from scapy.contrib.mpls import MPLS
22 from scapy.contrib.bier import BIER, BIERLength, BIFT
27 class TestBFIB(VppTestCase):
28 """ BIER FIB Test Case """
31 """ BFIB Unit Tests """
32 error = self.vapi.cli("test bier")
35 self.logger.critical(error)
36 self.assertNotIn("Failed", error)
39 class TestBier(VppTestCase):
40 """ BIER Test Case """
43 super(TestBier, self).setUp()
45 # create 2 pg interfaces
46 self.create_pg_interfaces(range(3))
48 # create the default MPLS table
50 tbl = VppMplsTable(self, 0)
52 self.tables.append(tbl)
54 tbl = VppIpTable(self, 10)
56 self.tables.append(tbl)
58 # setup both interfaces
59 for i in self.pg_interfaces:
68 for i in self.pg_interfaces:
73 super(TestBier, self).tearDown()
75 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
79 # Add a BIER table for sub-domain 0, set 0, and BSL 256
81 bti = VppBierTableID(0, 0, hdr_len_id)
82 bt = VppBierTable(self, bti, 77)
86 # A packet with no bits set gets dropped
88 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
89 MPLS(label=77, ttl=255) /
90 BIER(length=hdr_len_id) /
91 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
92 UDP(sport=1234, dport=1234) /
96 self.send_and_assert_no_replies(self.pg0, pkts,
100 # Add a BIER route for each bit-position in the table via a different
101 # next-hop. Testing whether the BIER walk and replicate forwarding
102 # function works for all bit posisitons.
106 for i in range(1, max_bp+1):
107 nh = "10.0.%d.%d" % (i / 255, i % 255)
109 VppIpRoute(self, nh, 32,
110 [VppRoutePath(self.pg1.remote_ip4,
111 self.pg1.sw_if_index,
112 labels=[VppMplsLabel(2000+i)])]))
113 nh_routes[-1].add_vpp_config()
116 VppBierRoute(self, bti, i,
117 [VppRoutePath(nh, 0xffffffff,
118 labels=[VppMplsLabel(100+i)])]))
119 bier_routes[-1].add_vpp_config()
122 # A packet with all bits set gets replicated once for each bit
124 pkt_sizes = [64, 1400]
126 for pkt_size in pkt_sizes:
127 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
128 MPLS(label=77, ttl=255) /
129 BIER(length=hdr_len_id,
130 BitString=scapy.compat.chb(255)*n_bytes) /
131 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
132 UDP(sport=1234, dport=1234) /
133 Raw(scapy.compat.chb(5) * pkt_size))
136 self.pg0.add_stream(pkts)
137 self.pg_enable_capture(self.pg_interfaces)
140 rx = self.pg1.get_capture(max_bp)
144 # The packets are not required to be sent in bit-position order
145 # when we setup the routes above we used the bit-position to
146 # construct the out-label. so use that here to determine the BP
149 bp = olabel.label - 2000
151 blabel = olabel[MPLS].payload
152 self.assertEqual(blabel.label, 100+bp)
153 self.assertEqual(blabel.ttl, 254)
155 bier_hdr = blabel[MPLS].payload
157 self.assertEqual(bier_hdr.id, 5)
158 self.assertEqual(bier_hdr.version, 0)
159 self.assertEqual(bier_hdr.length, hdr_len_id)
160 self.assertEqual(bier_hdr.entropy, 0)
161 self.assertEqual(bier_hdr.OAM, 0)
162 self.assertEqual(bier_hdr.RSV, 0)
163 self.assertEqual(bier_hdr.DSCP, 0)
164 self.assertEqual(bier_hdr.Proto, 5)
166 # The bit-string should consist only of the BP given by i.
167 byte_array = [b'\0'] * (n_bytes)
168 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
169 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
170 byte_array[byte_pos] = byte_val
171 bitstring = b''.join(byte_array)
173 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
174 self.assertEqual(bitstring, bier_hdr.BitString)
177 # cleanup. not strictly necessary, but it's much quicker this way
178 # because the bier_fib_dump and ip_fib_dump will be empty when the
179 # auto-cleanup kicks in
181 for br in bier_routes:
182 br.remove_vpp_config()
183 for nhr in nh_routes:
184 nhr.remove_vpp_config()
186 @unittest.skipUnless(running_extended_tests, "part of extended tests")
187 def test_bier_midpoint_1024(self):
188 """BIER midpoint BSL:1024"""
189 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
191 @unittest.skipUnless(running_extended_tests, "part of extended tests")
192 def test_bier_midpoint_512(self):
193 """BIER midpoint BSL:512"""
194 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
196 @unittest.skipUnless(running_extended_tests, "part of extended tests")
197 def test_bier_midpoint_256(self):
198 """BIER midpoint BSL:256"""
199 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
201 @unittest.skipUnless(running_extended_tests, "part of extended tests")
202 def test_bier_midpoint_128(self):
203 """BIER midpoint BSL:128"""
204 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
206 def test_bier_midpoint_64(self):
207 """BIER midpoint BSL:64"""
208 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
210 def test_bier_load_balance(self):
211 """BIER load-balance"""
214 # Add a BIER table for sub-domain 0, set 0, and BSL 256
216 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
217 bt = VppBierTable(self, bti, 77)
221 # packets with varying entropy
224 for ii in range(257):
225 pkts.append((Ether(dst=self.pg0.local_mac,
226 src=self.pg0.remote_mac) /
227 MPLS(label=77, ttl=255) /
228 BIER(length=BIERLength.BIER_LEN_64,
230 BitString=scapy.compat.chb(255)*16) /
231 IPv6(src=self.pg0.remote_ip6,
232 dst=self.pg0.remote_ip6) /
233 UDP(sport=1234, dport=1234) /
239 nhs = [{'ip': "10.0.0.1", 'label': 201},
240 {'ip': "10.0.0.2", 'label': 202},
241 {'ip': "10.0.0.3", 'label': 203},
242 {'ip': "10.0.0.4", 'label': 204}]
247 [VppRoutePath(self.pg1.remote_ip4,
248 self.pg1.sw_if_index,
249 labels=[VppMplsLabel(nh['label'])])])
252 bier_route = VppBierRoute(
254 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
255 labels=[VppMplsLabel(101)]),
256 VppRoutePath(nhs[1]['ip'], 0xffffffff,
257 labels=[VppMplsLabel(101)])])
258 bier_route.add_vpp_config()
260 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
263 # we should have recieved a packet from each neighbor
266 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
269 # add the other paths
271 bier_route.update_paths(
272 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
273 labels=[VppMplsLabel(101)]),
274 VppRoutePath(nhs[1]['ip'], 0xffffffff,
275 labels=[VppMplsLabel(101)]),
276 VppRoutePath(nhs[2]['ip'], 0xffffffff,
277 labels=[VppMplsLabel(101)]),
278 VppRoutePath(nhs[3]['ip'], 0xffffffff,
279 labels=[VppMplsLabel(101)])])
281 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
284 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
287 # remove first two paths
289 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
290 labels=[VppMplsLabel(101)]))
291 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
292 labels=[VppMplsLabel(101)]))
294 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
296 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
299 # remove the last of the paths, deleteing the entry
301 bier_route.remove_all_paths()
303 self.send_and_assert_no_replies(self.pg0, pkts)
305 def test_bier_head(self):
308 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
309 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
312 # Add a BIER table for sub-domain 0, set 0, and BSL 256
314 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
315 bt = VppBierTable(self, bti, 77)
319 # 2 bit positions via two next hops
323 ip_route_1 = VppIpRoute(self, nh1, 32,
324 [VppRoutePath(self.pg1.remote_ip4,
325 self.pg1.sw_if_index,
326 labels=[VppMplsLabel(2001)])])
327 ip_route_2 = VppIpRoute(self, nh2, 32,
328 [VppRoutePath(self.pg1.remote_ip4,
329 self.pg1.sw_if_index,
330 labels=[VppMplsLabel(2002)])])
331 ip_route_1.add_vpp_config()
332 ip_route_2.add_vpp_config()
334 bier_route_1 = VppBierRoute(self, bti, 1,
335 [VppRoutePath(nh1, 0xffffffff,
336 labels=[VppMplsLabel(101)])])
337 bier_route_2 = VppBierRoute(self, bti, 2,
338 [VppRoutePath(nh2, 0xffffffff,
339 labels=[VppMplsLabel(102)])])
340 bier_route_1.add_vpp_config()
341 bier_route_2.add_vpp_config()
344 # An imposition object with both bit-positions set
346 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
350 # Add a multicast route that will forward into the BIER doamin
352 route_ing_232_1_1_1 = VppIpMRoute(
356 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
357 paths=[VppMRoutePath(self.pg0.sw_if_index,
358 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
359 VppMRoutePath(0xffffffff,
360 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
361 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
362 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
363 bier_imp=bi.bi_index)])
364 route_ing_232_1_1_1.add_vpp_config()
367 # inject an IP packet. We expect it to be BIER encapped and
370 p = (Ether(dst=self.pg0.local_mac,
371 src=self.pg0.remote_mac) /
372 IP(src="1.1.1.1", dst="232.1.1.1") /
373 UDP(sport=1234, dport=1234))
375 self.pg0.add_stream([p])
376 self.pg_enable_capture(self.pg_interfaces)
379 rx = self.pg1.get_capture(2)
382 # Encap Stack is; eth, MPLS, MPLS, BIER
384 igp_mpls = rx[0][MPLS]
385 self.assertEqual(igp_mpls.label, 2001)
386 self.assertEqual(igp_mpls.ttl, 64)
387 self.assertEqual(igp_mpls.s, 0)
388 bier_mpls = igp_mpls[MPLS].payload
389 self.assertEqual(bier_mpls.label, 101)
390 self.assertEqual(bier_mpls.ttl, 64)
391 self.assertEqual(bier_mpls.s, 1)
392 self.assertEqual(rx[0][BIER].length, 2)
394 igp_mpls = rx[1][MPLS]
395 self.assertEqual(igp_mpls.label, 2002)
396 self.assertEqual(igp_mpls.ttl, 64)
397 self.assertEqual(igp_mpls.s, 0)
398 bier_mpls = igp_mpls[MPLS].payload
399 self.assertEqual(bier_mpls.label, 102)
400 self.assertEqual(bier_mpls.ttl, 64)
401 self.assertEqual(bier_mpls.s, 1)
402 self.assertEqual(rx[0][BIER].length, 2)
404 def test_bier_tail(self):
407 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
408 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
411 # Add a BIER table for sub-domain 0, set 0, and BSL 256
413 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
414 bt = VppBierTable(self, bti, 77)
420 bdt = VppBierDispTable(self, 8)
424 # BIER route in table that's for-us
426 bier_route_1 = VppBierRoute(
428 [VppRoutePath("0.0.0.0",
430 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
432 bier_route_1.add_vpp_config()
435 # An entry in the disposition table
437 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
438 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
439 FibPathProto.FIB_PATH_NH_PROTO_BIER,
440 "0.0.0.0", 0, rpf_id=8192)
441 bier_de_1.add_vpp_config()
444 # A multicast route to forward post BIER disposition
446 route_eg_232_1_1_1 = VppIpMRoute(
450 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
451 paths=[VppMRoutePath(self.pg1.sw_if_index,
452 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
453 route_eg_232_1_1_1.add_vpp_config()
454 route_eg_232_1_1_1.update_rpf_id(8192)
457 # A packet with all bits set gets spat out to BP:1
459 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
460 MPLS(label=77, ttl=255) /
461 BIER(length=BIERLength.BIER_LEN_256,
462 BitString=scapy.compat.chb(255)*32,
464 IP(src="1.1.1.1", dst="232.1.1.1") /
465 UDP(sport=1234, dport=1234) /
468 self.send_and_expect(self.pg0, [p], self.pg1)
471 # A packet that does not match the Disposition entry gets dropped
473 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
474 MPLS(label=77, ttl=255) /
475 BIER(length=BIERLength.BIER_LEN_256,
476 BitString=scapy.compat.chb(255)*32,
478 IP(src="1.1.1.1", dst="232.1.1.1") /
479 UDP(sport=1234, dport=1234) /
481 self.send_and_assert_no_replies(self.pg0, p*2,
482 "no matching disposition entry")
485 # Add the default route to the disposition table
487 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
488 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
489 FibPathProto.FIB_PATH_NH_PROTO_BIER,
490 "0.0.0.0", 0, rpf_id=8192)
491 bier_de_2.add_vpp_config()
494 # now the previous packet is forwarded
496 self.send_and_expect(self.pg0, [p], self.pg1)
499 # A multicast route to forward post BIER disposition that needs
500 # a check against sending back into the BIER core
502 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
505 route_eg_232_1_1_2 = VppIpMRoute(
509 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
510 paths=[VppMRoutePath(0xffffffff,
511 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
512 proto=DpoProto.DPO_PROTO_BIER,
513 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
514 bier_imp=bi.bi_index),
515 VppMRoutePath(self.pg1.sw_if_index,
516 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
517 route_eg_232_1_1_2.add_vpp_config()
518 route_eg_232_1_1_2.update_rpf_id(8192)
520 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
521 MPLS(label=77, ttl=255) /
522 BIER(length=BIERLength.BIER_LEN_256,
523 BitString=scapy.compat.chb(255)*32,
525 IP(src="1.1.1.1", dst="232.1.1.2") /
526 UDP(sport=1234, dport=1234) /
528 self.send_and_expect(self.pg0, [p], self.pg1)
530 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
531 """ BIER end-to-end"""
533 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
534 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
537 # Add a BIER table for sub-domain 0, set 0, and BSL 256
539 bti = VppBierTableID(0, 0, hdr_len_id)
540 bt = VppBierTable(self, bti, 77)
543 lowest = [b'\0'] * (n_bytes)
544 lowest[-1] = scapy.compat.chb(1)
545 highest = [b'\0'] * (n_bytes)
546 highest[0] = scapy.compat.chb(128)
549 # Impostion Sets bit strings
551 bi_low = VppBierImp(self, bti, 333, lowest)
552 bi_low.add_vpp_config()
553 bi_high = VppBierImp(self, bti, 334, highest)
554 bi_high.add_vpp_config()
557 # Add a multicast route that will forward into the BIER doamin
559 route_ing_232_1_1_1 = VppIpMRoute(
563 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
564 paths=[VppMRoutePath(self.pg0.sw_if_index,
565 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
566 VppMRoutePath(0xffffffff,
567 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
568 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
569 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
570 bier_imp=bi_low.bi_index)])
571 route_ing_232_1_1_1.add_vpp_config()
572 route_ing_232_1_1_2 = VppIpMRoute(
576 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
577 paths=[VppMRoutePath(self.pg0.sw_if_index,
578 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
579 VppMRoutePath(0xffffffff,
580 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
581 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
582 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
583 bier_imp=bi_high.bi_index)])
584 route_ing_232_1_1_2.add_vpp_config()
587 # disposition table 8
589 bdt = VppBierDispTable(self, 8)
593 # BIER routes in table that are for-us, resolving through
596 bier_route_1 = VppBierRoute(
598 [VppRoutePath("0.0.0.0",
600 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
602 bier_route_1.add_vpp_config()
603 bier_route_max = VppBierRoute(
605 [VppRoutePath("0.0.0.0",
607 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
609 bier_route_max.add_vpp_config()
612 # An entry in the disposition table for sender 333
615 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
616 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
617 FibPathProto.FIB_PATH_NH_PROTO_BIER,
618 "0.0.0.0", 10, rpf_id=8192)
619 bier_de_1.add_vpp_config()
620 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
621 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
622 FibPathProto.FIB_PATH_NH_PROTO_BIER,
623 "0.0.0.0", 10, rpf_id=8193)
624 bier_de_1.add_vpp_config()
627 # Add a multicast routes that will forward the traffic
630 route_eg_232_1_1_1 = VppIpMRoute(
634 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
636 paths=[VppMRoutePath(self.pg1.sw_if_index,
637 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
638 route_eg_232_1_1_1.add_vpp_config()
639 route_eg_232_1_1_1.update_rpf_id(8192)
640 route_eg_232_1_1_2 = VppIpMRoute(
644 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
646 paths=[VppMRoutePath(self.pg1.sw_if_index,
647 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
648 route_eg_232_1_1_2.add_vpp_config()
649 route_eg_232_1_1_2.update_rpf_id(8193)
652 # inject a packet in VRF-0. We expect it to be BIER encapped,
653 # replicated, then hit the disposition and be forwarded
654 # out of VRF 10, i.e. on pg1
656 p = (Ether(dst=self.pg0.local_mac,
657 src=self.pg0.remote_mac) /
658 IP(src="1.1.1.1", dst="232.1.1.1") /
659 UDP(sport=1234, dport=1234) /
660 Raw(scapy.compat.chb(5) * 32))
662 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
664 self.assertEqual(rx[0][IP].src, "1.1.1.1")
665 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
667 p = (Ether(dst=self.pg0.local_mac,
668 src=self.pg0.remote_mac) /
669 IP(src="1.1.1.1", dst="232.1.1.2") /
670 UDP(sport=1234, dport=1234) /
671 Raw(scapy.compat.chb(5) * 512))
673 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
674 self.assertEqual(rx[0][IP].src, "1.1.1.1")
675 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
677 @unittest.skipUnless(running_extended_tests, "part of extended tests")
678 def test_bier_e2e_1024(self):
679 """ BIER end-to-end BSL:1024"""
680 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
682 @unittest.skipUnless(running_extended_tests, "part of extended tests")
683 def test_bier_e2e_512(self):
684 """ BIER end-to-end BSL:512"""
685 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
687 @unittest.skipUnless(running_extended_tests, "part of extended tests")
688 def test_bier_e2e_256(self):
689 """ BIER end-to-end BSL:256"""
690 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
692 @unittest.skipUnless(running_extended_tests, "part of extended tests")
693 def test_bier_e2e_128(self):
694 """ BIER end-to-end BSL:128"""
695 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
697 def test_bier_e2e_64(self):
698 """ BIER end-to-end BSL:64"""
699 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
701 def test_bier_head_o_udp(self):
702 """BIER head over UDP"""
704 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
705 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
708 # Add a BIER table for sub-domain 1, set 0, and BSL 256
710 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
711 bt = VppBierTable(self, bti, 77)
715 # 1 bit positions via 1 next hops
718 ip_route = VppIpRoute(self, nh1, 32,
719 [VppRoutePath(self.pg1.remote_ip4,
720 self.pg1.sw_if_index,
721 labels=[VppMplsLabel(2001)])])
722 ip_route.add_vpp_config()
724 udp_encap = VppUdpEncap(self,
728 udp_encap.add_vpp_config()
730 bier_route = VppBierRoute(
732 [VppRoutePath("0.0.0.0",
734 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
735 next_hop_id=udp_encap.id)])
736 bier_route.add_vpp_config()
739 # An 2 imposition objects with all bit-positions set
740 # only use the second, but creating 2 tests with a non-zero
741 # value index in the route add
743 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
745 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
749 # Add a multicast route that will forward into the BIER doamin
751 route_ing_232_1_1_1 = VppIpMRoute(
755 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
756 paths=[VppMRoutePath(self.pg0.sw_if_index,
757 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
758 VppMRoutePath(0xffffffff,
759 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
760 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
761 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
762 bier_imp=bi2.bi_index)])
763 route_ing_232_1_1_1.add_vpp_config()
766 # inject a packet an IP. We expect it to be BIER and UDP encapped,
768 p = (Ether(dst=self.pg0.local_mac,
769 src=self.pg0.remote_mac) /
770 IP(src="1.1.1.1", dst="232.1.1.1") /
771 UDP(sport=1234, dport=1234))
773 self.pg0.add_stream([p])
774 self.pg_enable_capture(self.pg_interfaces)
777 rx = self.pg1.get_capture(1)
780 # Encap Stack is, eth, IP, UDP, BIFT, BIER
782 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
783 self.assertEqual(rx[0][IP].dst, nh1)
784 self.assertEqual(rx[0][UDP].sport, 330)
785 self.assertEqual(rx[0][UDP].dport, 8138)
786 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
787 self.assertEqual(rx[0][BIFT].sd, 1)
788 self.assertEqual(rx[0][BIFT].set, 0)
789 self.assertEqual(rx[0][BIFT].ttl, 64)
790 self.assertEqual(rx[0][BIER].length, 2)
792 def test_bier_tail_o_udp(self):
793 """BIER Tail over UDP"""
795 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
796 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
799 # Add a BIER table for sub-domain 0, set 0, and BSL 256
801 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
802 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
808 bdt = VppBierDispTable(self, 8)
812 # BIER route in table that's for-us
814 bier_route_1 = VppBierRoute(
816 [VppRoutePath("0.0.0.0",
818 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
820 bier_route_1.add_vpp_config()
823 # An entry in the disposition table
825 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
826 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
827 FibPathProto.FIB_PATH_NH_PROTO_BIER,
828 "0.0.0.0", 0, rpf_id=8192)
829 bier_de_1.add_vpp_config()
832 # A multicast route to forward post BIER disposition
834 route_eg_232_1_1_1 = VppIpMRoute(
838 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
839 paths=[VppMRoutePath(self.pg1.sw_if_index,
840 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
841 route_eg_232_1_1_1.add_vpp_config()
842 route_eg_232_1_1_1.update_rpf_id(8192)
845 # A packet with all bits set gets spat out to BP:1
847 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
848 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
849 UDP(sport=333, dport=8138) /
850 BIFT(sd=1, set=0, bsl=2, ttl=255) /
851 BIER(length=BIERLength.BIER_LEN_256,
852 BitString=scapy.compat.chb(255)*32,
854 IP(src="1.1.1.1", dst="232.1.1.1") /
855 UDP(sport=1234, dport=1234) /
858 rx = self.send_and_expect(self.pg0, [p], self.pg1)
861 if __name__ == '__main__':
862 unittest.main(testRunner=VppTestRunner)