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(self, bti, max_bp,
587 [VppRoutePath("0.0.0.0",
590 bier_route_max.add_vpp_config()
593 # An entry in the disposition table for sender 333
596 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
597 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
598 DpoProto.DPO_PROTO_BIER,
599 "0.0.0.0", 10, rpf_id=8192)
600 bier_de_1.add_vpp_config()
601 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
602 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
603 DpoProto.DPO_PROTO_BIER,
604 "0.0.0.0", 10, rpf_id=8193)
605 bier_de_1.add_vpp_config()
608 # Add a multicast routes that will forward the traffic
611 route_eg_232_1_1_1 = VppIpMRoute(
615 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
617 paths=[VppMRoutePath(self.pg1.sw_if_index,
618 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
619 route_eg_232_1_1_1.add_vpp_config()
620 route_eg_232_1_1_1.update_rpf_id(8192)
621 route_eg_232_1_1_2 = VppIpMRoute(
625 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
627 paths=[VppMRoutePath(self.pg1.sw_if_index,
628 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
629 route_eg_232_1_1_2.add_vpp_config()
630 route_eg_232_1_1_2.update_rpf_id(8193)
633 # inject a packet in VRF-0. We expect it to be BIER encapped,
634 # replicated, then hit the disposition and be forwarded
635 # out of VRF 10, i.e. on pg1
637 p = (Ether(dst=self.pg0.local_mac,
638 src=self.pg0.remote_mac) /
639 IP(src="1.1.1.1", dst="232.1.1.1") /
640 UDP(sport=1234, dport=1234) /
641 Raw(scapy.compat.chb(5) * 32))
643 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
645 self.assertEqual(rx[0][IP].src, "1.1.1.1")
646 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
648 p = (Ether(dst=self.pg0.local_mac,
649 src=self.pg0.remote_mac) /
650 IP(src="1.1.1.1", dst="232.1.1.2") /
651 UDP(sport=1234, dport=1234) /
652 Raw(scapy.compat.chb(5) * 512))
654 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
655 self.assertEqual(rx[0][IP].src, "1.1.1.1")
656 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
658 @unittest.skipUnless(running_extended_tests, "part of extended tests")
659 def test_bier_e2e_1024(self):
660 """ BIER end-to-end BSL:1024"""
661 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
663 @unittest.skipUnless(running_extended_tests, "part of extended tests")
664 def test_bier_e2e_512(self):
665 """ BIER end-to-end BSL:512"""
666 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
668 @unittest.skipUnless(running_extended_tests, "part of extended tests")
669 def test_bier_e2e_256(self):
670 """ BIER end-to-end BSL:256"""
671 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
673 @unittest.skipUnless(running_extended_tests, "part of extended tests")
674 def test_bier_e2e_128(self):
675 """ BIER end-to-end BSL:128"""
676 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
678 def test_bier_e2e_64(self):
679 """ BIER end-to-end BSL:64"""
680 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
682 def test_bier_head_o_udp(self):
683 """BIER head over UDP"""
686 # Add a BIER table for sub-domain 1, set 0, and BSL 256
688 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
689 bt = VppBierTable(self, bti, 77)
693 # 1 bit positions via 1 next hops
696 ip_route = VppIpRoute(self, nh1, 32,
697 [VppRoutePath(self.pg1.remote_ip4,
698 self.pg1.sw_if_index,
699 labels=[VppMplsLabel(2001)])])
700 ip_route.add_vpp_config()
702 udp_encap = VppUdpEncap(self,
706 udp_encap.add_vpp_config()
708 bier_route = VppBierRoute(
710 [VppRoutePath("0.0.0.0",
713 next_hop_id=udp_encap.id)])
714 bier_route.add_vpp_config()
717 # An 2 imposition objects with all bit-positions set
718 # only use the second, but creating 2 tests with a non-zero
719 # value index in the route add
721 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
723 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
727 # Add a multicast route that will forward into the BIER doamin
729 route_ing_232_1_1_1 = VppIpMRoute(
733 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
734 paths=[VppMRoutePath(self.pg0.sw_if_index,
735 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
736 VppMRoutePath(0xffffffff,
737 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
738 proto=DpoProto.DPO_PROTO_BIER,
739 bier_imp=bi2.bi_index)])
740 route_ing_232_1_1_1.add_vpp_config()
743 # inject a packet an IP. We expect it to be BIER and UDP encapped,
745 p = (Ether(dst=self.pg0.local_mac,
746 src=self.pg0.remote_mac) /
747 IP(src="1.1.1.1", dst="232.1.1.1") /
748 UDP(sport=1234, dport=1234))
750 self.pg0.add_stream([p])
751 self.pg_enable_capture(self.pg_interfaces)
754 rx = self.pg1.get_capture(1)
757 # Encap Stack is, eth, IP, UDP, BIFT, BIER
759 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
760 self.assertEqual(rx[0][IP].dst, nh1)
761 self.assertEqual(rx[0][UDP].sport, 330)
762 self.assertEqual(rx[0][UDP].dport, 8138)
763 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
764 self.assertEqual(rx[0][BIFT].sd, 1)
765 self.assertEqual(rx[0][BIFT].set, 0)
766 self.assertEqual(rx[0][BIFT].ttl, 64)
767 self.assertEqual(rx[0][BIER].length, 2)
769 def test_bier_tail_o_udp(self):
770 """BIER Tail over UDP"""
773 # Add a BIER table for sub-domain 0, set 0, and BSL 256
775 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
776 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
782 bdt = VppBierDispTable(self, 8)
786 # BIER route in table that's for-us
788 bier_route_1 = VppBierRoute(
790 [VppRoutePath("0.0.0.0",
792 proto=DpoProto.DPO_PROTO_BIER,
794 bier_route_1.add_vpp_config()
797 # An entry in the disposition table
799 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
800 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
801 DpoProto.DPO_PROTO_BIER,
802 "0.0.0.0", 0, rpf_id=8192)
803 bier_de_1.add_vpp_config()
806 # A multicast route to forward post BIER disposition
808 route_eg_232_1_1_1 = VppIpMRoute(
812 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
813 paths=[VppMRoutePath(self.pg1.sw_if_index,
814 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
815 route_eg_232_1_1_1.add_vpp_config()
816 route_eg_232_1_1_1.update_rpf_id(8192)
819 # A packet with all bits set gets spat out to BP:1
821 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
822 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
823 UDP(sport=333, dport=8138) /
824 BIFT(sd=1, set=0, bsl=2, ttl=255) /
825 BIER(length=BIERLength.BIER_LEN_256,
826 BitString=scapy.compat.chb(255)*32,
828 IP(src="1.1.1.1", dst="232.1.1.1") /
829 UDP(sport=1234, dport=1234) /
832 rx = self.send_and_expect(self.pg0, [p], self.pg1)
835 if __name__ == '__main__':
836 unittest.main(testRunner=VppTestRunner)