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, \
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
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)
283 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
286 # remove first two paths
288 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
289 labels=[VppMplsLabel(101)]))
290 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
291 labels=[VppMplsLabel(101)]))
293 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
295 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
298 # remove the last of the paths, deleteing the entry
300 bier_route.remove_all_paths()
302 self.send_and_assert_no_replies(self.pg0, pkts)
304 def test_bier_head(self):
308 # Add a BIER table for sub-domain 0, set 0, and BSL 256
310 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
311 bt = VppBierTable(self, bti, 77)
315 # 2 bit positions via two next hops
319 ip_route_1 = VppIpRoute(self, nh1, 32,
320 [VppRoutePath(self.pg1.remote_ip4,
321 self.pg1.sw_if_index,
322 labels=[VppMplsLabel(2001)])])
323 ip_route_2 = VppIpRoute(self, nh2, 32,
324 [VppRoutePath(self.pg1.remote_ip4,
325 self.pg1.sw_if_index,
326 labels=[VppMplsLabel(2002)])])
327 ip_route_1.add_vpp_config()
328 ip_route_2.add_vpp_config()
330 bier_route_1 = VppBierRoute(self, bti, 1,
331 [VppRoutePath(nh1, 0xffffffff,
332 labels=[VppMplsLabel(101)])])
333 bier_route_2 = VppBierRoute(self, bti, 2,
334 [VppRoutePath(nh2, 0xffffffff,
335 labels=[VppMplsLabel(102)])])
336 bier_route_1.add_vpp_config()
337 bier_route_2.add_vpp_config()
340 # An imposition object with both bit-positions set
342 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
346 # Add a multicast route that will forward into the BIER doamin
348 route_ing_232_1_1_1 = VppIpMRoute(
352 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
353 paths=[VppMRoutePath(self.pg0.sw_if_index,
354 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
355 VppMRoutePath(0xffffffff,
356 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
357 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
358 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
359 bier_imp=bi.bi_index)])
360 route_ing_232_1_1_1.add_vpp_config()
363 # inject an IP packet. We expect it to be BIER encapped and
366 p = (Ether(dst=self.pg0.local_mac,
367 src=self.pg0.remote_mac) /
368 IP(src="1.1.1.1", dst="232.1.1.1") /
369 UDP(sport=1234, dport=1234))
371 self.pg0.add_stream([p])
372 self.pg_enable_capture(self.pg_interfaces)
375 rx = self.pg1.get_capture(2)
378 # Encap Stack is; eth, MPLS, MPLS, BIER
380 igp_mpls = rx[0][MPLS]
381 self.assertEqual(igp_mpls.label, 2001)
382 self.assertEqual(igp_mpls.ttl, 64)
383 self.assertEqual(igp_mpls.s, 0)
384 bier_mpls = igp_mpls[MPLS].payload
385 self.assertEqual(bier_mpls.label, 101)
386 self.assertEqual(bier_mpls.ttl, 64)
387 self.assertEqual(bier_mpls.s, 1)
388 self.assertEqual(rx[0][BIER].length, 2)
390 igp_mpls = rx[1][MPLS]
391 self.assertEqual(igp_mpls.label, 2002)
392 self.assertEqual(igp_mpls.ttl, 64)
393 self.assertEqual(igp_mpls.s, 0)
394 bier_mpls = igp_mpls[MPLS].payload
395 self.assertEqual(bier_mpls.label, 102)
396 self.assertEqual(bier_mpls.ttl, 64)
397 self.assertEqual(bier_mpls.s, 1)
398 self.assertEqual(rx[0][BIER].length, 2)
400 def test_bier_tail(self):
404 # Add a BIER table for sub-domain 0, set 0, and BSL 256
406 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
407 bt = VppBierTable(self, bti, 77)
413 bdt = VppBierDispTable(self, 8)
417 # BIER route in table that's for-us
419 bier_route_1 = VppBierRoute(
421 [VppRoutePath("0.0.0.0",
423 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
425 bier_route_1.add_vpp_config()
428 # An entry in the disposition table
430 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
431 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
432 FibPathProto.FIB_PATH_NH_PROTO_BIER,
433 "0.0.0.0", 0, rpf_id=8192)
434 bier_de_1.add_vpp_config()
437 # A multicast route to forward post BIER disposition
439 route_eg_232_1_1_1 = VppIpMRoute(
443 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
444 paths=[VppMRoutePath(self.pg1.sw_if_index,
445 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
446 route_eg_232_1_1_1.add_vpp_config()
447 route_eg_232_1_1_1.update_rpf_id(8192)
450 # A packet with all bits set gets spat out to BP:1
452 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
453 MPLS(label=77, ttl=255) /
454 BIER(length=BIERLength.BIER_LEN_256,
455 BitString=scapy.compat.chb(255)*32,
457 IP(src="1.1.1.1", dst="232.1.1.1") /
458 UDP(sport=1234, dport=1234) /
461 self.send_and_expect(self.pg0, [p], self.pg1)
464 # A packet that does not match the Disposition entry gets dropped
466 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
467 MPLS(label=77, ttl=255) /
468 BIER(length=BIERLength.BIER_LEN_256,
469 BitString=scapy.compat.chb(255)*32,
471 IP(src="1.1.1.1", dst="232.1.1.1") /
472 UDP(sport=1234, dport=1234) /
474 self.send_and_assert_no_replies(self.pg0, p*2,
475 "no matching disposition entry")
478 # Add the default route to the disposition table
480 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
481 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
482 FibPathProto.FIB_PATH_NH_PROTO_BIER,
483 "0.0.0.0", 0, rpf_id=8192)
484 bier_de_2.add_vpp_config()
487 # now the previous packet is forwarded
489 self.send_and_expect(self.pg0, [p], self.pg1)
492 # A multicast route to forward post BIER disposition that needs
493 # a check against sending back into the BIER core
495 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
498 route_eg_232_1_1_2 = VppIpMRoute(
502 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
503 paths=[VppMRoutePath(0xffffffff,
504 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
505 proto=DpoProto.DPO_PROTO_BIER,
506 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
507 bier_imp=bi.bi_index),
508 VppMRoutePath(self.pg1.sw_if_index,
509 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
510 route_eg_232_1_1_2.add_vpp_config()
511 route_eg_232_1_1_2.update_rpf_id(8192)
513 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
514 MPLS(label=77, ttl=255) /
515 BIER(length=BIERLength.BIER_LEN_256,
516 BitString=scapy.compat.chb(255)*32,
518 IP(src="1.1.1.1", dst="232.1.1.2") /
519 UDP(sport=1234, dport=1234) /
521 self.send_and_expect(self.pg0, [p], self.pg1)
523 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
524 """ BIER end-to-end"""
527 # Add a BIER table for sub-domain 0, set 0, and BSL 256
529 bti = VppBierTableID(0, 0, hdr_len_id)
530 bt = VppBierTable(self, bti, 77)
533 lowest = [b'\0'] * (n_bytes)
534 lowest[-1] = scapy.compat.chb(1)
535 highest = [b'\0'] * (n_bytes)
536 highest[0] = scapy.compat.chb(128)
539 # Impostion Sets bit strings
541 bi_low = VppBierImp(self, bti, 333, lowest)
542 bi_low.add_vpp_config()
543 bi_high = VppBierImp(self, bti, 334, highest)
544 bi_high.add_vpp_config()
547 # Add a multicast route that will forward into the BIER doamin
549 route_ing_232_1_1_1 = VppIpMRoute(
553 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
554 paths=[VppMRoutePath(self.pg0.sw_if_index,
555 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
556 VppMRoutePath(0xffffffff,
557 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
558 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
559 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
560 bier_imp=bi_low.bi_index)])
561 route_ing_232_1_1_1.add_vpp_config()
562 route_ing_232_1_1_2 = VppIpMRoute(
566 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
567 paths=[VppMRoutePath(self.pg0.sw_if_index,
568 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
569 VppMRoutePath(0xffffffff,
570 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
571 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
572 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
573 bier_imp=bi_high.bi_index)])
574 route_ing_232_1_1_2.add_vpp_config()
577 # disposition table 8
579 bdt = VppBierDispTable(self, 8)
583 # BIER routes in table that are for-us, resolving through
586 bier_route_1 = VppBierRoute(
588 [VppRoutePath("0.0.0.0",
590 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
592 bier_route_1.add_vpp_config()
593 bier_route_max = VppBierRoute(
595 [VppRoutePath("0.0.0.0",
597 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
599 bier_route_max.add_vpp_config()
602 # An entry in the disposition table for sender 333
605 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
606 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
607 FibPathProto.FIB_PATH_NH_PROTO_BIER,
608 "0.0.0.0", 10, rpf_id=8192)
609 bier_de_1.add_vpp_config()
610 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
611 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
612 FibPathProto.FIB_PATH_NH_PROTO_BIER,
613 "0.0.0.0", 10, rpf_id=8193)
614 bier_de_1.add_vpp_config()
617 # Add a multicast routes that will forward the traffic
620 route_eg_232_1_1_1 = VppIpMRoute(
624 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
626 paths=[VppMRoutePath(self.pg1.sw_if_index,
627 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
628 route_eg_232_1_1_1.add_vpp_config()
629 route_eg_232_1_1_1.update_rpf_id(8192)
630 route_eg_232_1_1_2 = VppIpMRoute(
634 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
636 paths=[VppMRoutePath(self.pg1.sw_if_index,
637 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
638 route_eg_232_1_1_2.add_vpp_config()
639 route_eg_232_1_1_2.update_rpf_id(8193)
642 # inject a packet in VRF-0. We expect it to be BIER encapped,
643 # replicated, then hit the disposition and be forwarded
644 # out of VRF 10, i.e. on pg1
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.1") /
649 UDP(sport=1234, dport=1234) /
650 Raw(scapy.compat.chb(5) * 32))
652 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
654 self.assertEqual(rx[0][IP].src, "1.1.1.1")
655 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
657 p = (Ether(dst=self.pg0.local_mac,
658 src=self.pg0.remote_mac) /
659 IP(src="1.1.1.1", dst="232.1.1.2") /
660 UDP(sport=1234, dport=1234) /
661 Raw(scapy.compat.chb(5) * 512))
663 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.2")
667 @unittest.skipUnless(running_extended_tests, "part of extended tests")
668 def test_bier_e2e_1024(self):
669 """ BIER end-to-end BSL:1024"""
670 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
672 @unittest.skipUnless(running_extended_tests, "part of extended tests")
673 def test_bier_e2e_512(self):
674 """ BIER end-to-end BSL:512"""
675 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
677 @unittest.skipUnless(running_extended_tests, "part of extended tests")
678 def test_bier_e2e_256(self):
679 """ BIER end-to-end BSL:256"""
680 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
682 @unittest.skipUnless(running_extended_tests, "part of extended tests")
683 def test_bier_e2e_128(self):
684 """ BIER end-to-end BSL:128"""
685 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
687 def test_bier_e2e_64(self):
688 """ BIER end-to-end BSL:64"""
689 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
691 def test_bier_head_o_udp(self):
692 """BIER head over UDP"""
695 # Add a BIER table for sub-domain 1, set 0, and BSL 256
697 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
698 bt = VppBierTable(self, bti, 77)
702 # 1 bit positions via 1 next hops
705 ip_route = VppIpRoute(self, nh1, 32,
706 [VppRoutePath(self.pg1.remote_ip4,
707 self.pg1.sw_if_index,
708 labels=[VppMplsLabel(2001)])])
709 ip_route.add_vpp_config()
711 udp_encap = VppUdpEncap(self,
715 udp_encap.add_vpp_config()
717 bier_route = VppBierRoute(
719 [VppRoutePath("0.0.0.0",
721 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
722 next_hop_id=udp_encap.id)])
723 bier_route.add_vpp_config()
726 # An 2 imposition objects with all bit-positions set
727 # only use the second, but creating 2 tests with a non-zero
728 # value index in the route add
730 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
732 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
736 # Add a multicast route that will forward into the BIER doamin
738 route_ing_232_1_1_1 = VppIpMRoute(
742 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
743 paths=[VppMRoutePath(self.pg0.sw_if_index,
744 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
745 VppMRoutePath(0xffffffff,
746 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
747 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
748 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
749 bier_imp=bi2.bi_index)])
750 route_ing_232_1_1_1.add_vpp_config()
753 # inject a packet an IP. We expect it to be BIER and UDP encapped,
755 p = (Ether(dst=self.pg0.local_mac,
756 src=self.pg0.remote_mac) /
757 IP(src="1.1.1.1", dst="232.1.1.1") /
758 UDP(sport=1234, dport=1234))
760 self.pg0.add_stream([p])
761 self.pg_enable_capture(self.pg_interfaces)
764 rx = self.pg1.get_capture(1)
767 # Encap Stack is, eth, IP, UDP, BIFT, BIER
769 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
770 self.assertEqual(rx[0][IP].dst, nh1)
771 self.assertEqual(rx[0][UDP].sport, 330)
772 self.assertEqual(rx[0][UDP].dport, 8138)
773 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
774 self.assertEqual(rx[0][BIFT].sd, 1)
775 self.assertEqual(rx[0][BIFT].set, 0)
776 self.assertEqual(rx[0][BIFT].ttl, 64)
777 self.assertEqual(rx[0][BIER].length, 2)
779 def test_bier_tail_o_udp(self):
780 """BIER Tail over UDP"""
783 # Add a BIER table for sub-domain 0, set 0, and BSL 256
785 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
786 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
792 bdt = VppBierDispTable(self, 8)
796 # BIER route in table that's for-us
798 bier_route_1 = VppBierRoute(
800 [VppRoutePath("0.0.0.0",
802 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
804 bier_route_1.add_vpp_config()
807 # An entry in the disposition table
809 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
810 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
811 FibPathProto.FIB_PATH_NH_PROTO_BIER,
812 "0.0.0.0", 0, rpf_id=8192)
813 bier_de_1.add_vpp_config()
816 # A multicast route to forward post BIER disposition
818 route_eg_232_1_1_1 = VppIpMRoute(
822 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
823 paths=[VppMRoutePath(self.pg1.sw_if_index,
824 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
825 route_eg_232_1_1_1.add_vpp_config()
826 route_eg_232_1_1_1.update_rpf_id(8192)
829 # A packet with all bits set gets spat out to BP:1
831 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
832 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
833 UDP(sport=333, dport=8138) /
834 BIFT(sd=1, set=0, bsl=2, ttl=255) /
835 BIER(length=BIERLength.BIER_LEN_256,
836 BitString=scapy.compat.chb(255)*32,
838 IP(src="1.1.1.1", dst="232.1.1.1") /
839 UDP(sport=1234, dport=1234) /
842 rx = self.send_and_expect(self.pg0, [p], self.pg1)
845 if __name__ == '__main__':
846 unittest.main(testRunner=VppTestRunner)