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
15 from scapy.packet import Raw
16 from scapy.layers.l2 import Ether
17 from scapy.layers.inet import IP, UDP
18 from scapy.layers.inet6 import IPv6
19 from scapy.contrib.mpls import MPLS
20 from scapy.contrib.bier import BIER, BIERLength, BIFT
23 class TestBFIB(VppTestCase):
24 """ BIER FIB Test Case """
27 """ BFIB Unit Tests """
28 error = self.vapi.cli("test bier")
31 self.logger.critical(error)
32 self.assertEqual(error.find("Failed"), -1)
35 class TestBier(VppTestCase):
36 """ BIER Test Case """
39 super(TestBier, self).setUp()
41 # create 2 pg interfaces
42 self.create_pg_interfaces(range(3))
44 # create the default MPLS table
46 tbl = VppMplsTable(self, 0)
48 self.tables.append(tbl)
50 tbl = VppIpTable(self, 10)
52 self.tables.append(tbl)
54 # setup both interfaces
55 for i in self.pg_interfaces:
64 for i in self.pg_interfaces:
69 super(TestBier, self).tearDown()
71 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
75 # Add a BIER table for sub-domain 0, set 0, and BSL 256
77 bti = VppBierTableID(0, 0, hdr_len_id)
78 bt = VppBierTable(self, bti, 77)
82 # A packet with no bits set gets dropped
84 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
85 MPLS(label=77, ttl=255) /
86 BIER(length=hdr_len_id) /
87 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
88 UDP(sport=1234, dport=1234) /
92 self.send_and_assert_no_replies(self.pg0, pkts,
96 # Add a BIER route for each bit-position in the table via a different
97 # next-hop. Testing whether the BIER walk and replicate forwarding
98 # function works for all bit posisitons.
102 for i in range(1, max_bp+1):
103 nh = "10.0.%d.%d" % (i / 255, i % 255)
105 VppIpRoute(self, nh, 32,
106 [VppRoutePath(self.pg1.remote_ip4,
107 self.pg1.sw_if_index,
108 labels=[VppMplsLabel(2000+i)])]))
109 nh_routes[-1].add_vpp_config()
112 VppBierRoute(self, bti, i,
113 [VppRoutePath(nh, 0xffffffff,
114 labels=[VppMplsLabel(100+i)])]))
115 bier_routes[-1].add_vpp_config()
118 # A packet with all bits set gets replicated once for each bit
120 pkt_sizes = [64, 1400]
122 for pkt_size in pkt_sizes:
123 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
124 MPLS(label=77, ttl=255) /
125 BIER(length=hdr_len_id, BitString=chr(255)*n_bytes) /
126 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
127 UDP(sport=1234, dport=1234) /
128 Raw(chr(5) * pkt_size))
131 self.pg0.add_stream(pkts)
132 self.pg_enable_capture(self.pg_interfaces)
135 rx = self.pg1.get_capture(max_bp)
139 # The packets are not required to be sent in bit-position order
140 # when we setup the routes above we used the bit-position to
141 # construct the out-label. so use that here to determine the BP
144 bp = olabel.label - 2000
146 blabel = olabel[MPLS].payload
147 self.assertEqual(blabel.label, 100+bp)
148 self.assertEqual(blabel.ttl, 254)
150 bier_hdr = blabel[MPLS].payload
152 self.assertEqual(bier_hdr.id, 5)
153 self.assertEqual(bier_hdr.version, 0)
154 self.assertEqual(bier_hdr.length, hdr_len_id)
155 self.assertEqual(bier_hdr.entropy, 0)
156 self.assertEqual(bier_hdr.OAM, 0)
157 self.assertEqual(bier_hdr.RSV, 0)
158 self.assertEqual(bier_hdr.DSCP, 0)
159 self.assertEqual(bier_hdr.Proto, 5)
161 # The bit-string should consist only of the BP given by i.
162 byte_array = ['\0'] * (n_bytes)
163 byte_val = chr(1 << (bp - 1) % 8)
164 byte_pos = n_bytes - (((bp - 1) / 8) + 1)
165 byte_array[byte_pos] = byte_val
166 bitstring = ''.join(byte_array)
168 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
169 self.assertEqual(bitstring, bier_hdr.BitString)
172 # cleanup. not strictly necessary, but it's much quicker this way
173 # becuase the bier_fib_dump and ip_fib_dump will be empty when the
174 # auto-cleanup kicks in
176 for br in bier_routes:
177 br.remove_vpp_config()
178 for nhr in nh_routes:
179 nhr.remove_vpp_config()
181 @unittest.skipUnless(running_extended_tests, "part of extended tests")
182 def test_bier_midpoint_1024(self):
183 """BIER midpoint BSL:1024"""
184 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
186 @unittest.skipUnless(running_extended_tests, "part of extended tests")
187 def test_bier_midpoint_512(self):
188 """BIER midpoint BSL:512"""
189 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
191 @unittest.skipUnless(running_extended_tests, "part of extended tests")
192 def test_bier_midpoint_256(self):
193 """BIER midpoint BSL:256"""
194 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
196 @unittest.skipUnless(running_extended_tests, "part of extended tests")
197 def test_bier_midpoint_128(self):
198 """BIER midpoint BSL:128"""
199 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
201 def test_bier_midpoint_64(self):
202 """BIER midpoint BSL:64"""
203 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
205 def test_bier_load_balance(self):
206 """BIER load-balance"""
209 # Add a BIER table for sub-domain 0, set 0, and BSL 256
211 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
212 bt = VppBierTable(self, bti, 77)
216 # packets with varying entropy
219 for ii in range(257):
220 pkts.append((Ether(dst=self.pg0.local_mac,
221 src=self.pg0.remote_mac) /
222 MPLS(label=77, ttl=255) /
223 BIER(length=BIERLength.BIER_LEN_64,
225 BitString=chr(255)*16) /
226 IPv6(src=self.pg0.remote_ip6,
227 dst=self.pg0.remote_ip6) /
228 UDP(sport=1234, dport=1234) /
234 nhs = [{'ip': "10.0.0.1", 'label': 201},
235 {'ip': "10.0.0.2", 'label': 202},
236 {'ip': "10.0.0.3", 'label': 203},
237 {'ip': "10.0.0.4", 'label': 204}]
242 [VppRoutePath(self.pg1.remote_ip4,
243 self.pg1.sw_if_index,
244 labels=[VppMplsLabel(nh['label'])])])
247 bier_route = VppBierRoute(
249 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
250 labels=[VppMplsLabel(101)]),
251 VppRoutePath(nhs[1]['ip'], 0xffffffff,
252 labels=[VppMplsLabel(101)])])
253 bier_route.add_vpp_config()
255 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
258 # we should have recieved a packet from each neighbor
261 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
264 # add the other paths
266 bier_route.update_paths(
267 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
268 labels=[VppMplsLabel(101)]),
269 VppRoutePath(nhs[1]['ip'], 0xffffffff,
270 labels=[VppMplsLabel(101)]),
271 VppRoutePath(nhs[2]['ip'], 0xffffffff,
272 labels=[VppMplsLabel(101)]),
273 VppRoutePath(nhs[3]['ip'], 0xffffffff,
274 labels=[VppMplsLabel(101)])])
276 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
278 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
281 # remove first two paths
283 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
284 labels=[VppMplsLabel(101)]))
285 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
286 labels=[VppMplsLabel(101)]))
288 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
290 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
293 # remove the last of the paths, deleteing the entry
295 bier_route.remove_all_paths()
297 self.send_and_assert_no_replies(self.pg0, pkts)
299 def test_bier_head(self):
303 # Add a BIER table for sub-domain 0, set 0, and BSL 256
305 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
306 bt = VppBierTable(self, bti, 77)
310 # 2 bit positions via two next hops
314 ip_route_1 = VppIpRoute(self, nh1, 32,
315 [VppRoutePath(self.pg1.remote_ip4,
316 self.pg1.sw_if_index,
317 labels=[VppMplsLabel(2001)])])
318 ip_route_2 = VppIpRoute(self, nh2, 32,
319 [VppRoutePath(self.pg1.remote_ip4,
320 self.pg1.sw_if_index,
321 labels=[VppMplsLabel(2002)])])
322 ip_route_1.add_vpp_config()
323 ip_route_2.add_vpp_config()
325 bier_route_1 = VppBierRoute(self, bti, 1,
326 [VppRoutePath(nh1, 0xffffffff,
327 labels=[VppMplsLabel(101)])])
328 bier_route_2 = VppBierRoute(self, bti, 2,
329 [VppRoutePath(nh2, 0xffffffff,
330 labels=[VppMplsLabel(102)])])
331 bier_route_1.add_vpp_config()
332 bier_route_2.add_vpp_config()
335 # An imposition object with both bit-positions set
337 bi = VppBierImp(self, bti, 333, chr(0x3) * 32)
341 # Add a multicast route that will forward into the BIER doamin
343 route_ing_232_1_1_1 = VppIpMRoute(
347 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
348 paths=[VppMRoutePath(self.pg0.sw_if_index,
349 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
350 VppMRoutePath(0xffffffff,
351 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
352 proto=DpoProto.DPO_PROTO_BIER,
353 bier_imp=bi.bi_index)])
354 route_ing_232_1_1_1.add_vpp_config()
357 # inject an IP packet. We expect it to be BIER encapped and
360 p = (Ether(dst=self.pg0.local_mac,
361 src=self.pg0.remote_mac) /
362 IP(src="1.1.1.1", dst="232.1.1.1") /
363 UDP(sport=1234, dport=1234))
365 self.pg0.add_stream([p])
366 self.pg_enable_capture(self.pg_interfaces)
369 rx = self.pg1.get_capture(2)
372 # Encap Stack is; eth, MPLS, MPLS, BIER
374 igp_mpls = rx[0][MPLS]
375 self.assertEqual(igp_mpls.label, 2001)
376 self.assertEqual(igp_mpls.ttl, 64)
377 self.assertEqual(igp_mpls.s, 0)
378 bier_mpls = igp_mpls[MPLS].payload
379 self.assertEqual(bier_mpls.label, 101)
380 self.assertEqual(bier_mpls.ttl, 64)
381 self.assertEqual(bier_mpls.s, 1)
382 self.assertEqual(rx[0][BIER].length, 2)
384 igp_mpls = rx[1][MPLS]
385 self.assertEqual(igp_mpls.label, 2002)
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, 102)
390 self.assertEqual(bier_mpls.ttl, 64)
391 self.assertEqual(bier_mpls.s, 1)
392 self.assertEqual(rx[0][BIER].length, 2)
394 def test_bier_tail(self):
398 # Add a BIER table for sub-domain 0, set 0, and BSL 256
400 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
401 bt = VppBierTable(self, bti, 77)
407 bdt = VppBierDispTable(self, 8)
411 # BIER route in table that's for-us
413 bier_route_1 = VppBierRoute(
415 [VppRoutePath("0.0.0.0",
417 proto=DpoProto.DPO_PROTO_BIER,
419 bier_route_1.add_vpp_config()
422 # An entry in the disposition table
424 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
425 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
426 DpoProto.DPO_PROTO_BIER,
427 "0.0.0.0", 0, rpf_id=8192)
428 bier_de_1.add_vpp_config()
431 # A multicast route to forward post BIER disposition
433 route_eg_232_1_1_1 = VppIpMRoute(
437 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
438 paths=[VppMRoutePath(self.pg1.sw_if_index,
439 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
440 route_eg_232_1_1_1.add_vpp_config()
441 route_eg_232_1_1_1.update_rpf_id(8192)
444 # A packet with all bits set gets spat out to BP:1
446 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
447 MPLS(label=77, ttl=255) /
448 BIER(length=BIERLength.BIER_LEN_256,
449 BitString=chr(255)*32,
451 IP(src="1.1.1.1", dst="232.1.1.1") /
452 UDP(sport=1234, dport=1234) /
455 self.send_and_expect(self.pg0, [p], self.pg1)
458 # A packet that does not match the Disposition entry gets dropped
460 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
461 MPLS(label=77, ttl=255) /
462 BIER(length=BIERLength.BIER_LEN_256,
463 BitString=chr(255)*32,
465 IP(src="1.1.1.1", dst="232.1.1.1") /
466 UDP(sport=1234, dport=1234) /
468 self.send_and_assert_no_replies(self.pg0, p*2,
469 "no matching disposition entry")
472 # Add the default route to the disposition table
474 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
475 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
476 DpoProto.DPO_PROTO_BIER,
477 "0.0.0.0", 0, rpf_id=8192)
478 bier_de_2.add_vpp_config()
481 # now the previous packet is forwarded
483 self.send_and_expect(self.pg0, [p], self.pg1)
486 # A multicast route to forward post BIER disposition that needs
487 # a check against sending back into the BIER core
489 bi = VppBierImp(self, bti, 333, chr(0x3) * 32)
492 route_eg_232_1_1_2 = VppIpMRoute(
496 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
497 paths=[VppMRoutePath(0xffffffff,
498 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
499 proto=DpoProto.DPO_PROTO_BIER,
500 bier_imp=bi.bi_index),
501 VppMRoutePath(self.pg1.sw_if_index,
502 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
503 route_eg_232_1_1_2.add_vpp_config()
504 route_eg_232_1_1_2.update_rpf_id(8192)
506 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
507 MPLS(label=77, ttl=255) /
508 BIER(length=BIERLength.BIER_LEN_256,
509 BitString=chr(255)*32,
511 IP(src="1.1.1.1", dst="232.1.1.2") /
512 UDP(sport=1234, dport=1234) /
514 self.send_and_expect(self.pg0, [p], self.pg1)
516 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
517 """ BIER end-to-end"""
520 # Add a BIER table for sub-domain 0, set 0, and BSL 256
522 bti = VppBierTableID(0, 0, hdr_len_id)
523 bt = VppBierTable(self, bti, 77)
526 lowest = ['\0'] * (n_bytes)
528 highest = ['\0'] * (n_bytes)
529 highest[0] = chr(128)
532 # Impostion Sets bit strings
534 bi_low = VppBierImp(self, bti, 333, lowest)
535 bi_low.add_vpp_config()
536 bi_high = VppBierImp(self, bti, 334, highest)
537 bi_high.add_vpp_config()
540 # Add a multicast route that will forward into the BIER doamin
542 route_ing_232_1_1_1 = VppIpMRoute(
546 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
547 paths=[VppMRoutePath(self.pg0.sw_if_index,
548 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
549 VppMRoutePath(0xffffffff,
550 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
551 proto=DpoProto.DPO_PROTO_BIER,
552 bier_imp=bi_low.bi_index)])
553 route_ing_232_1_1_1.add_vpp_config()
554 route_ing_232_1_1_2 = VppIpMRoute(
558 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
559 paths=[VppMRoutePath(self.pg0.sw_if_index,
560 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
561 VppMRoutePath(0xffffffff,
562 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
563 proto=DpoProto.DPO_PROTO_BIER,
564 bier_imp=bi_high.bi_index)])
565 route_ing_232_1_1_2.add_vpp_config()
568 # disposition table 8
570 bdt = VppBierDispTable(self, 8)
574 # BIER routes in table that are for-us, resolving through
577 bier_route_1 = VppBierRoute(
579 [VppRoutePath("0.0.0.0",
581 proto=DpoProto.DPO_PROTO_BIER,
583 bier_route_1.add_vpp_config()
584 bier_route_max = VppBierRoute(self, bti, max_bp,
585 [VppRoutePath("0.0.0.0",
588 bier_route_max.add_vpp_config()
591 # An entry in the disposition table for sender 333
594 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
595 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
596 DpoProto.DPO_PROTO_BIER,
597 "0.0.0.0", 10, rpf_id=8192)
598 bier_de_1.add_vpp_config()
599 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
600 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
601 DpoProto.DPO_PROTO_BIER,
602 "0.0.0.0", 10, rpf_id=8193)
603 bier_de_1.add_vpp_config()
606 # Add a multicast routes that will forward the traffic
609 route_eg_232_1_1_1 = VppIpMRoute(
613 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
615 paths=[VppMRoutePath(self.pg1.sw_if_index,
616 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
617 route_eg_232_1_1_1.add_vpp_config()
618 route_eg_232_1_1_1.update_rpf_id(8192)
619 route_eg_232_1_1_2 = VppIpMRoute(
623 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
625 paths=[VppMRoutePath(self.pg1.sw_if_index,
626 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
627 route_eg_232_1_1_2.add_vpp_config()
628 route_eg_232_1_1_2.update_rpf_id(8193)
631 # inject a packet in VRF-0. We expect it to be BIER encapped,
632 # replicated, then hit the disposition and be forwarded
633 # out of VRF 10, i.e. on pg1
635 p = (Ether(dst=self.pg0.local_mac,
636 src=self.pg0.remote_mac) /
637 IP(src="1.1.1.1", dst="232.1.1.1") /
638 UDP(sport=1234, dport=1234) /
641 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
643 self.assertEqual(rx[0][IP].src, "1.1.1.1")
644 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
646 p = (Ether(dst=self.pg0.local_mac,
647 src=self.pg0.remote_mac) /
648 IP(src="1.1.1.1", dst="232.1.1.2") /
649 UDP(sport=1234, dport=1234) /
652 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
653 self.assertEqual(rx[0][IP].src, "1.1.1.1")
654 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
656 @unittest.skipUnless(running_extended_tests, "part of extended tests")
657 def test_bier_e2e_1024(self):
658 """ BIER end-to-end BSL:1024"""
659 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
661 @unittest.skipUnless(running_extended_tests, "part of extended tests")
662 def test_bier_e2e_512(self):
663 """ BIER end-to-end BSL:512"""
664 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
666 @unittest.skipUnless(running_extended_tests, "part of extended tests")
667 def test_bier_e2e_256(self):
668 """ BIER end-to-end BSL:256"""
669 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
671 @unittest.skipUnless(running_extended_tests, "part of extended tests")
672 def test_bier_e2e_128(self):
673 """ BIER end-to-end BSL:128"""
674 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
676 def test_bier_e2e_64(self):
677 """ BIER end-to-end BSL:64"""
678 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
680 def test_bier_head_o_udp(self):
681 """BIER head over UDP"""
684 # Add a BIER table for sub-domain 1, set 0, and BSL 256
686 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
687 bt = VppBierTable(self, bti, 77)
691 # 1 bit positions via 1 next hops
694 ip_route = VppIpRoute(self, nh1, 32,
695 [VppRoutePath(self.pg1.remote_ip4,
696 self.pg1.sw_if_index,
697 labels=[VppMplsLabel(2001)])])
698 ip_route.add_vpp_config()
700 udp_encap = VppUdpEncap(self,
704 udp_encap.add_vpp_config()
706 bier_route = VppBierRoute(
708 [VppRoutePath("0.0.0.0",
711 next_hop_id=udp_encap.id)])
712 bier_route.add_vpp_config()
715 # An 2 imposition objects with all bit-positions set
716 # only use the second, but creating 2 tests with a non-zero
717 # value index in the route add
719 bi = VppBierImp(self, bti, 333, chr(0xff) * 32)
721 bi2 = VppBierImp(self, bti, 334, chr(0xff) * 32)
725 # Add a multicast route that will forward into the BIER doamin
727 route_ing_232_1_1_1 = VppIpMRoute(
731 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
732 paths=[VppMRoutePath(self.pg0.sw_if_index,
733 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
734 VppMRoutePath(0xffffffff,
735 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
736 proto=DpoProto.DPO_PROTO_BIER,
737 bier_imp=bi2.bi_index)])
738 route_ing_232_1_1_1.add_vpp_config()
741 # inject a packet an IP. We expect it to be BIER and UDP encapped,
743 p = (Ether(dst=self.pg0.local_mac,
744 src=self.pg0.remote_mac) /
745 IP(src="1.1.1.1", dst="232.1.1.1") /
746 UDP(sport=1234, dport=1234))
748 self.pg0.add_stream([p])
749 self.pg_enable_capture(self.pg_interfaces)
752 rx = self.pg1.get_capture(1)
755 # Encap Stack is, eth, IP, UDP, BIFT, BIER
757 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
758 self.assertEqual(rx[0][IP].dst, nh1)
759 self.assertEqual(rx[0][UDP].sport, 330)
760 self.assertEqual(rx[0][UDP].dport, 8138)
761 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
762 self.assertEqual(rx[0][BIFT].sd, 1)
763 self.assertEqual(rx[0][BIFT].set, 0)
764 self.assertEqual(rx[0][BIFT].ttl, 64)
765 self.assertEqual(rx[0][BIER].length, 2)
767 def test_bier_tail_o_udp(self):
768 """BIER Tail over UDP"""
771 # Add a BIER table for sub-domain 0, set 0, and BSL 256
773 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
774 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
780 bdt = VppBierDispTable(self, 8)
784 # BIER route in table that's for-us
786 bier_route_1 = VppBierRoute(
788 [VppRoutePath("0.0.0.0",
790 proto=DpoProto.DPO_PROTO_BIER,
792 bier_route_1.add_vpp_config()
795 # An entry in the disposition table
797 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
798 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
799 DpoProto.DPO_PROTO_BIER,
800 "0.0.0.0", 0, rpf_id=8192)
801 bier_de_1.add_vpp_config()
804 # A multicast route to forward post BIER disposition
806 route_eg_232_1_1_1 = VppIpMRoute(
810 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
811 paths=[VppMRoutePath(self.pg1.sw_if_index,
812 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
813 route_eg_232_1_1_1.add_vpp_config()
814 route_eg_232_1_1_1.update_rpf_id(8192)
817 # A packet with all bits set gets spat out to BP:1
819 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
820 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
821 UDP(sport=333, dport=8138) /
822 BIFT(sd=1, set=0, bsl=2, ttl=255) /
823 BIER(length=BIERLength.BIER_LEN_256,
824 BitString=chr(255)*32,
826 IP(src="1.1.1.1", dst="232.1.1.1") /
827 UDP(sport=1234, dport=1234) /
830 rx = self.send_and_expect(self.pg0, [p], self.pg1)
833 if __name__ == '__main__':
834 unittest.main(testRunner=VppTestRunner)