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, \
9 MRouteEntryFlags, MRouteItfFlags, MPLS_LABEL_INVALID, \
11 from vpp_bier import BIER_HDR_PAYLOAD, VppBierImp, VppBierDispEntry, \
12 VppBierDispTable, VppBierTable, VppBierTableID, VppBierRoute
13 from vpp_udp_encap import VppUdpEncap
16 from scapy.packet import Raw
17 from scapy.layers.l2 import Ether
18 from scapy.layers.inet import IP, UDP
19 from scapy.layers.inet6 import IPv6
20 from scapy.contrib.mpls import MPLS
21 from scapy.contrib.bier import BIER, BIERLength, BIFT
24 class TestBFIB(VppTestCase):
25 """ BIER FIB Test Case """
28 """ BFIB Unit Tests """
29 error = self.vapi.cli("test bier")
32 self.logger.critical(error)
33 self.assertNotIn("Failed", error)
36 class TestBier(VppTestCase):
37 """ BIER Test Case """
40 super(TestBier, self).setUp()
42 # create 2 pg interfaces
43 self.create_pg_interfaces(range(3))
45 # create the default MPLS table
47 tbl = VppMplsTable(self, 0)
49 self.tables.append(tbl)
51 tbl = VppIpTable(self, 10)
53 self.tables.append(tbl)
55 # setup both interfaces
56 for i in self.pg_interfaces:
65 for i in self.pg_interfaces:
70 super(TestBier, self).tearDown()
72 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
76 # Add a BIER table for sub-domain 0, set 0, and BSL 256
78 bti = VppBierTableID(0, 0, hdr_len_id)
79 bt = VppBierTable(self, bti, 77)
83 # A packet with no bits set gets dropped
85 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
86 MPLS(label=77, ttl=255) /
87 BIER(length=hdr_len_id) /
88 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
89 UDP(sport=1234, dport=1234) /
93 self.send_and_assert_no_replies(self.pg0, pkts,
97 # Add a BIER route for each bit-position in the table via a different
98 # next-hop. Testing whether the BIER walk and replicate forwarding
99 # function works for all bit posisitons.
103 for i in range(1, max_bp+1):
104 nh = "10.0.%d.%d" % (i / 255, i % 255)
106 VppIpRoute(self, nh, 32,
107 [VppRoutePath(self.pg1.remote_ip4,
108 self.pg1.sw_if_index,
109 labels=[VppMplsLabel(2000+i)])]))
110 nh_routes[-1].add_vpp_config()
113 VppBierRoute(self, bti, i,
114 [VppRoutePath(nh, 0xffffffff,
115 labels=[VppMplsLabel(100+i)])]))
116 bier_routes[-1].add_vpp_config()
119 # A packet with all bits set gets replicated once for each bit
121 pkt_sizes = [64, 1400]
123 for pkt_size in pkt_sizes:
124 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
125 MPLS(label=77, ttl=255) /
126 BIER(length=hdr_len_id,
127 BitString=scapy.compat.chb(255)*n_bytes) /
128 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
129 UDP(sport=1234, dport=1234) /
130 Raw(scapy.compat.chb(5) * pkt_size))
133 self.pg0.add_stream(pkts)
134 self.pg_enable_capture(self.pg_interfaces)
137 rx = self.pg1.get_capture(max_bp)
141 # The packets are not required to be sent in bit-position order
142 # when we setup the routes above we used the bit-position to
143 # construct the out-label. so use that here to determine the BP
146 bp = olabel.label - 2000
148 blabel = olabel[MPLS].payload
149 self.assertEqual(blabel.label, 100+bp)
150 self.assertEqual(blabel.ttl, 254)
152 bier_hdr = blabel[MPLS].payload
154 self.assertEqual(bier_hdr.id, 5)
155 self.assertEqual(bier_hdr.version, 0)
156 self.assertEqual(bier_hdr.length, hdr_len_id)
157 self.assertEqual(bier_hdr.entropy, 0)
158 self.assertEqual(bier_hdr.OAM, 0)
159 self.assertEqual(bier_hdr.RSV, 0)
160 self.assertEqual(bier_hdr.DSCP, 0)
161 self.assertEqual(bier_hdr.Proto, 5)
163 # The bit-string should consist only of the BP given by i.
164 byte_array = [b'\0'] * (n_bytes)
165 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
166 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
167 byte_array[byte_pos] = byte_val
168 bitstring = ''.join([scapy.compat.chb(x) for x in byte_array])
170 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
171 self.assertEqual(bitstring, bier_hdr.BitString)
174 # cleanup. not strictly necessary, but it's much quicker this way
175 # because the bier_fib_dump and ip_fib_dump will be empty when the
176 # auto-cleanup kicks in
178 for br in bier_routes:
179 br.remove_vpp_config()
180 for nhr in nh_routes:
181 nhr.remove_vpp_config()
183 @unittest.skipUnless(running_extended_tests, "part of extended tests")
184 def test_bier_midpoint_1024(self):
185 """BIER midpoint BSL:1024"""
186 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
188 @unittest.skipUnless(running_extended_tests, "part of extended tests")
189 def test_bier_midpoint_512(self):
190 """BIER midpoint BSL:512"""
191 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
193 @unittest.skipUnless(running_extended_tests, "part of extended tests")
194 def test_bier_midpoint_256(self):
195 """BIER midpoint BSL:256"""
196 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
198 @unittest.skipUnless(running_extended_tests, "part of extended tests")
199 def test_bier_midpoint_128(self):
200 """BIER midpoint BSL:128"""
201 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
203 def test_bier_midpoint_64(self):
204 """BIER midpoint BSL:64"""
205 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
207 def test_bier_load_balance(self):
208 """BIER load-balance"""
211 # Add a BIER table for sub-domain 0, set 0, and BSL 256
213 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
214 bt = VppBierTable(self, bti, 77)
218 # packets with varying entropy
221 for ii in range(257):
222 pkts.append((Ether(dst=self.pg0.local_mac,
223 src=self.pg0.remote_mac) /
224 MPLS(label=77, ttl=255) /
225 BIER(length=BIERLength.BIER_LEN_64,
227 BitString=scapy.compat.chb(255)*16) /
228 IPv6(src=self.pg0.remote_ip6,
229 dst=self.pg0.remote_ip6) /
230 UDP(sport=1234, dport=1234) /
236 nhs = [{'ip': "10.0.0.1", 'label': 201},
237 {'ip': "10.0.0.2", 'label': 202},
238 {'ip': "10.0.0.3", 'label': 203},
239 {'ip': "10.0.0.4", 'label': 204}]
244 [VppRoutePath(self.pg1.remote_ip4,
245 self.pg1.sw_if_index,
246 labels=[VppMplsLabel(nh['label'])])])
249 bier_route = VppBierRoute(
251 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
252 labels=[VppMplsLabel(101)]),
253 VppRoutePath(nhs[1]['ip'], 0xffffffff,
254 labels=[VppMplsLabel(101)])])
255 bier_route.add_vpp_config()
257 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
260 # we should have recieved a packet from each neighbor
263 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
266 # add the other paths
268 bier_route.update_paths(
269 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
270 labels=[VppMplsLabel(101)]),
271 VppRoutePath(nhs[1]['ip'], 0xffffffff,
272 labels=[VppMplsLabel(101)]),
273 VppRoutePath(nhs[2]['ip'], 0xffffffff,
274 labels=[VppMplsLabel(101)]),
275 VppRoutePath(nhs[3]['ip'], 0xffffffff,
276 labels=[VppMplsLabel(101)])])
278 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
280 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
283 # remove first two paths
285 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
286 labels=[VppMplsLabel(101)]))
287 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
288 labels=[VppMplsLabel(101)]))
290 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
292 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
295 # remove the last of the paths, deleteing the entry
297 bier_route.remove_all_paths()
299 self.send_and_assert_no_replies(self.pg0, pkts)
301 def test_bier_head(self):
305 # Add a BIER table for sub-domain 0, set 0, and BSL 256
307 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
308 bt = VppBierTable(self, bti, 77)
312 # 2 bit positions via two next hops
316 ip_route_1 = VppIpRoute(self, nh1, 32,
317 [VppRoutePath(self.pg1.remote_ip4,
318 self.pg1.sw_if_index,
319 labels=[VppMplsLabel(2001)])])
320 ip_route_2 = VppIpRoute(self, nh2, 32,
321 [VppRoutePath(self.pg1.remote_ip4,
322 self.pg1.sw_if_index,
323 labels=[VppMplsLabel(2002)])])
324 ip_route_1.add_vpp_config()
325 ip_route_2.add_vpp_config()
327 bier_route_1 = VppBierRoute(self, bti, 1,
328 [VppRoutePath(nh1, 0xffffffff,
329 labels=[VppMplsLabel(101)])])
330 bier_route_2 = VppBierRoute(self, bti, 2,
331 [VppRoutePath(nh2, 0xffffffff,
332 labels=[VppMplsLabel(102)])])
333 bier_route_1.add_vpp_config()
334 bier_route_2.add_vpp_config()
337 # An imposition object with both bit-positions set
339 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
343 # Add a multicast route that will forward into the BIER doamin
345 route_ing_232_1_1_1 = VppIpMRoute(
349 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
350 paths=[VppMRoutePath(self.pg0.sw_if_index,
351 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
352 VppMRoutePath(0xffffffff,
353 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
354 proto=DpoProto.DPO_PROTO_BIER,
355 bier_imp=bi.bi_index)])
356 route_ing_232_1_1_1.add_vpp_config()
359 # inject an IP packet. We expect it to be BIER encapped and
362 p = (Ether(dst=self.pg0.local_mac,
363 src=self.pg0.remote_mac) /
364 IP(src="1.1.1.1", dst="232.1.1.1") /
365 UDP(sport=1234, dport=1234))
367 self.pg0.add_stream([p])
368 self.pg_enable_capture(self.pg_interfaces)
371 rx = self.pg1.get_capture(2)
374 # Encap Stack is; eth, MPLS, MPLS, BIER
376 igp_mpls = rx[0][MPLS]
377 self.assertEqual(igp_mpls.label, 2001)
378 self.assertEqual(igp_mpls.ttl, 64)
379 self.assertEqual(igp_mpls.s, 0)
380 bier_mpls = igp_mpls[MPLS].payload
381 self.assertEqual(bier_mpls.label, 101)
382 self.assertEqual(bier_mpls.ttl, 64)
383 self.assertEqual(bier_mpls.s, 1)
384 self.assertEqual(rx[0][BIER].length, 2)
386 igp_mpls = rx[1][MPLS]
387 self.assertEqual(igp_mpls.label, 2002)
388 self.assertEqual(igp_mpls.ttl, 64)
389 self.assertEqual(igp_mpls.s, 0)
390 bier_mpls = igp_mpls[MPLS].payload
391 self.assertEqual(bier_mpls.label, 102)
392 self.assertEqual(bier_mpls.ttl, 64)
393 self.assertEqual(bier_mpls.s, 1)
394 self.assertEqual(rx[0][BIER].length, 2)
396 def test_bier_tail(self):
400 # Add a BIER table for sub-domain 0, set 0, and BSL 256
402 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
403 bt = VppBierTable(self, bti, 77)
409 bdt = VppBierDispTable(self, 8)
413 # BIER route in table that's for-us
415 bier_route_1 = VppBierRoute(
417 [VppRoutePath("0.0.0.0",
419 proto=DpoProto.DPO_PROTO_BIER,
421 bier_route_1.add_vpp_config()
424 # An entry in the disposition table
426 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
427 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
428 DpoProto.DPO_PROTO_BIER,
429 "0.0.0.0", 0, rpf_id=8192)
430 bier_de_1.add_vpp_config()
433 # A multicast route to forward post BIER disposition
435 route_eg_232_1_1_1 = VppIpMRoute(
439 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
440 paths=[VppMRoutePath(self.pg1.sw_if_index,
441 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
442 route_eg_232_1_1_1.add_vpp_config()
443 route_eg_232_1_1_1.update_rpf_id(8192)
446 # A packet with all bits set gets spat out to BP:1
448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
449 MPLS(label=77, ttl=255) /
450 BIER(length=BIERLength.BIER_LEN_256,
451 BitString=scapy.compat.chb(255)*32,
453 IP(src="1.1.1.1", dst="232.1.1.1") /
454 UDP(sport=1234, dport=1234) /
457 self.send_and_expect(self.pg0, [p], self.pg1)
460 # A packet that does not match the Disposition entry gets dropped
462 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
463 MPLS(label=77, ttl=255) /
464 BIER(length=BIERLength.BIER_LEN_256,
465 BitString=scapy.compat.chb(255)*32,
467 IP(src="1.1.1.1", dst="232.1.1.1") /
468 UDP(sport=1234, dport=1234) /
470 self.send_and_assert_no_replies(self.pg0, p*2,
471 "no matching disposition entry")
474 # Add the default route to the disposition table
476 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
477 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
478 DpoProto.DPO_PROTO_BIER,
479 "0.0.0.0", 0, rpf_id=8192)
480 bier_de_2.add_vpp_config()
483 # now the previous packet is forwarded
485 self.send_and_expect(self.pg0, [p], self.pg1)
488 # A multicast route to forward post BIER disposition that needs
489 # a check against sending back into the BIER core
491 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
494 route_eg_232_1_1_2 = VppIpMRoute(
498 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
499 paths=[VppMRoutePath(0xffffffff,
500 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
501 proto=DpoProto.DPO_PROTO_BIER,
502 bier_imp=bi.bi_index),
503 VppMRoutePath(self.pg1.sw_if_index,
504 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
505 route_eg_232_1_1_2.add_vpp_config()
506 route_eg_232_1_1_2.update_rpf_id(8192)
508 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
509 MPLS(label=77, ttl=255) /
510 BIER(length=BIERLength.BIER_LEN_256,
511 BitString=scapy.compat.chb(255)*32,
513 IP(src="1.1.1.1", dst="232.1.1.2") /
514 UDP(sport=1234, dport=1234) /
516 self.send_and_expect(self.pg0, [p], self.pg1)
518 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
519 """ BIER end-to-end"""
522 # Add a BIER table for sub-domain 0, set 0, and BSL 256
524 bti = VppBierTableID(0, 0, hdr_len_id)
525 bt = VppBierTable(self, bti, 77)
528 lowest = [b'\0'] * (n_bytes)
529 lowest[-1] = scapy.compat.chb(1)
530 highest = [b'\0'] * (n_bytes)
531 highest[0] = scapy.compat.chb(128)
534 # Impostion Sets bit strings
536 bi_low = VppBierImp(self, bti, 333, lowest)
537 bi_low.add_vpp_config()
538 bi_high = VppBierImp(self, bti, 334, highest)
539 bi_high.add_vpp_config()
542 # Add a multicast route that will forward into the BIER doamin
544 route_ing_232_1_1_1 = VppIpMRoute(
548 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
549 paths=[VppMRoutePath(self.pg0.sw_if_index,
550 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
551 VppMRoutePath(0xffffffff,
552 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
553 proto=DpoProto.DPO_PROTO_BIER,
554 bier_imp=bi_low.bi_index)])
555 route_ing_232_1_1_1.add_vpp_config()
556 route_ing_232_1_1_2 = VppIpMRoute(
560 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
561 paths=[VppMRoutePath(self.pg0.sw_if_index,
562 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
563 VppMRoutePath(0xffffffff,
564 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
565 proto=DpoProto.DPO_PROTO_BIER,
566 bier_imp=bi_high.bi_index)])
567 route_ing_232_1_1_2.add_vpp_config()
570 # disposition table 8
572 bdt = VppBierDispTable(self, 8)
576 # BIER routes in table that are for-us, resolving through
579 bier_route_1 = VppBierRoute(
581 [VppRoutePath("0.0.0.0",
583 proto=DpoProto.DPO_PROTO_BIER,
585 bier_route_1.add_vpp_config()
586 bier_route_max = VppBierRoute(
588 [VppRoutePath("0.0.0.0",
591 proto=DpoProto.DPO_PROTO_BIER)])
592 bier_route_max.add_vpp_config()
595 # An entry in the disposition table for sender 333
598 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
599 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
600 DpoProto.DPO_PROTO_BIER,
601 "0.0.0.0", 10, rpf_id=8192)
602 bier_de_1.add_vpp_config()
603 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
604 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
605 DpoProto.DPO_PROTO_BIER,
606 "0.0.0.0", 10, rpf_id=8193)
607 bier_de_1.add_vpp_config()
610 # Add a multicast routes that will forward the traffic
613 route_eg_232_1_1_1 = VppIpMRoute(
617 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
619 paths=[VppMRoutePath(self.pg1.sw_if_index,
620 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
621 route_eg_232_1_1_1.add_vpp_config()
622 route_eg_232_1_1_1.update_rpf_id(8192)
623 route_eg_232_1_1_2 = VppIpMRoute(
627 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
629 paths=[VppMRoutePath(self.pg1.sw_if_index,
630 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
631 route_eg_232_1_1_2.add_vpp_config()
632 route_eg_232_1_1_2.update_rpf_id(8193)
635 # inject a packet in VRF-0. We expect it to be BIER encapped,
636 # replicated, then hit the disposition and be forwarded
637 # out of VRF 10, i.e. on pg1
639 p = (Ether(dst=self.pg0.local_mac,
640 src=self.pg0.remote_mac) /
641 IP(src="1.1.1.1", dst="232.1.1.1") /
642 UDP(sport=1234, dport=1234) /
643 Raw(scapy.compat.chb(5) * 32))
645 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
647 self.assertEqual(rx[0][IP].src, "1.1.1.1")
648 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
650 p = (Ether(dst=self.pg0.local_mac,
651 src=self.pg0.remote_mac) /
652 IP(src="1.1.1.1", dst="232.1.1.2") /
653 UDP(sport=1234, dport=1234) /
654 Raw(scapy.compat.chb(5) * 512))
656 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
657 self.assertEqual(rx[0][IP].src, "1.1.1.1")
658 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
660 @unittest.skipUnless(running_extended_tests, "part of extended tests")
661 def test_bier_e2e_1024(self):
662 """ BIER end-to-end BSL:1024"""
663 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
665 @unittest.skipUnless(running_extended_tests, "part of extended tests")
666 def test_bier_e2e_512(self):
667 """ BIER end-to-end BSL:512"""
668 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
670 @unittest.skipUnless(running_extended_tests, "part of extended tests")
671 def test_bier_e2e_256(self):
672 """ BIER end-to-end BSL:256"""
673 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
675 @unittest.skipUnless(running_extended_tests, "part of extended tests")
676 def test_bier_e2e_128(self):
677 """ BIER end-to-end BSL:128"""
678 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
680 def test_bier_e2e_64(self):
681 """ BIER end-to-end BSL:64"""
682 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
684 def test_bier_head_o_udp(self):
685 """BIER head over UDP"""
688 # Add a BIER table for sub-domain 1, set 0, and BSL 256
690 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
691 bt = VppBierTable(self, bti, 77)
695 # 1 bit positions via 1 next hops
698 ip_route = VppIpRoute(self, nh1, 32,
699 [VppRoutePath(self.pg1.remote_ip4,
700 self.pg1.sw_if_index,
701 labels=[VppMplsLabel(2001)])])
702 ip_route.add_vpp_config()
704 udp_encap = VppUdpEncap(self,
708 udp_encap.add_vpp_config()
710 bier_route = VppBierRoute(
712 [VppRoutePath("0.0.0.0",
715 next_hop_id=udp_encap.id)])
716 bier_route.add_vpp_config()
719 # An 2 imposition objects with all bit-positions set
720 # only use the second, but creating 2 tests with a non-zero
721 # value index in the route add
723 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
725 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
729 # Add a multicast route that will forward into the BIER doamin
731 route_ing_232_1_1_1 = VppIpMRoute(
735 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
736 paths=[VppMRoutePath(self.pg0.sw_if_index,
737 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
738 VppMRoutePath(0xffffffff,
739 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
740 proto=DpoProto.DPO_PROTO_BIER,
741 bier_imp=bi2.bi_index)])
742 route_ing_232_1_1_1.add_vpp_config()
745 # inject a packet an IP. We expect it to be BIER and UDP encapped,
747 p = (Ether(dst=self.pg0.local_mac,
748 src=self.pg0.remote_mac) /
749 IP(src="1.1.1.1", dst="232.1.1.1") /
750 UDP(sport=1234, dport=1234))
752 self.pg0.add_stream([p])
753 self.pg_enable_capture(self.pg_interfaces)
756 rx = self.pg1.get_capture(1)
759 # Encap Stack is, eth, IP, UDP, BIFT, BIER
761 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
762 self.assertEqual(rx[0][IP].dst, nh1)
763 self.assertEqual(rx[0][UDP].sport, 330)
764 self.assertEqual(rx[0][UDP].dport, 8138)
765 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
766 self.assertEqual(rx[0][BIFT].sd, 1)
767 self.assertEqual(rx[0][BIFT].set, 0)
768 self.assertEqual(rx[0][BIFT].ttl, 64)
769 self.assertEqual(rx[0][BIER].length, 2)
771 def test_bier_tail_o_udp(self):
772 """BIER Tail over UDP"""
775 # Add a BIER table for sub-domain 0, set 0, and BSL 256
777 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
778 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
784 bdt = VppBierDispTable(self, 8)
788 # BIER route in table that's for-us
790 bier_route_1 = VppBierRoute(
792 [VppRoutePath("0.0.0.0",
794 proto=DpoProto.DPO_PROTO_BIER,
796 bier_route_1.add_vpp_config()
799 # An entry in the disposition table
801 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
802 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
803 DpoProto.DPO_PROTO_BIER,
804 "0.0.0.0", 0, rpf_id=8192)
805 bier_de_1.add_vpp_config()
808 # A multicast route to forward post BIER disposition
810 route_eg_232_1_1_1 = VppIpMRoute(
814 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
815 paths=[VppMRoutePath(self.pg1.sw_if_index,
816 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
817 route_eg_232_1_1_1.add_vpp_config()
818 route_eg_232_1_1_1.update_rpf_id(8192)
821 # A packet with all bits set gets spat out to BP:1
823 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
824 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
825 UDP(sport=333, dport=8138) /
826 BIFT(sd=1, set=0, bsl=2, ttl=255) /
827 BIER(length=BIERLength.BIER_LEN_256,
828 BitString=scapy.compat.chb(255)*32,
830 IP(src="1.1.1.1", dst="232.1.1.1") /
831 UDP(sport=1234, dport=1234) /
834 rx = self.send_and_expect(self.pg0, [p], self.pg1)
837 if __name__ == '__main__':
838 unittest.main(testRunner=VppTestRunner)