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
26 class TestBFIB(VppTestCase):
27 """ BIER FIB Test Case """
30 """ BFIB Unit Tests """
31 error = self.vapi.cli("test bier")
34 self.logger.critical(error)
35 self.assertNotIn("Failed", error)
38 class TestBier(VppTestCase):
39 """ BIER Test Case """
42 super(TestBier, self).setUp()
44 # create 2 pg interfaces
45 self.create_pg_interfaces(range(3))
47 # create the default MPLS table
49 tbl = VppMplsTable(self, 0)
51 self.tables.append(tbl)
53 tbl = VppIpTable(self, 10)
55 self.tables.append(tbl)
57 # setup both interfaces
58 for i in self.pg_interfaces:
67 for i in self.pg_interfaces:
72 super(TestBier, self).tearDown()
74 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
78 # Add a BIER table for sub-domain 0, set 0, and BSL 256
80 bti = VppBierTableID(0, 0, hdr_len_id)
81 bt = VppBierTable(self, bti, 77)
85 # A packet with no bits set gets dropped
87 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
88 MPLS(label=77, ttl=255) /
89 BIER(length=hdr_len_id) /
90 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
91 UDP(sport=1234, dport=1234) /
95 self.send_and_assert_no_replies(self.pg0, pkts,
99 # Add a BIER route for each bit-position in the table via a different
100 # next-hop. Testing whether the BIER walk and replicate forwarding
101 # function works for all bit posisitons.
105 for i in range(1, max_bp+1):
106 nh = "10.0.%d.%d" % (i / 255, i % 255)
108 VppIpRoute(self, nh, 32,
109 [VppRoutePath(self.pg1.remote_ip4,
110 self.pg1.sw_if_index,
111 labels=[VppMplsLabel(2000+i)])]))
112 nh_routes[-1].add_vpp_config()
115 VppBierRoute(self, bti, i,
116 [VppRoutePath(nh, 0xffffffff,
117 labels=[VppMplsLabel(100+i)])]))
118 bier_routes[-1].add_vpp_config()
121 # A packet with all bits set gets replicated once for each bit
123 pkt_sizes = [64, 1400]
125 for pkt_size in pkt_sizes:
126 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
127 MPLS(label=77, ttl=255) /
128 BIER(length=hdr_len_id,
129 BitString=scapy.compat.chb(255)*n_bytes) /
130 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
131 UDP(sport=1234, dport=1234) /
132 Raw(scapy.compat.chb(5) * pkt_size))
135 self.pg0.add_stream(pkts)
136 self.pg_enable_capture(self.pg_interfaces)
139 rx = self.pg1.get_capture(max_bp)
143 # The packets are not required to be sent in bit-position order
144 # when we setup the routes above we used the bit-position to
145 # construct the out-label. so use that here to determine the BP
148 bp = olabel.label - 2000
150 blabel = olabel[MPLS].payload
151 self.assertEqual(blabel.label, 100+bp)
152 self.assertEqual(blabel.ttl, 254)
154 bier_hdr = blabel[MPLS].payload
156 self.assertEqual(bier_hdr.id, 5)
157 self.assertEqual(bier_hdr.version, 0)
158 self.assertEqual(bier_hdr.length, hdr_len_id)
159 self.assertEqual(bier_hdr.entropy, 0)
160 self.assertEqual(bier_hdr.OAM, 0)
161 self.assertEqual(bier_hdr.RSV, 0)
162 self.assertEqual(bier_hdr.DSCP, 0)
163 self.assertEqual(bier_hdr.Proto, 5)
165 # The bit-string should consist only of the BP given by i.
166 byte_array = [b'\0'] * (n_bytes)
167 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
168 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
169 byte_array[byte_pos] = byte_val
170 bitstring = ''.join([scapy.compat.chb(x) for x in byte_array])
172 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
173 self.assertEqual(bitstring, bier_hdr.BitString)
176 # cleanup. not strictly necessary, but it's much quicker this way
177 # because the bier_fib_dump and ip_fib_dump will be empty when the
178 # auto-cleanup kicks in
180 for br in bier_routes:
181 br.remove_vpp_config()
182 for nhr in nh_routes:
183 nhr.remove_vpp_config()
185 @unittest.skipUnless(running_extended_tests, "part of extended tests")
186 def test_bier_midpoint_1024(self):
187 """BIER midpoint BSL:1024"""
188 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
190 @unittest.skipUnless(running_extended_tests, "part of extended tests")
191 def test_bier_midpoint_512(self):
192 """BIER midpoint BSL:512"""
193 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
195 @unittest.skipUnless(running_extended_tests, "part of extended tests")
196 def test_bier_midpoint_256(self):
197 """BIER midpoint BSL:256"""
198 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
200 @unittest.skipUnless(running_extended_tests, "part of extended tests")
201 def test_bier_midpoint_128(self):
202 """BIER midpoint BSL:128"""
203 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
205 def test_bier_midpoint_64(self):
206 """BIER midpoint BSL:64"""
207 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
209 def test_bier_load_balance(self):
210 """BIER load-balance"""
213 # Add a BIER table for sub-domain 0, set 0, and BSL 256
215 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
216 bt = VppBierTable(self, bti, 77)
220 # packets with varying entropy
223 for ii in range(257):
224 pkts.append((Ether(dst=self.pg0.local_mac,
225 src=self.pg0.remote_mac) /
226 MPLS(label=77, ttl=255) /
227 BIER(length=BIERLength.BIER_LEN_64,
229 BitString=scapy.compat.chb(255)*16) /
230 IPv6(src=self.pg0.remote_ip6,
231 dst=self.pg0.remote_ip6) /
232 UDP(sport=1234, dport=1234) /
238 nhs = [{'ip': "10.0.0.1", 'label': 201},
239 {'ip': "10.0.0.2", 'label': 202},
240 {'ip': "10.0.0.3", 'label': 203},
241 {'ip': "10.0.0.4", 'label': 204}]
246 [VppRoutePath(self.pg1.remote_ip4,
247 self.pg1.sw_if_index,
248 labels=[VppMplsLabel(nh['label'])])])
251 bier_route = VppBierRoute(
253 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
254 labels=[VppMplsLabel(101)]),
255 VppRoutePath(nhs[1]['ip'], 0xffffffff,
256 labels=[VppMplsLabel(101)])])
257 bier_route.add_vpp_config()
259 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
262 # we should have recieved a packet from each neighbor
265 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
268 # add the other paths
270 bier_route.update_paths(
271 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
272 labels=[VppMplsLabel(101)]),
273 VppRoutePath(nhs[1]['ip'], 0xffffffff,
274 labels=[VppMplsLabel(101)]),
275 VppRoutePath(nhs[2]['ip'], 0xffffffff,
276 labels=[VppMplsLabel(101)]),
277 VppRoutePath(nhs[3]['ip'], 0xffffffff,
278 labels=[VppMplsLabel(101)])])
280 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
282 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
285 # remove first two paths
287 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
288 labels=[VppMplsLabel(101)]))
289 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
290 labels=[VppMplsLabel(101)]))
292 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
294 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
297 # remove the last of the paths, deleteing the entry
299 bier_route.remove_all_paths()
301 self.send_and_assert_no_replies(self.pg0, pkts)
303 def test_bier_head(self):
307 # Add a BIER table for sub-domain 0, set 0, and BSL 256
309 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
310 bt = VppBierTable(self, bti, 77)
314 # 2 bit positions via two next hops
318 ip_route_1 = VppIpRoute(self, nh1, 32,
319 [VppRoutePath(self.pg1.remote_ip4,
320 self.pg1.sw_if_index,
321 labels=[VppMplsLabel(2001)])])
322 ip_route_2 = VppIpRoute(self, nh2, 32,
323 [VppRoutePath(self.pg1.remote_ip4,
324 self.pg1.sw_if_index,
325 labels=[VppMplsLabel(2002)])])
326 ip_route_1.add_vpp_config()
327 ip_route_2.add_vpp_config()
329 bier_route_1 = VppBierRoute(self, bti, 1,
330 [VppRoutePath(nh1, 0xffffffff,
331 labels=[VppMplsLabel(101)])])
332 bier_route_2 = VppBierRoute(self, bti, 2,
333 [VppRoutePath(nh2, 0xffffffff,
334 labels=[VppMplsLabel(102)])])
335 bier_route_1.add_vpp_config()
336 bier_route_2.add_vpp_config()
339 # An imposition object with both bit-positions set
341 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
345 # Add a multicast route that will forward into the BIER doamin
347 route_ing_232_1_1_1 = VppIpMRoute(
351 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
352 paths=[VppMRoutePath(self.pg0.sw_if_index,
353 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
354 VppMRoutePath(0xffffffff,
355 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
356 proto=DpoProto.DPO_PROTO_BIER,
357 bier_imp=bi.bi_index)])
358 route_ing_232_1_1_1.add_vpp_config()
361 # inject an IP packet. We expect it to be BIER encapped and
364 p = (Ether(dst=self.pg0.local_mac,
365 src=self.pg0.remote_mac) /
366 IP(src="1.1.1.1", dst="232.1.1.1") /
367 UDP(sport=1234, dport=1234))
369 self.pg0.add_stream([p])
370 self.pg_enable_capture(self.pg_interfaces)
373 rx = self.pg1.get_capture(2)
376 # Encap Stack is; eth, MPLS, MPLS, BIER
378 igp_mpls = rx[0][MPLS]
379 self.assertEqual(igp_mpls.label, 2001)
380 self.assertEqual(igp_mpls.ttl, 64)
381 self.assertEqual(igp_mpls.s, 0)
382 bier_mpls = igp_mpls[MPLS].payload
383 self.assertEqual(bier_mpls.label, 101)
384 self.assertEqual(bier_mpls.ttl, 64)
385 self.assertEqual(bier_mpls.s, 1)
386 self.assertEqual(rx[0][BIER].length, 2)
388 igp_mpls = rx[1][MPLS]
389 self.assertEqual(igp_mpls.label, 2002)
390 self.assertEqual(igp_mpls.ttl, 64)
391 self.assertEqual(igp_mpls.s, 0)
392 bier_mpls = igp_mpls[MPLS].payload
393 self.assertEqual(bier_mpls.label, 102)
394 self.assertEqual(bier_mpls.ttl, 64)
395 self.assertEqual(bier_mpls.s, 1)
396 self.assertEqual(rx[0][BIER].length, 2)
398 def test_bier_tail(self):
402 # Add a BIER table for sub-domain 0, set 0, and BSL 256
404 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
405 bt = VppBierTable(self, bti, 77)
411 bdt = VppBierDispTable(self, 8)
415 # BIER route in table that's for-us
417 bier_route_1 = VppBierRoute(
419 [VppRoutePath("0.0.0.0",
421 proto=DpoProto.DPO_PROTO_BIER,
423 bier_route_1.add_vpp_config()
426 # An entry in the disposition table
428 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
429 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
430 DpoProto.DPO_PROTO_BIER,
431 "0.0.0.0", 0, rpf_id=8192)
432 bier_de_1.add_vpp_config()
435 # A multicast route to forward post BIER disposition
437 route_eg_232_1_1_1 = VppIpMRoute(
441 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
442 paths=[VppMRoutePath(self.pg1.sw_if_index,
443 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
444 route_eg_232_1_1_1.add_vpp_config()
445 route_eg_232_1_1_1.update_rpf_id(8192)
448 # A packet with all bits set gets spat out to BP:1
450 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
451 MPLS(label=77, ttl=255) /
452 BIER(length=BIERLength.BIER_LEN_256,
453 BitString=scapy.compat.chb(255)*32,
455 IP(src="1.1.1.1", dst="232.1.1.1") /
456 UDP(sport=1234, dport=1234) /
459 self.send_and_expect(self.pg0, [p], self.pg1)
462 # A packet that does not match the Disposition entry gets dropped
464 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
465 MPLS(label=77, ttl=255) /
466 BIER(length=BIERLength.BIER_LEN_256,
467 BitString=scapy.compat.chb(255)*32,
469 IP(src="1.1.1.1", dst="232.1.1.1") /
470 UDP(sport=1234, dport=1234) /
472 self.send_and_assert_no_replies(self.pg0, p*2,
473 "no matching disposition entry")
476 # Add the default route to the disposition table
478 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
479 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
480 DpoProto.DPO_PROTO_BIER,
481 "0.0.0.0", 0, rpf_id=8192)
482 bier_de_2.add_vpp_config()
485 # now the previous packet is forwarded
487 self.send_and_expect(self.pg0, [p], self.pg1)
490 # A multicast route to forward post BIER disposition that needs
491 # a check against sending back into the BIER core
493 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
496 route_eg_232_1_1_2 = VppIpMRoute(
500 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
501 paths=[VppMRoutePath(0xffffffff,
502 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
503 proto=DpoProto.DPO_PROTO_BIER,
504 bier_imp=bi.bi_index),
505 VppMRoutePath(self.pg1.sw_if_index,
506 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
507 route_eg_232_1_1_2.add_vpp_config()
508 route_eg_232_1_1_2.update_rpf_id(8192)
510 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
511 MPLS(label=77, ttl=255) /
512 BIER(length=BIERLength.BIER_LEN_256,
513 BitString=scapy.compat.chb(255)*32,
515 IP(src="1.1.1.1", dst="232.1.1.2") /
516 UDP(sport=1234, dport=1234) /
518 self.send_and_expect(self.pg0, [p], self.pg1)
520 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
521 """ BIER end-to-end"""
524 # Add a BIER table for sub-domain 0, set 0, and BSL 256
526 bti = VppBierTableID(0, 0, hdr_len_id)
527 bt = VppBierTable(self, bti, 77)
530 lowest = [b'\0'] * (n_bytes)
531 lowest[-1] = scapy.compat.chb(1)
532 highest = [b'\0'] * (n_bytes)
533 highest[0] = scapy.compat.chb(128)
536 # Impostion Sets bit strings
538 bi_low = VppBierImp(self, bti, 333, lowest)
539 bi_low.add_vpp_config()
540 bi_high = VppBierImp(self, bti, 334, highest)
541 bi_high.add_vpp_config()
544 # Add a multicast route that will forward into the BIER doamin
546 route_ing_232_1_1_1 = VppIpMRoute(
550 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
551 paths=[VppMRoutePath(self.pg0.sw_if_index,
552 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
553 VppMRoutePath(0xffffffff,
554 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
555 proto=DpoProto.DPO_PROTO_BIER,
556 bier_imp=bi_low.bi_index)])
557 route_ing_232_1_1_1.add_vpp_config()
558 route_ing_232_1_1_2 = VppIpMRoute(
562 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
563 paths=[VppMRoutePath(self.pg0.sw_if_index,
564 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
565 VppMRoutePath(0xffffffff,
566 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
567 proto=DpoProto.DPO_PROTO_BIER,
568 bier_imp=bi_high.bi_index)])
569 route_ing_232_1_1_2.add_vpp_config()
572 # disposition table 8
574 bdt = VppBierDispTable(self, 8)
578 # BIER routes in table that are for-us, resolving through
581 bier_route_1 = VppBierRoute(
583 [VppRoutePath("0.0.0.0",
585 proto=DpoProto.DPO_PROTO_BIER,
587 bier_route_1.add_vpp_config()
588 bier_route_max = VppBierRoute(
590 [VppRoutePath("0.0.0.0",
593 proto=DpoProto.DPO_PROTO_BIER)])
594 bier_route_max.add_vpp_config()
597 # An entry in the disposition table for sender 333
600 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
601 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
602 DpoProto.DPO_PROTO_BIER,
603 "0.0.0.0", 10, rpf_id=8192)
604 bier_de_1.add_vpp_config()
605 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
606 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
607 DpoProto.DPO_PROTO_BIER,
608 "0.0.0.0", 10, rpf_id=8193)
609 bier_de_1.add_vpp_config()
612 # Add a multicast routes that will forward the traffic
615 route_eg_232_1_1_1 = VppIpMRoute(
619 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
621 paths=[VppMRoutePath(self.pg1.sw_if_index,
622 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
623 route_eg_232_1_1_1.add_vpp_config()
624 route_eg_232_1_1_1.update_rpf_id(8192)
625 route_eg_232_1_1_2 = VppIpMRoute(
629 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
631 paths=[VppMRoutePath(self.pg1.sw_if_index,
632 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
633 route_eg_232_1_1_2.add_vpp_config()
634 route_eg_232_1_1_2.update_rpf_id(8193)
637 # inject a packet in VRF-0. We expect it to be BIER encapped,
638 # replicated, then hit the disposition and be forwarded
639 # out of VRF 10, i.e. on pg1
641 p = (Ether(dst=self.pg0.local_mac,
642 src=self.pg0.remote_mac) /
643 IP(src="1.1.1.1", dst="232.1.1.1") /
644 UDP(sport=1234, dport=1234) /
645 Raw(scapy.compat.chb(5) * 32))
647 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
649 self.assertEqual(rx[0][IP].src, "1.1.1.1")
650 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
652 p = (Ether(dst=self.pg0.local_mac,
653 src=self.pg0.remote_mac) /
654 IP(src="1.1.1.1", dst="232.1.1.2") /
655 UDP(sport=1234, dport=1234) /
656 Raw(scapy.compat.chb(5) * 512))
658 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
659 self.assertEqual(rx[0][IP].src, "1.1.1.1")
660 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
662 @unittest.skipUnless(running_extended_tests, "part of extended tests")
663 def test_bier_e2e_1024(self):
664 """ BIER end-to-end BSL:1024"""
665 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
667 @unittest.skipUnless(running_extended_tests, "part of extended tests")
668 def test_bier_e2e_512(self):
669 """ BIER end-to-end BSL:512"""
670 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
672 @unittest.skipUnless(running_extended_tests, "part of extended tests")
673 def test_bier_e2e_256(self):
674 """ BIER end-to-end BSL:256"""
675 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
677 @unittest.skipUnless(running_extended_tests, "part of extended tests")
678 def test_bier_e2e_128(self):
679 """ BIER end-to-end BSL:128"""
680 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
682 def test_bier_e2e_64(self):
683 """ BIER end-to-end BSL:64"""
684 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
686 def test_bier_head_o_udp(self):
687 """BIER head over UDP"""
690 # Add a BIER table for sub-domain 1, set 0, and BSL 256
692 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
693 bt = VppBierTable(self, bti, 77)
697 # 1 bit positions via 1 next hops
700 ip_route = VppIpRoute(self, nh1, 32,
701 [VppRoutePath(self.pg1.remote_ip4,
702 self.pg1.sw_if_index,
703 labels=[VppMplsLabel(2001)])])
704 ip_route.add_vpp_config()
706 udp_encap = VppUdpEncap(self,
710 udp_encap.add_vpp_config()
712 bier_route = VppBierRoute(
714 [VppRoutePath("0.0.0.0",
717 next_hop_id=udp_encap.id)])
718 bier_route.add_vpp_config()
721 # An 2 imposition objects with all bit-positions set
722 # only use the second, but creating 2 tests with a non-zero
723 # value index in the route add
725 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
727 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
731 # Add a multicast route that will forward into the BIER doamin
733 route_ing_232_1_1_1 = VppIpMRoute(
737 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
738 paths=[VppMRoutePath(self.pg0.sw_if_index,
739 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
740 VppMRoutePath(0xffffffff,
741 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
742 proto=DpoProto.DPO_PROTO_BIER,
743 bier_imp=bi2.bi_index)])
744 route_ing_232_1_1_1.add_vpp_config()
747 # inject a packet an IP. We expect it to be BIER and UDP encapped,
749 p = (Ether(dst=self.pg0.local_mac,
750 src=self.pg0.remote_mac) /
751 IP(src="1.1.1.1", dst="232.1.1.1") /
752 UDP(sport=1234, dport=1234))
754 self.pg0.add_stream([p])
755 self.pg_enable_capture(self.pg_interfaces)
758 rx = self.pg1.get_capture(1)
761 # Encap Stack is, eth, IP, UDP, BIFT, BIER
763 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
764 self.assertEqual(rx[0][IP].dst, nh1)
765 self.assertEqual(rx[0][UDP].sport, 330)
766 self.assertEqual(rx[0][UDP].dport, 8138)
767 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
768 self.assertEqual(rx[0][BIFT].sd, 1)
769 self.assertEqual(rx[0][BIFT].set, 0)
770 self.assertEqual(rx[0][BIFT].ttl, 64)
771 self.assertEqual(rx[0][BIER].length, 2)
773 def test_bier_tail_o_udp(self):
774 """BIER Tail over UDP"""
777 # Add a BIER table for sub-domain 0, set 0, and BSL 256
779 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
780 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
786 bdt = VppBierDispTable(self, 8)
790 # BIER route in table that's for-us
792 bier_route_1 = VppBierRoute(
794 [VppRoutePath("0.0.0.0",
796 proto=DpoProto.DPO_PROTO_BIER,
798 bier_route_1.add_vpp_config()
801 # An entry in the disposition table
803 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
804 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
805 DpoProto.DPO_PROTO_BIER,
806 "0.0.0.0", 0, rpf_id=8192)
807 bier_de_1.add_vpp_config()
810 # A multicast route to forward post BIER disposition
812 route_eg_232_1_1_1 = VppIpMRoute(
816 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
817 paths=[VppMRoutePath(self.pg1.sw_if_index,
818 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
819 route_eg_232_1_1_1.add_vpp_config()
820 route_eg_232_1_1_1.update_rpf_id(8192)
823 # A packet with all bits set gets spat out to BP:1
825 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
826 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
827 UDP(sport=333, dport=8138) /
828 BIFT(sd=1, set=0, bsl=2, ttl=255) /
829 BIER(length=BIERLength.BIER_LEN_256,
830 BitString=scapy.compat.chb(255)*32,
832 IP(src="1.1.1.1", dst="232.1.1.1") /
833 UDP(sport=1234, dport=1234) /
836 rx = self.send_and_expect(self.pg0, [p], self.pg1)
839 if __name__ == '__main__':
840 unittest.main(testRunner=VppTestRunner)