5 from config import config
6 from framework import VppTestCase, VppTestRunner
7 from vpp_ip import DpoProto
8 from vpp_ip_route import VppIpRoute, VppRoutePath, \
9 VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \
11 VppMplsLabel, FibPathProto, FibPathType
12 from vpp_bier import BIER_HDR_PAYLOAD, VppBierImp, VppBierDispEntry, \
13 VppBierDispTable, VppBierTable, VppBierTableID, VppBierRoute
14 from vpp_udp_encap import VppUdpEncap
15 from vpp_papi import VppEnum
18 from scapy.packet import Raw
19 from scapy.layers.l2 import Ether
20 from scapy.layers.inet import IP, UDP
21 from scapy.layers.inet6 import IPv6
22 from scapy.contrib.mpls import MPLS
23 from scapy.contrib.bier import BIER, BIERLength, BIFT
28 class TestBFIB(VppTestCase):
29 """ BIER FIB Test Case """
32 """ BFIB Unit Tests """
33 error = self.vapi.cli("test bier")
36 self.logger.critical(error)
37 self.assertNotIn("Failed", error)
40 class TestBier(VppTestCase):
41 """ BIER Test Case """
44 super(TestBier, self).setUp()
46 # create 2 pg interfaces
47 self.create_pg_interfaces(range(3))
49 # create the default MPLS table
51 tbl = VppMplsTable(self, 0)
53 self.tables.append(tbl)
55 tbl = VppIpTable(self, 10)
57 self.tables.append(tbl)
59 # setup both interfaces
60 for i in self.pg_interfaces:
69 for i in self.pg_interfaces:
74 super(TestBier, self).tearDown()
76 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
80 # Add a BIER table for sub-domain 0, set 0, and BSL 256
82 bti = VppBierTableID(0, 0, hdr_len_id)
83 bt = VppBierTable(self, bti, 77)
87 # A packet with no bits set gets dropped
89 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
90 MPLS(label=77, ttl=255) /
91 BIER(length=hdr_len_id) /
92 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
93 UDP(sport=1234, dport=1234) /
97 self.send_and_assert_no_replies(self.pg0, pkts,
101 # Add a BIER route for each bit-position in the table via a different
102 # next-hop. Testing whether the BIER walk and replicate forwarding
103 # function works for all bit posisitons.
107 for i in range(1, max_bp+1):
108 nh = "10.0.%d.%d" % (i / 255, i % 255)
110 VppIpRoute(self, nh, 32,
111 [VppRoutePath(self.pg1.remote_ip4,
112 self.pg1.sw_if_index,
113 labels=[VppMplsLabel(2000+i)])]))
114 nh_routes[-1].add_vpp_config()
117 VppBierRoute(self, bti, i,
118 [VppRoutePath(nh, 0xffffffff,
119 labels=[VppMplsLabel(100+i)])]))
120 bier_routes[-1].add_vpp_config()
123 # A packet with all bits set gets replicated once for each bit
125 pkt_sizes = [64, 1400]
127 for pkt_size in pkt_sizes:
128 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
129 MPLS(label=77, ttl=255) /
130 BIER(length=hdr_len_id,
131 BitString=scapy.compat.chb(255)*n_bytes) /
132 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
133 UDP(sport=1234, dport=1234) /
134 Raw(scapy.compat.chb(5) * pkt_size))
137 self.pg0.add_stream(pkts)
138 self.pg_enable_capture(self.pg_interfaces)
141 rx = self.pg1.get_capture(max_bp)
145 # The packets are not required to be sent in bit-position order
146 # when we setup the routes above we used the bit-position to
147 # construct the out-label. so use that here to determine the BP
150 bp = olabel.label - 2000
152 blabel = olabel[MPLS].payload
153 self.assertEqual(blabel.label, 100+bp)
154 self.assertEqual(blabel.ttl, 254)
156 bier_hdr = blabel[MPLS].payload
158 self.assertEqual(bier_hdr.id, 5)
159 self.assertEqual(bier_hdr.version, 0)
160 self.assertEqual(bier_hdr.length, hdr_len_id)
161 self.assertEqual(bier_hdr.entropy, 0)
162 self.assertEqual(bier_hdr.OAM, 0)
163 self.assertEqual(bier_hdr.RSV, 0)
164 self.assertEqual(bier_hdr.DSCP, 0)
165 self.assertEqual(bier_hdr.Proto, 5)
167 # The bit-string should consist only of the BP given by i.
168 byte_array = [b'\0'] * (n_bytes)
169 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
170 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
171 byte_array[byte_pos] = byte_val
172 bitstring = b''.join(byte_array)
174 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
175 self.assertEqual(bitstring, bier_hdr.BitString)
178 # cleanup. not strictly necessary, but it's much quicker this way
179 # because the bier_fib_dump and ip_fib_dump will be empty when the
180 # auto-cleanup kicks in
182 for br in bier_routes:
183 br.remove_vpp_config()
184 for nhr in nh_routes:
185 nhr.remove_vpp_config()
187 @unittest.skipUnless(config.extended, "part of extended tests")
188 def test_bier_midpoint_1024(self):
189 """BIER midpoint BSL:1024"""
190 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
192 @unittest.skipUnless(config.extended, "part of extended tests")
193 def test_bier_midpoint_512(self):
194 """BIER midpoint BSL:512"""
195 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
197 @unittest.skipUnless(config.extended, "part of extended tests")
198 def test_bier_midpoint_256(self):
199 """BIER midpoint BSL:256"""
200 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
202 @unittest.skipUnless(config.extended, "part of extended tests")
203 def test_bier_midpoint_128(self):
204 """BIER midpoint BSL:128"""
205 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
207 def test_bier_midpoint_64(self):
208 """BIER midpoint BSL:64"""
209 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
211 def test_bier_load_balance(self):
212 """BIER load-balance"""
215 # Add a BIER table for sub-domain 0, set 0, and BSL 256
217 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
218 bt = VppBierTable(self, bti, 77)
222 # packets with varying entropy
225 for ii in range(257):
226 pkts.append((Ether(dst=self.pg0.local_mac,
227 src=self.pg0.remote_mac) /
228 MPLS(label=77, ttl=255) /
229 BIER(length=BIERLength.BIER_LEN_64,
231 BitString=scapy.compat.chb(255)*16) /
232 IPv6(src=self.pg0.remote_ip6,
233 dst=self.pg0.remote_ip6) /
234 UDP(sport=1234, dport=1234) /
240 nhs = [{'ip': "10.0.0.1", 'label': 201},
241 {'ip': "10.0.0.2", 'label': 202},
242 {'ip': "10.0.0.3", 'label': 203},
243 {'ip': "10.0.0.4", 'label': 204}]
248 [VppRoutePath(self.pg1.remote_ip4,
249 self.pg1.sw_if_index,
250 labels=[VppMplsLabel(nh['label'])])])
253 bier_route = VppBierRoute(
255 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
256 labels=[VppMplsLabel(101)]),
257 VppRoutePath(nhs[1]['ip'], 0xffffffff,
258 labels=[VppMplsLabel(101)])])
259 bier_route.add_vpp_config()
261 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
264 # we should have recieved a packet from each neighbor
267 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
270 # add the other paths
272 bier_route.update_paths(
273 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
274 labels=[VppMplsLabel(101)]),
275 VppRoutePath(nhs[1]['ip'], 0xffffffff,
276 labels=[VppMplsLabel(101)]),
277 VppRoutePath(nhs[2]['ip'], 0xffffffff,
278 labels=[VppMplsLabel(101)]),
279 VppRoutePath(nhs[3]['ip'], 0xffffffff,
280 labels=[VppMplsLabel(101)])])
282 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
285 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
288 # remove first two paths
290 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
291 labels=[VppMplsLabel(101)]))
292 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
293 labels=[VppMplsLabel(101)]))
295 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
297 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
300 # remove the last of the paths, deleteing the entry
302 bier_route.remove_all_paths()
304 self.send_and_assert_no_replies(self.pg0, pkts)
306 def test_bier_head(self):
309 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
310 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
313 # Add a BIER table for sub-domain 0, set 0, and BSL 256
315 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
316 bt = VppBierTable(self, bti, 77)
320 # 2 bit positions via two next hops
324 ip_route_1 = VppIpRoute(self, nh1, 32,
325 [VppRoutePath(self.pg1.remote_ip4,
326 self.pg1.sw_if_index,
327 labels=[VppMplsLabel(2001)])])
328 ip_route_2 = VppIpRoute(self, nh2, 32,
329 [VppRoutePath(self.pg1.remote_ip4,
330 self.pg1.sw_if_index,
331 labels=[VppMplsLabel(2002)])])
332 ip_route_1.add_vpp_config()
333 ip_route_2.add_vpp_config()
335 bier_route_1 = VppBierRoute(self, bti, 1,
336 [VppRoutePath(nh1, 0xffffffff,
337 labels=[VppMplsLabel(101)])])
338 bier_route_2 = VppBierRoute(self, bti, 2,
339 [VppRoutePath(nh2, 0xffffffff,
340 labels=[VppMplsLabel(102)])])
341 bier_route_1.add_vpp_config()
342 bier_route_2.add_vpp_config()
345 # An imposition object with both bit-positions set
347 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
351 # Add a multicast route that will forward into the BIER doamin
353 route_ing_232_1_1_1 = VppIpMRoute(
357 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
358 paths=[VppMRoutePath(self.pg0.sw_if_index,
359 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
360 VppMRoutePath(0xffffffff,
361 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
362 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
363 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
364 bier_imp=bi.bi_index)])
365 route_ing_232_1_1_1.add_vpp_config()
368 # inject an IP packet. We expect it to be BIER encapped and
371 p = (Ether(dst=self.pg0.local_mac,
372 src=self.pg0.remote_mac) /
373 IP(src="1.1.1.1", dst="232.1.1.1") /
374 UDP(sport=1234, dport=1234))
376 self.pg0.add_stream([p])
377 self.pg_enable_capture(self.pg_interfaces)
380 rx = self.pg1.get_capture(2)
383 # Encap Stack is; eth, MPLS, MPLS, BIER
385 igp_mpls = rx[0][MPLS]
386 self.assertEqual(igp_mpls.label, 2001)
387 self.assertEqual(igp_mpls.ttl, 64)
388 self.assertEqual(igp_mpls.s, 0)
389 bier_mpls = igp_mpls[MPLS].payload
390 self.assertEqual(bier_mpls.label, 101)
391 self.assertEqual(bier_mpls.ttl, 64)
392 self.assertEqual(bier_mpls.s, 1)
393 self.assertEqual(rx[0][BIER].length, 2)
395 igp_mpls = rx[1][MPLS]
396 self.assertEqual(igp_mpls.label, 2002)
397 self.assertEqual(igp_mpls.ttl, 64)
398 self.assertEqual(igp_mpls.s, 0)
399 bier_mpls = igp_mpls[MPLS].payload
400 self.assertEqual(bier_mpls.label, 102)
401 self.assertEqual(bier_mpls.ttl, 64)
402 self.assertEqual(bier_mpls.s, 1)
403 self.assertEqual(rx[0][BIER].length, 2)
405 def test_bier_tail(self):
408 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
409 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
412 # Add a BIER table for sub-domain 0, set 0, and BSL 256
414 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
415 bt = VppBierTable(self, bti, 77)
421 bdt = VppBierDispTable(self, 8)
425 # BIER route in table that's for-us
427 bier_route_1 = VppBierRoute(
429 [VppRoutePath("0.0.0.0",
431 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
433 bier_route_1.add_vpp_config()
436 # An entry in the disposition table
438 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
439 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
440 FibPathProto.FIB_PATH_NH_PROTO_BIER,
441 "0.0.0.0", 0, rpf_id=8192)
442 bier_de_1.add_vpp_config()
445 # A multicast route to forward post BIER disposition
447 route_eg_232_1_1_1 = VppIpMRoute(
451 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
452 paths=[VppMRoutePath(self.pg1.sw_if_index,
453 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
454 route_eg_232_1_1_1.add_vpp_config()
455 route_eg_232_1_1_1.update_rpf_id(8192)
458 # A packet with all bits set gets spat out to BP:1
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=scapy.compat.chb(255)*32,
465 IP(src="1.1.1.1", dst="232.1.1.1") /
466 UDP(sport=1234, dport=1234) /
469 self.send_and_expect(self.pg0, [p], self.pg1)
472 # A packet that does not match the Disposition entry gets dropped
474 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
475 MPLS(label=77, ttl=255) /
476 BIER(length=BIERLength.BIER_LEN_256,
477 BitString=scapy.compat.chb(255)*32,
479 IP(src="1.1.1.1", dst="232.1.1.1") /
480 UDP(sport=1234, dport=1234) /
482 self.send_and_assert_no_replies(self.pg0, p*2,
483 "no matching disposition entry")
486 # Add the default route to the disposition table
488 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
489 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
490 FibPathProto.FIB_PATH_NH_PROTO_BIER,
491 "0.0.0.0", 0, rpf_id=8192)
492 bier_de_2.add_vpp_config()
495 # now the previous packet is forwarded
497 self.send_and_expect(self.pg0, [p], self.pg1)
500 # A multicast route to forward post BIER disposition that needs
501 # a check against sending back into the BIER core
503 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
506 route_eg_232_1_1_2 = VppIpMRoute(
510 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
511 paths=[VppMRoutePath(0xffffffff,
512 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
513 proto=DpoProto.DPO_PROTO_BIER,
514 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
515 bier_imp=bi.bi_index),
516 VppMRoutePath(self.pg1.sw_if_index,
517 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
518 route_eg_232_1_1_2.add_vpp_config()
519 route_eg_232_1_1_2.update_rpf_id(8192)
521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
522 MPLS(label=77, ttl=255) /
523 BIER(length=BIERLength.BIER_LEN_256,
524 BitString=scapy.compat.chb(255)*32,
526 IP(src="1.1.1.1", dst="232.1.1.2") /
527 UDP(sport=1234, dport=1234) /
529 self.send_and_expect(self.pg0, [p], self.pg1)
531 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
532 """ BIER end-to-end"""
534 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
535 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
538 # Add a BIER table for sub-domain 0, set 0, and BSL 256
540 bti = VppBierTableID(0, 0, hdr_len_id)
541 bt = VppBierTable(self, bti, 77)
544 lowest = [b'\0'] * (n_bytes)
545 lowest[-1] = scapy.compat.chb(1)
546 highest = [b'\0'] * (n_bytes)
547 highest[0] = scapy.compat.chb(128)
550 # Impostion Sets bit strings
552 bi_low = VppBierImp(self, bti, 333, lowest)
553 bi_low.add_vpp_config()
554 bi_high = VppBierImp(self, bti, 334, highest)
555 bi_high.add_vpp_config()
558 # Add a multicast route that will forward into the BIER doamin
560 route_ing_232_1_1_1 = VppIpMRoute(
564 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
565 paths=[VppMRoutePath(self.pg0.sw_if_index,
566 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
567 VppMRoutePath(0xffffffff,
568 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
569 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
570 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
571 bier_imp=bi_low.bi_index)])
572 route_ing_232_1_1_1.add_vpp_config()
573 route_ing_232_1_1_2 = VppIpMRoute(
577 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
578 paths=[VppMRoutePath(self.pg0.sw_if_index,
579 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
580 VppMRoutePath(0xffffffff,
581 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
582 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
583 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
584 bier_imp=bi_high.bi_index)])
585 route_ing_232_1_1_2.add_vpp_config()
588 # disposition table 8
590 bdt = VppBierDispTable(self, 8)
594 # BIER routes in table that are for-us, resolving through
597 bier_route_1 = VppBierRoute(
599 [VppRoutePath("0.0.0.0",
601 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
603 bier_route_1.add_vpp_config()
604 bier_route_max = VppBierRoute(
606 [VppRoutePath("0.0.0.0",
608 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
610 bier_route_max.add_vpp_config()
613 # An entry in the disposition table for sender 333
616 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
617 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
618 FibPathProto.FIB_PATH_NH_PROTO_BIER,
619 "0.0.0.0", 10, rpf_id=8192)
620 bier_de_1.add_vpp_config()
621 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
622 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
623 FibPathProto.FIB_PATH_NH_PROTO_BIER,
624 "0.0.0.0", 10, rpf_id=8193)
625 bier_de_1.add_vpp_config()
628 # Add a multicast routes that will forward the traffic
631 route_eg_232_1_1_1 = VppIpMRoute(
635 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
637 paths=[VppMRoutePath(self.pg1.sw_if_index,
638 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
639 route_eg_232_1_1_1.add_vpp_config()
640 route_eg_232_1_1_1.update_rpf_id(8192)
641 route_eg_232_1_1_2 = VppIpMRoute(
645 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
647 paths=[VppMRoutePath(self.pg1.sw_if_index,
648 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
649 route_eg_232_1_1_2.add_vpp_config()
650 route_eg_232_1_1_2.update_rpf_id(8193)
653 # inject a packet in VRF-0. We expect it to be BIER encapped,
654 # replicated, then hit the disposition and be forwarded
655 # out of VRF 10, i.e. on pg1
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.1") /
660 UDP(sport=1234, dport=1234) /
661 Raw(scapy.compat.chb(5) * 32))
663 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
665 self.assertEqual(rx[0][IP].src, "1.1.1.1")
666 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
668 p = (Ether(dst=self.pg0.local_mac,
669 src=self.pg0.remote_mac) /
670 IP(src="1.1.1.1", dst="232.1.1.2") /
671 UDP(sport=1234, dport=1234) /
672 Raw(scapy.compat.chb(5) * 512))
674 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
675 self.assertEqual(rx[0][IP].src, "1.1.1.1")
676 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
678 @unittest.skipUnless(config.extended, "part of extended tests")
679 def test_bier_e2e_1024(self):
680 """ BIER end-to-end BSL:1024"""
681 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
683 @unittest.skipUnless(config.extended, "part of extended tests")
684 def test_bier_e2e_512(self):
685 """ BIER end-to-end BSL:512"""
686 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
688 @unittest.skipUnless(config.extended, "part of extended tests")
689 def test_bier_e2e_256(self):
690 """ BIER end-to-end BSL:256"""
691 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
693 @unittest.skipUnless(config.extended, "part of extended tests")
694 def test_bier_e2e_128(self):
695 """ BIER end-to-end BSL:128"""
696 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
698 def test_bier_e2e_64(self):
699 """ BIER end-to-end BSL:64"""
700 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
702 def test_bier_head_o_udp(self):
703 """BIER head over UDP"""
705 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
706 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
709 # Add a BIER table for sub-domain 1, set 0, and BSL 256
711 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
712 bt = VppBierTable(self, bti, 77)
716 # 1 bit positions via 1 next hops
719 ip_route = VppIpRoute(self, nh1, 32,
720 [VppRoutePath(self.pg1.remote_ip4,
721 self.pg1.sw_if_index,
722 labels=[VppMplsLabel(2001)])])
723 ip_route.add_vpp_config()
725 udp_encap = VppUdpEncap(self,
729 udp_encap.add_vpp_config()
731 bier_route = VppBierRoute(
733 [VppRoutePath("0.0.0.0",
735 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
736 next_hop_id=udp_encap.id)])
737 bier_route.add_vpp_config()
740 # An 2 imposition objects with all bit-positions set
741 # only use the second, but creating 2 tests with a non-zero
742 # value index in the route add
744 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
746 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
750 # Add a multicast route that will forward into the BIER doamin
752 route_ing_232_1_1_1 = VppIpMRoute(
756 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
757 paths=[VppMRoutePath(self.pg0.sw_if_index,
758 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
759 VppMRoutePath(0xffffffff,
760 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
761 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
762 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
763 bier_imp=bi2.bi_index)])
764 route_ing_232_1_1_1.add_vpp_config()
767 # inject a packet an IP. We expect it to be BIER and UDP encapped,
769 p = (Ether(dst=self.pg0.local_mac,
770 src=self.pg0.remote_mac) /
771 IP(src="1.1.1.1", dst="232.1.1.1") /
772 UDP(sport=1234, dport=1234))
774 self.pg0.add_stream([p])
775 self.pg_enable_capture(self.pg_interfaces)
778 rx = self.pg1.get_capture(1)
781 # Encap Stack is, eth, IP, UDP, BIFT, BIER
783 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
784 self.assertEqual(rx[0][IP].dst, nh1)
785 self.assertEqual(rx[0][UDP].sport, 330)
786 self.assertEqual(rx[0][UDP].dport, 8138)
787 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
788 self.assertEqual(rx[0][BIFT].sd, 1)
789 self.assertEqual(rx[0][BIFT].set, 0)
790 self.assertEqual(rx[0][BIFT].ttl, 64)
791 self.assertEqual(rx[0][BIER].length, 2)
793 def test_bier_tail_o_udp(self):
794 """BIER Tail over UDP"""
796 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
797 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
800 # Add a BIER table for sub-domain 0, set 0, and BSL 256
802 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
803 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
809 bdt = VppBierDispTable(self, 8)
813 # BIER route in table that's for-us
815 bier_route_1 = VppBierRoute(
817 [VppRoutePath("0.0.0.0",
819 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
821 bier_route_1.add_vpp_config()
824 # An entry in the disposition table
826 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
827 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
828 FibPathProto.FIB_PATH_NH_PROTO_BIER,
829 "0.0.0.0", 0, rpf_id=8192)
830 bier_de_1.add_vpp_config()
833 # A multicast route to forward post BIER disposition
835 route_eg_232_1_1_1 = VppIpMRoute(
839 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
840 paths=[VppMRoutePath(self.pg1.sw_if_index,
841 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
842 route_eg_232_1_1_1.add_vpp_config()
843 route_eg_232_1_1_1.update_rpf_id(8192)
846 # A packet with all bits set gets spat out to BP:1
848 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
849 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
850 UDP(sport=333, dport=8138) /
851 BIFT(sd=1, set=0, bsl=2, ttl=255) /
852 BIER(length=BIERLength.BIER_LEN_256,
853 BitString=scapy.compat.chb(255)*32,
855 IP(src="1.1.1.1", dst="232.1.1.1") /
856 UDP(sport=1234, dport=1234) /
859 rx = self.send_and_expect(self.pg0, [p], self.pg1)
862 if __name__ == '__main__':
863 unittest.main(testRunner=VppTestRunner)