blob: 5a2c51c17086ca45426917ffa20a461b58e44a77 [file] [log] [blame]
Neale Rannsd792d9c2017-10-21 10:53:20 -07001#!/usr/bin/env python
2
3import unittest
Neale Rannsd792d9c2017-10-21 10:53:20 -07004
Neale Rannsf0510722018-01-31 11:35:41 -08005from framework import VppTestCase, VppTestRunner, running_extended_tests
Neale Rannsc0a93142018-09-05 15:42:26 -07006from vpp_ip import DpoProto
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -08007from vpp_ip_route import VppIpRoute, VppRoutePath, \
Neale Rannsd792d9c2017-10-21 10:53:20 -07008 VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \
Neale Rannsc0a93142018-09-05 15:42:26 -07009 MRouteEntryFlags, MRouteItfFlags, MPLS_LABEL_INVALID, \
Neale Ranns31ed7442018-02-23 05:29:09 -080010 VppMplsLabel
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080011from vpp_bier import BIER_HDR_PAYLOAD, VppBierImp, VppBierDispEntry, \
12 VppBierDispTable, VppBierTable, VppBierTableID, VppBierRoute
13from vpp_udp_encap import VppUdpEncap
Neale Rannsd792d9c2017-10-21 10:53:20 -070014
15from scapy.packet import Raw
16from scapy.layers.l2 import Ether
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080017from scapy.layers.inet import IP, UDP
Neale Rannsd792d9c2017-10-21 10:53:20 -070018from scapy.layers.inet6 import IPv6
19from scapy.contrib.mpls import MPLS
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080020from scapy.contrib.bier import BIER, BIERLength, BIFT
Neale Rannsd792d9c2017-10-21 10:53:20 -070021
22
23class 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
35class 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
Neale Rannsf0510722018-01-31 11:35:41 -080071 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
Neale Rannsd792d9c2017-10-21 10:53:20 -070072 """BIER midpoint"""
73
74 #
75 # Add a BIER table for sub-domain 0, set 0, and BSL 256
76 #
Neale Rannsf0510722018-01-31 11:35:41 -080077 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -070078 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) /
Neale Rannsf0510722018-01-31 11:35:41 -080086 BIER(length=hdr_len_id) /
Neale Rannsd792d9c2017-10-21 10:53:20 -070087 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 = []
Neale Rannsf0510722018-01-31 11:35:41 -0800102 for i in range(1, max_bp+1):
Neale Rannsd792d9c2017-10-21 10:53:20 -0700103 nh = "10.0.%d.%d" % (i / 255, i % 255)
Neale Ranns31ed7442018-02-23 05:29:09 -0800104 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)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700109 nh_routes[-1].add_vpp_config()
110
Neale Ranns31ed7442018-02-23 05:29:09 -0800111 bier_routes.append(
112 VppBierRoute(self, bti, i,
113 [VppRoutePath(nh, 0xffffffff,
114 labels=[VppMplsLabel(100+i)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700115 bier_routes[-1].add_vpp_config()
116
117 #
Neale Rannsf0510722018-01-31 11:35:41 -0800118 # A packet with all bits set gets replicated once for each bit
Neale Rannsd792d9c2017-10-21 10:53:20 -0700119 #
Neale Rannsf0510722018-01-31 11:35:41 -0800120 pkt_sizes = [64, 1400]
Neale Rannsd792d9c2017-10-21 10:53:20 -0700121
Neale Rannsf0510722018-01-31 11:35:41 -0800122 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
Neale Rannsd792d9c2017-10-21 10:53:20 -0700130
Neale Rannsf0510722018-01-31 11:35:41 -0800131 self.pg0.add_stream(pkts)
132 self.pg_enable_capture(self.pg_interfaces)
133 self.pg_start()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700134
Neale Rannsf0510722018-01-31 11:35:41 -0800135 rx = self.pg1.get_capture(max_bp)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700136
Neale Rannsf0510722018-01-31 11:35:41 -0800137 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
Neale Rannsd792d9c2017-10-21 10:53:20 -0700145
Neale Rannsf0510722018-01-31 11:35:41 -0800146 blabel = olabel[MPLS].payload
147 self.assertEqual(blabel.label, 100+bp)
148 self.assertEqual(blabel.ttl, 254)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700149
Neale Rannsf0510722018-01-31 11:35:41 -0800150 bier_hdr = blabel[MPLS].payload
Neale Rannsd792d9c2017-10-21 10:53:20 -0700151
Neale Rannsf0510722018-01-31 11:35:41 -0800152 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)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700160
Neale Rannsf0510722018-01-31 11:35:41 -0800161 # 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)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700167
Neale Rannsf0510722018-01-31 11:35:41 -0800168 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
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800181 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800182 def test_bier_midpoint_1024(self):
183 """BIER midpoint BSL:1024"""
184 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
185
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800186 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800187 def test_bier_midpoint_512(self):
188 """BIER midpoint BSL:512"""
189 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
190
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800191 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800192 def test_bier_midpoint_256(self):
193 """BIER midpoint BSL:256"""
194 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
195
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800196 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800197 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):
Neale Rannsc819fc62018-02-16 02:44:05 -0800202 """BIER midpoint BSL:64"""
Neale Rannsf0510722018-01-31 11:35:41 -0800203 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700204
Neale Rannsef90ed02018-09-13 08:45:12 -0700205 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
Neale Rannsd792d9c2017-10-21 10:53:20 -0700299 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,
Neale Ranns31ed7442018-02-23 05:29:09 -0800317 labels=[VppMplsLabel(2001)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700318 ip_route_2 = VppIpRoute(self, nh2, 32,
319 [VppRoutePath(self.pg1.remote_ip4,
320 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800321 labels=[VppMplsLabel(2002)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700322 ip_route_1.add_vpp_config()
323 ip_route_2.add_vpp_config()
324
Neale Ranns91286372017-12-05 13:24:04 -0800325 bier_route_1 = VppBierRoute(self, bti, 1,
326 [VppRoutePath(nh1, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800327 labels=[VppMplsLabel(101)])])
Neale Ranns91286372017-12-05 13:24:04 -0800328 bier_route_2 = VppBierRoute(self, bti, 2,
329 [VppRoutePath(nh2, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800330 labels=[VppMplsLabel(102)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700331 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 #
Neale Ranns91286372017-12-05 13:24:04 -0800357 # inject an IP packet. We expect it to be BIER encapped and
Neale Rannsd792d9c2017-10-21 10:53:20 -0700358 # 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
Neale Ranns91286372017-12-05 13:24:04 -0800371 #
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
Neale Rannsd792d9c2017-10-21 10:53:20 -0700394 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 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800413 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)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700419 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,
Neale Rannsf0510722018-01-31 11:35:41 -0800426 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700427 "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) /
Neale Rannsf0510722018-01-31 11:35:41 -0800448 BIER(length=BIERLength.BIER_LEN_256,
449 BitString=chr(255)*32,
450 BFRID=99) /
Neale Rannsd792d9c2017-10-21 10:53:20 -0700451 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
Neale Rannsceb4d052017-12-13 09:13:41 -0800457 #
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) /
Neale Rannsf0510722018-01-31 11:35:41 -0800462 BIER(length=BIERLength.BIER_LEN_256,
463 BitString=chr(255)*32,
464 BFRID=77) /
Neale Rannsceb4d052017-12-13 09:13:41 -0800465 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,
Neale Rannsf0510722018-01-31 11:35:41 -0800476 DpoProto.DPO_PROTO_BIER,
Neale Rannsceb4d052017-12-13 09:13:41 -0800477 "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
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700485 #
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
Neale Rannsf0510722018-01-31 11:35:41 -0800516 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
517 """ BIER end-to-end"""
Neale Rannsd792d9c2017-10-21 10:53:20 -0700518
519 #
520 # Add a BIER table for sub-domain 0, set 0, and BSL 256
521 #
Neale Rannsf0510722018-01-31 11:35:41 -0800522 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700523 bt = VppBierTable(self, bti, 77)
524 bt.add_vpp_config()
525
Neale Rannsf0510722018-01-31 11:35:41 -0800526 lowest = ['\0'] * (n_bytes)
527 lowest[-1] = chr(1)
528 highest = ['\0'] * (n_bytes)
529 highest[0] = chr(128)
530
Neale Rannsd792d9c2017-10-21 10:53:20 -0700531 #
Neale Rannsf0510722018-01-31 11:35:41 -0800532 # Impostion Sets bit strings
Neale Rannsd792d9c2017-10-21 10:53:20 -0700533 #
Neale Rannsf0510722018-01-31 11:35:41 -0800534 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()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700538
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,
Neale Rannsf0510722018-01-31 11:35:41 -0800552 bier_imp=bi_low.bi_index)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700553 route_ing_232_1_1_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800554 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()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700566
567 #
568 # disposition table 8
569 #
570 bdt = VppBierDispTable(self, 8)
571 bdt.add_vpp_config()
572
573 #
Neale Rannsf0510722018-01-31 11:35:41 -0800574 # BIER routes in table that are for-us, resolving through
Neale Rannsd792d9c2017-10-21 10:53:20 -0700575 # disp table 8.
576 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800577 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)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700583 bier_route_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800584 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()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700589
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,
Neale Rannsf0510722018-01-31 11:35:41 -0800596 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700597 "0.0.0.0", 10, rpf_id=8192)
598 bier_de_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800599 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()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700604
605 #
Neale Rannsf0510722018-01-31 11:35:41 -0800606 # Add a multicast routes that will forward the traffic
Neale Rannsd792d9c2017-10-21 10:53:20 -0700607 # 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)
Neale Rannsf0510722018-01-31 11:35:41 -0800619 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)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700629
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") /
Neale Rannsf0510722018-01-31 11:35:41 -0800638 UDP(sport=1234, dport=1234) /
639 Raw(chr(5) * 32))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700640
Neale Ranns91286372017-12-05 13:24:04 -0800641 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
642
Neale Ranns91286372017-12-05 13:24:04 -0800643 self.assertEqual(rx[0][IP].src, "1.1.1.1")
644 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
645
Neale Rannsf0510722018-01-31 11:35:41 -0800646 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
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800656 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800657 def test_bier_e2e_1024(self):
658 """ BIER end-to-end BSL:1024"""
659 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
660
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800661 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800662 def test_bier_e2e_512(self):
663 """ BIER end-to-end BSL:512"""
664 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
665
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800666 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800667 def test_bier_e2e_256(self):
668 """ BIER end-to-end BSL:256"""
669 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
670
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800671 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800672 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
Neale Ranns91286372017-12-05 13:24:04 -0800680 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,
Neale Ranns31ed7442018-02-23 05:29:09 -0800697 labels=[VppMplsLabel(2001)])])
Neale Ranns91286372017-12-05 13:24:04 -0800698 ip_route.add_vpp_config()
699
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700700 udp_encap = VppUdpEncap(self,
Neale Ranns91286372017-12-05 13:24:04 -0800701 self.pg0.local_ip4,
702 nh1,
703 330, 8138)
704 udp_encap.add_vpp_config()
705
Neale Ranns2303cb12018-02-21 04:57:17 -0800706 bier_route = VppBierRoute(
707 self, bti, 1,
708 [VppRoutePath("0.0.0.0",
709 0xFFFFFFFF,
710 is_udp_encap=1,
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700711 next_hop_id=udp_encap.id)])
Neale Ranns91286372017-12-05 13:24:04 -0800712 bier_route.add_vpp_config()
713
714 #
Neale Rannseea537a2018-01-09 04:11:28 -0800715 # 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
Neale Ranns91286372017-12-05 13:24:04 -0800718 #
719 bi = VppBierImp(self, bti, 333, chr(0xff) * 32)
720 bi.add_vpp_config()
Neale Rannseea537a2018-01-09 04:11:28 -0800721 bi2 = VppBierImp(self, bti, 334, chr(0xff) * 32)
722 bi2.add_vpp_config()
Neale Ranns91286372017-12-05 13:24:04 -0800723
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,
Neale Rannseea537a2018-01-09 04:11:28 -0800737 bier_imp=bi2.bi_index)])
Neale Ranns91286372017-12-05 13:24:04 -0800738 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)
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700761 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
Neale Ranns91286372017-12-05 13:24:04 -0800762 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 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800786 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)])
Neale Ranns91286372017-12-05 13:24:04 -0800792 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,
Neale Rannsf0510722018-01-31 11:35:41 -0800799 DpoProto.DPO_PROTO_BIER,
Neale Ranns91286372017-12-05 13:24:04 -0800800 "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) /
Neale Rannsf0510722018-01-31 11:35:41 -0800823 BIER(length=BIERLength.BIER_LEN_256,
824 BitString=chr(255)*32,
825 BFRID=99) /
Neale Ranns91286372017-12-05 13:24:04 -0800826 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)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700831
832
833if __name__ == '__main__':
834 unittest.main(testRunner=VppTestRunner)