MAP: Convert from DPO to input feature.
[vpp.git] / test / test_bier.py
1 #!/usr/bin/env python
2
3 import unittest
4 import socket
5
6 from framework import VppTestCase, VppTestRunner, running_extended_tests
7 from vpp_ip import DpoProto
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
9     VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \
10     MRouteEntryFlags, MRouteItfFlags, MPLS_LABEL_INVALID, \
11     VppMplsLabel
12 from vpp_bier import *
13 from vpp_udp_encap import *
14
15 from scapy.packet import Raw
16 from scapy.layers.l2 import Ether
17 from scapy.layers.inet import IP, UDP, ICMP
18 from scapy.layers.inet6 import IPv6
19 from scapy.contrib.mpls import MPLS
20 from scapy.contrib.bier import *
21
22
23 class TestBFIB(VppTestCase):
24     """ BIER FIB Test Case """
25
26     def test_bfib(self):
27         """ BFIB Unit Tests """
28         error = self.vapi.cli("test bier")
29
30         if error:
31             self.logger.critical(error)
32         self.assertEqual(error.find("Failed"), -1)
33
34
35 class TestBier(VppTestCase):
36     """ BIER Test Case """
37
38     def setUp(self):
39         super(TestBier, self).setUp()
40
41         # create 2 pg interfaces
42         self.create_pg_interfaces(range(3))
43
44         # create the default MPLS table
45         self.tables = []
46         tbl = VppMplsTable(self, 0)
47         tbl.add_vpp_config()
48         self.tables.append(tbl)
49
50         tbl = VppIpTable(self, 10)
51         tbl.add_vpp_config()
52         self.tables.append(tbl)
53
54         # setup both interfaces
55         for i in self.pg_interfaces:
56             if i == self.pg2:
57                 i.set_table_ip4(10)
58             i.admin_up()
59             i.config_ip4()
60             i.resolve_arp()
61             i.enable_mpls()
62
63     def tearDown(self):
64         for i in self.pg_interfaces:
65             i.disable_mpls()
66             i.unconfig_ip4()
67             i.set_table_ip4(0)
68             i.admin_down()
69         super(TestBier, self).tearDown()
70
71     def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
72         """BIER midpoint"""
73
74         #
75         # Add a BIER table for sub-domain 0, set 0, and BSL 256
76         #
77         bti = VppBierTableID(0, 0, hdr_len_id)
78         bt = VppBierTable(self, bti, 77)
79         bt.add_vpp_config()
80
81         #
82         # A packet with no bits set gets dropped
83         #
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) /
89              Raw())
90         pkts = [p]
91
92         self.send_and_assert_no_replies(self.pg0, pkts,
93                                         "Empty Bit-String")
94
95         #
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.
99         #
100         nh_routes = []
101         bier_routes = []
102         for i in range(1, max_bp+1):
103             nh = "10.0.%d.%d" % (i / 255, i % 255)
104             nh_routes.append(
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()
110
111             bier_routes.append(
112                 VppBierRoute(self, bti, i,
113                              [VppRoutePath(nh, 0xffffffff,
114                                            labels=[VppMplsLabel(100+i)])]))
115             bier_routes[-1].add_vpp_config()
116
117         #
118         # A packet with all bits set gets replicated once for each bit
119         #
120         pkt_sizes = [64, 1400]
121
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))
129             pkts = p
130
131             self.pg0.add_stream(pkts)
132             self.pg_enable_capture(self.pg_interfaces)
133             self.pg_start()
134
135             rx = self.pg1.get_capture(max_bp)
136
137             for rxp in rx:
138                 #
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
142                 #
143                 olabel = rxp[MPLS]
144                 bp = olabel.label - 2000
145
146                 blabel = olabel[MPLS].payload
147                 self.assertEqual(blabel.label, 100+bp)
148                 self.assertEqual(blabel.ttl, 254)
149
150                 bier_hdr = blabel[MPLS].payload
151
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)
160
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)
167
168                 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
169                 self.assertEqual(bitstring, bier_hdr.BitString)
170
171         #
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
175         #
176         for br in bier_routes:
177             br.remove_vpp_config()
178         for nhr in nh_routes:
179             nhr.remove_vpp_config()
180
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)
185
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)
190
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)
195
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)
200
201     def test_bier_midpoint_64(self):
202         """BIER midpoint BSL:64"""
203         self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
204
205     def test_bier_load_balance(self):
206         """BIER load-balance"""
207
208         #
209         # Add a BIER table for sub-domain 0, set 0, and BSL 256
210         #
211         bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
212         bt = VppBierTable(self, bti, 77)
213         bt.add_vpp_config()
214
215         #
216         # packets with varying entropy
217         #
218         pkts = []
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,
224                               entropy=ii,
225                               BitString=chr(255)*16) /
226                          IPv6(src=self.pg0.remote_ip6,
227                               dst=self.pg0.remote_ip6) /
228                          UDP(sport=1234, dport=1234) /
229                          Raw()))
230
231         #
232         # 4 next hops
233         #
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}]
238
239         for nh in nhs:
240             ipr = VppIpRoute(
241                 self, nh['ip'], 32,
242                 [VppRoutePath(self.pg1.remote_ip4,
243                               self.pg1.sw_if_index,
244                               labels=[VppMplsLabel(nh['label'])])])
245             ipr.add_vpp_config()
246
247         bier_route = VppBierRoute(
248             self, bti, 1,
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()
254
255         rx = self.send_and_expect(self.pg0, pkts, self.pg1)
256
257         #
258         # we should have recieved a packet from each neighbor
259         #
260         for nh in nhs[:2]:
261             self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
262
263         #
264         # add the other paths
265         #
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)])])
275
276         rx = self.send_and_expect(self.pg0, pkts, self.pg1)
277         for nh in nhs:
278             self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
279
280         #
281         # remove first two paths
282         #
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)]))
287
288         rx = self.send_and_expect(self.pg0, pkts, self.pg1)
289         for nh in nhs[2:]:
290             self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
291
292         #
293         # remove the last of the paths, deleteing the entry
294         #
295         bier_route.remove_all_paths()
296
297         self.send_and_assert_no_replies(self.pg0, pkts)
298
299     def test_bier_head(self):
300         """BIER head"""
301
302         #
303         # Add a BIER table for sub-domain 0, set 0, and BSL 256
304         #
305         bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
306         bt = VppBierTable(self, bti, 77)
307         bt.add_vpp_config()
308
309         #
310         # 2 bit positions via two next hops
311         #
312         nh1 = "10.0.0.1"
313         nh2 = "10.0.0.2"
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()
324
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()
333
334         #
335         # An imposition object with both bit-positions set
336         #
337         bi = VppBierImp(self, bti, 333, chr(0x3) * 32)
338         bi.add_vpp_config()
339
340         #
341         # Add a multicast route that will forward into the BIER doamin
342         #
343         route_ing_232_1_1_1 = VppIpMRoute(
344             self,
345             "0.0.0.0",
346             "232.1.1.1", 32,
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()
355
356         #
357         # inject an IP packet. We expect it to be BIER encapped and
358         # replicated.
359         #
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))
364
365         self.pg0.add_stream([p])
366         self.pg_enable_capture(self.pg_interfaces)
367         self.pg_start()
368
369         rx = self.pg1.get_capture(2)
370
371         #
372         # Encap Stack is; eth, MPLS, MPLS, BIER
373         #
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)
383
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)
393
394     def test_bier_tail(self):
395         """BIER Tail"""
396
397         #
398         # Add a BIER table for sub-domain 0, set 0, and BSL 256
399         #
400         bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
401         bt = VppBierTable(self, bti, 77)
402         bt.add_vpp_config()
403
404         #
405         # disposition table
406         #
407         bdt = VppBierDispTable(self, 8)
408         bdt.add_vpp_config()
409
410         #
411         # BIER route in table that's for-us
412         #
413         bier_route_1 = VppBierRoute(
414             self, bti, 1,
415             [VppRoutePath("0.0.0.0",
416                           0xffffffff,
417                           proto=DpoProto.DPO_PROTO_BIER,
418                           nh_table_id=8)])
419         bier_route_1.add_vpp_config()
420
421         #
422         # An entry in the disposition table
423         #
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()
429
430         #
431         # A multicast route to forward post BIER disposition
432         #
433         route_eg_232_1_1_1 = VppIpMRoute(
434             self,
435             "0.0.0.0",
436             "232.1.1.1", 32,
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)
442
443         #
444         # A packet with all bits set gets spat out to BP:1
445         #
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,
450                   BFRID=99) /
451              IP(src="1.1.1.1", dst="232.1.1.1") /
452              UDP(sport=1234, dport=1234) /
453              Raw())
454
455         self.send_and_expect(self.pg0, [p], self.pg1)
456
457         #
458         # A packet that does not match the Disposition entry gets dropped
459         #
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,
464                   BFRID=77) /
465              IP(src="1.1.1.1", dst="232.1.1.1") /
466              UDP(sport=1234, dport=1234) /
467              Raw())
468         self.send_and_assert_no_replies(self.pg0, p*2,
469                                         "no matching disposition entry")
470
471         #
472         # Add the default route to the disposition table
473         #
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()
479
480         #
481         # now the previous packet is forwarded
482         #
483         self.send_and_expect(self.pg0, [p], self.pg1)
484
485         #
486         # A multicast route to forward post BIER disposition that needs
487         # a check against sending back into the BIER core
488         #
489         bi = VppBierImp(self, bti, 333, chr(0x3) * 32)
490         bi.add_vpp_config()
491
492         route_eg_232_1_1_2 = VppIpMRoute(
493             self,
494             "0.0.0.0",
495             "232.1.1.2", 32,
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)
505
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,
510                   BFRID=77) /
511              IP(src="1.1.1.1", dst="232.1.1.2") /
512              UDP(sport=1234, dport=1234) /
513              Raw())
514         self.send_and_expect(self.pg0, [p], self.pg1)
515
516     def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
517         """ BIER end-to-end"""
518
519         #
520         # Add a BIER table for sub-domain 0, set 0, and BSL 256
521         #
522         bti = VppBierTableID(0, 0, hdr_len_id)
523         bt = VppBierTable(self, bti, 77)
524         bt.add_vpp_config()
525
526         lowest = ['\0'] * (n_bytes)
527         lowest[-1] = chr(1)
528         highest = ['\0'] * (n_bytes)
529         highest[0] = chr(128)
530
531         #
532         # Impostion Sets bit strings
533         #
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()
538
539         #
540         # Add a multicast route that will forward into the BIER doamin
541         #
542         route_ing_232_1_1_1 = VppIpMRoute(
543             self,
544             "0.0.0.0",
545             "232.1.1.1", 32,
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(
555             self,
556             "0.0.0.0",
557             "232.1.1.2", 32,
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()
566
567         #
568         # disposition table 8
569         #
570         bdt = VppBierDispTable(self, 8)
571         bdt.add_vpp_config()
572
573         #
574         # BIER routes in table that are for-us, resolving through
575         # disp table 8.
576         #
577         bier_route_1 = VppBierRoute(
578             self, bti, 1,
579             [VppRoutePath("0.0.0.0",
580                           0xffffffff,
581                           proto=DpoProto.DPO_PROTO_BIER,
582                           nh_table_id=8)])
583         bier_route_1.add_vpp_config()
584         bier_route_max = VppBierRoute(self, bti, max_bp,
585                                       [VppRoutePath("0.0.0.0",
586                                                     0xffffffff,
587                                                     nh_table_id=8)])
588         bier_route_max.add_vpp_config()
589
590         #
591         # An entry in the disposition table for sender 333
592         #  lookup in VRF 10
593         #
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()
604
605         #
606         # Add a multicast routes that will forward the traffic
607         # post-disposition
608         #
609         route_eg_232_1_1_1 = VppIpMRoute(
610             self,
611             "0.0.0.0",
612             "232.1.1.1", 32,
613             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
614             table_id=10,
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(
620             self,
621             "0.0.0.0",
622             "232.1.1.2", 32,
623             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
624             table_id=10,
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)
629
630         #
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
634         #
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) /
639              Raw(chr(5) * 32))
640
641         rx = self.send_and_expect(self.pg0, p*65, self.pg1)
642
643         self.assertEqual(rx[0][IP].src, "1.1.1.1")
644         self.assertEqual(rx[0][IP].dst, "232.1.1.1")
645
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) /
650              Raw(chr(5) * 512))
651
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")
655
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)
660
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)
665
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)
670
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)
675
676     def test_bier_e2e_64(self):
677         """ BIER end-to-end BSL:64"""
678         self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
679
680     def test_bier_head_o_udp(self):
681         """BIER head over UDP"""
682
683         #
684         # Add a BIER table for sub-domain 1, set 0, and BSL 256
685         #
686         bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
687         bt = VppBierTable(self, bti, 77)
688         bt.add_vpp_config()
689
690         #
691         # 1 bit positions via 1 next hops
692         #
693         nh1 = "10.0.0.1"
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()
699
700         udp_encap = VppUdpEncap(self,
701                                 self.pg0.local_ip4,
702                                 nh1,
703                                 330, 8138)
704         udp_encap.add_vpp_config()
705
706         bier_route = VppBierRoute(
707             self, bti, 1,
708             [VppRoutePath("0.0.0.0",
709                           0xFFFFFFFF,
710                           is_udp_encap=1,
711                           next_hop_id=udp_encap.id)])
712         bier_route.add_vpp_config()
713
714         #
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
718         #
719         bi = VppBierImp(self, bti, 333, chr(0xff) * 32)
720         bi.add_vpp_config()
721         bi2 = VppBierImp(self, bti, 334, chr(0xff) * 32)
722         bi2.add_vpp_config()
723
724         #
725         # Add a multicast route that will forward into the BIER doamin
726         #
727         route_ing_232_1_1_1 = VppIpMRoute(
728             self,
729             "0.0.0.0",
730             "232.1.1.1", 32,
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()
739
740         #
741         # inject a packet an IP. We expect it to be BIER and UDP encapped,
742         #
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))
747
748         self.pg0.add_stream([p])
749         self.pg_enable_capture(self.pg_interfaces)
750         self.pg_start()
751
752         rx = self.pg1.get_capture(1)
753
754         #
755         # Encap Stack is, eth, IP, UDP, BIFT, BIER
756         #
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)
766
767     def test_bier_tail_o_udp(self):
768         """BIER Tail over UDP"""
769
770         #
771         # Add a BIER table for sub-domain 0, set 0, and BSL 256
772         #
773         bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
774         bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
775         bt.add_vpp_config()
776
777         #
778         # disposition table
779         #
780         bdt = VppBierDispTable(self, 8)
781         bdt.add_vpp_config()
782
783         #
784         # BIER route in table that's for-us
785         #
786         bier_route_1 = VppBierRoute(
787             self, bti, 1,
788             [VppRoutePath("0.0.0.0",
789                           0xffffffff,
790                           proto=DpoProto.DPO_PROTO_BIER,
791                           nh_table_id=8)])
792         bier_route_1.add_vpp_config()
793
794         #
795         # An entry in the disposition table
796         #
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()
802
803         #
804         # A multicast route to forward post BIER disposition
805         #
806         route_eg_232_1_1_1 = VppIpMRoute(
807             self,
808             "0.0.0.0",
809             "232.1.1.1", 32,
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)
815
816         #
817         # A packet with all bits set gets spat out to BP:1
818         #
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,
825                   BFRID=99) /
826              IP(src="1.1.1.1", dst="232.1.1.1") /
827              UDP(sport=1234, dport=1234) /
828              Raw())
829
830         rx = self.send_and_expect(self.pg0, [p], self.pg1)
831
832
833 if __name__ == '__main__':
834     unittest.main(testRunner=VppTestRunner)