blob: b8130ce93f2408218c86394cfb66ff2122bdda91 [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
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Rannsd792d9c2017-10-21 10:53:20 -070016from scapy.packet import Raw
17from scapy.layers.l2 import Ether
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080018from scapy.layers.inet import IP, UDP
Neale Rannsd792d9c2017-10-21 10:53:20 -070019from scapy.layers.inet6 import IPv6
20from scapy.contrib.mpls import MPLS
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080021from scapy.contrib.bier import BIER, BIERLength, BIFT
Neale Rannsd792d9c2017-10-21 10:53:20 -070022
Paul Vinciguerra4271c972019-05-14 13:25:49 -040023NUM_PKTS = 67
24
Neale Rannsd792d9c2017-10-21 10:53:20 -070025
26class TestBFIB(VppTestCase):
27 """ BIER FIB Test Case """
28
29 def test_bfib(self):
30 """ BFIB Unit Tests """
31 error = self.vapi.cli("test bier")
32
33 if error:
34 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -080035 self.assertNotIn("Failed", error)
Neale Rannsd792d9c2017-10-21 10:53:20 -070036
37
38class TestBier(VppTestCase):
39 """ BIER Test Case """
40
41 def setUp(self):
42 super(TestBier, self).setUp()
43
44 # create 2 pg interfaces
45 self.create_pg_interfaces(range(3))
46
47 # create the default MPLS table
48 self.tables = []
49 tbl = VppMplsTable(self, 0)
50 tbl.add_vpp_config()
51 self.tables.append(tbl)
52
53 tbl = VppIpTable(self, 10)
54 tbl.add_vpp_config()
55 self.tables.append(tbl)
56
57 # setup both interfaces
58 for i in self.pg_interfaces:
59 if i == self.pg2:
60 i.set_table_ip4(10)
61 i.admin_up()
62 i.config_ip4()
63 i.resolve_arp()
64 i.enable_mpls()
65
66 def tearDown(self):
67 for i in self.pg_interfaces:
68 i.disable_mpls()
69 i.unconfig_ip4()
70 i.set_table_ip4(0)
71 i.admin_down()
72 super(TestBier, self).tearDown()
73
Neale Rannsf0510722018-01-31 11:35:41 -080074 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
Neale Rannsd792d9c2017-10-21 10:53:20 -070075 """BIER midpoint"""
76
77 #
78 # Add a BIER table for sub-domain 0, set 0, and BSL 256
79 #
Neale Rannsf0510722018-01-31 11:35:41 -080080 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -070081 bt = VppBierTable(self, bti, 77)
82 bt.add_vpp_config()
83
84 #
85 # A packet with no bits set gets dropped
86 #
87 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
88 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -080089 BIER(length=hdr_len_id) /
Neale Rannsd792d9c2017-10-21 10:53:20 -070090 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
91 UDP(sport=1234, dport=1234) /
92 Raw())
93 pkts = [p]
94
95 self.send_and_assert_no_replies(self.pg0, pkts,
96 "Empty Bit-String")
97
98 #
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.
102 #
103 nh_routes = []
104 bier_routes = []
Neale Rannsf0510722018-01-31 11:35:41 -0800105 for i in range(1, max_bp+1):
Neale Rannsd792d9c2017-10-21 10:53:20 -0700106 nh = "10.0.%d.%d" % (i / 255, i % 255)
Neale Ranns31ed7442018-02-23 05:29:09 -0800107 nh_routes.append(
108 VppIpRoute(self, nh, 32,
109 [VppRoutePath(self.pg1.remote_ip4,
110 self.pg1.sw_if_index,
111 labels=[VppMplsLabel(2000+i)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700112 nh_routes[-1].add_vpp_config()
113
Neale Ranns31ed7442018-02-23 05:29:09 -0800114 bier_routes.append(
115 VppBierRoute(self, bti, i,
116 [VppRoutePath(nh, 0xffffffff,
117 labels=[VppMplsLabel(100+i)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700118 bier_routes[-1].add_vpp_config()
119
120 #
Neale Rannsf0510722018-01-31 11:35:41 -0800121 # A packet with all bits set gets replicated once for each bit
Neale Rannsd792d9c2017-10-21 10:53:20 -0700122 #
Neale Rannsf0510722018-01-31 11:35:41 -0800123 pkt_sizes = [64, 1400]
Neale Rannsd792d9c2017-10-21 10:53:20 -0700124
Neale Rannsf0510722018-01-31 11:35:41 -0800125 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) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700128 BIER(length=hdr_len_id,
129 BitString=scapy.compat.chb(255)*n_bytes) /
Neale Rannsf0510722018-01-31 11:35:41 -0800130 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
131 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700132 Raw(scapy.compat.chb(5) * pkt_size))
Neale Rannsf0510722018-01-31 11:35:41 -0800133 pkts = p
Neale Rannsd792d9c2017-10-21 10:53:20 -0700134
Neale Rannsf0510722018-01-31 11:35:41 -0800135 self.pg0.add_stream(pkts)
136 self.pg_enable_capture(self.pg_interfaces)
137 self.pg_start()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700138
Neale Rannsf0510722018-01-31 11:35:41 -0800139 rx = self.pg1.get_capture(max_bp)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700140
Neale Rannsf0510722018-01-31 11:35:41 -0800141 for rxp in rx:
142 #
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
146 #
147 olabel = rxp[MPLS]
148 bp = olabel.label - 2000
Neale Rannsd792d9c2017-10-21 10:53:20 -0700149
Neale Rannsf0510722018-01-31 11:35:41 -0800150 blabel = olabel[MPLS].payload
151 self.assertEqual(blabel.label, 100+bp)
152 self.assertEqual(blabel.ttl, 254)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700153
Neale Rannsf0510722018-01-31 11:35:41 -0800154 bier_hdr = blabel[MPLS].payload
Neale Rannsd792d9c2017-10-21 10:53:20 -0700155
Neale Rannsf0510722018-01-31 11:35:41 -0800156 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)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700164
Neale Rannsf0510722018-01-31 11:35:41 -0800165 # The bit-string should consist only of the BP given by i.
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700166 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)
Neale Rannsf0510722018-01-31 11:35:41 -0800169 byte_array[byte_pos] = byte_val
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700170 bitstring = ''.join([scapy.compat.chb(x) for x in byte_array])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700171
Neale Rannsf0510722018-01-31 11:35:41 -0800172 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
173 self.assertEqual(bitstring, bier_hdr.BitString)
174
175 #
176 # cleanup. not strictly necessary, but it's much quicker this way
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700177 # because the bier_fib_dump and ip_fib_dump will be empty when the
Neale Rannsf0510722018-01-31 11:35:41 -0800178 # auto-cleanup kicks in
179 #
180 for br in bier_routes:
181 br.remove_vpp_config()
182 for nhr in nh_routes:
183 nhr.remove_vpp_config()
184
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800185 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800186 def test_bier_midpoint_1024(self):
187 """BIER midpoint BSL:1024"""
188 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
189
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800190 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800191 def test_bier_midpoint_512(self):
192 """BIER midpoint BSL:512"""
193 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
194
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800195 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800196 def test_bier_midpoint_256(self):
197 """BIER midpoint BSL:256"""
198 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
199
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800200 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800201 def test_bier_midpoint_128(self):
202 """BIER midpoint BSL:128"""
203 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
204
205 def test_bier_midpoint_64(self):
Neale Rannsc819fc62018-02-16 02:44:05 -0800206 """BIER midpoint BSL:64"""
Neale Rannsf0510722018-01-31 11:35:41 -0800207 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700208
Neale Rannsef90ed02018-09-13 08:45:12 -0700209 def test_bier_load_balance(self):
210 """BIER load-balance"""
211
212 #
213 # Add a BIER table for sub-domain 0, set 0, and BSL 256
214 #
215 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
216 bt = VppBierTable(self, bti, 77)
217 bt.add_vpp_config()
218
219 #
220 # packets with varying entropy
221 #
222 pkts = []
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,
228 entropy=ii,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700229 BitString=scapy.compat.chb(255)*16) /
Neale Rannsef90ed02018-09-13 08:45:12 -0700230 IPv6(src=self.pg0.remote_ip6,
231 dst=self.pg0.remote_ip6) /
232 UDP(sport=1234, dport=1234) /
233 Raw()))
234
235 #
236 # 4 next hops
237 #
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}]
242
243 for nh in nhs:
244 ipr = VppIpRoute(
245 self, nh['ip'], 32,
246 [VppRoutePath(self.pg1.remote_ip4,
247 self.pg1.sw_if_index,
248 labels=[VppMplsLabel(nh['label'])])])
249 ipr.add_vpp_config()
250
251 bier_route = VppBierRoute(
252 self, bti, 1,
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()
258
259 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
260
261 #
262 # we should have recieved a packet from each neighbor
263 #
264 for nh in nhs[:2]:
265 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
266
267 #
268 # add the other paths
269 #
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)])])
279
280 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
281 for nh in nhs:
282 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
283
284 #
285 # remove first two paths
286 #
287 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
288 labels=[VppMplsLabel(101)]))
289 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
290 labels=[VppMplsLabel(101)]))
291
292 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
293 for nh in nhs[2:]:
294 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
295
296 #
297 # remove the last of the paths, deleteing the entry
298 #
299 bier_route.remove_all_paths()
300
301 self.send_and_assert_no_replies(self.pg0, pkts)
302
Neale Rannsd792d9c2017-10-21 10:53:20 -0700303 def test_bier_head(self):
304 """BIER head"""
305
306 #
307 # Add a BIER table for sub-domain 0, set 0, and BSL 256
308 #
309 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
310 bt = VppBierTable(self, bti, 77)
311 bt.add_vpp_config()
312
313 #
314 # 2 bit positions via two next hops
315 #
316 nh1 = "10.0.0.1"
317 nh2 = "10.0.0.2"
318 ip_route_1 = VppIpRoute(self, nh1, 32,
319 [VppRoutePath(self.pg1.remote_ip4,
320 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800321 labels=[VppMplsLabel(2001)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700322 ip_route_2 = VppIpRoute(self, nh2, 32,
323 [VppRoutePath(self.pg1.remote_ip4,
324 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800325 labels=[VppMplsLabel(2002)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700326 ip_route_1.add_vpp_config()
327 ip_route_2.add_vpp_config()
328
Neale Ranns91286372017-12-05 13:24:04 -0800329 bier_route_1 = VppBierRoute(self, bti, 1,
330 [VppRoutePath(nh1, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800331 labels=[VppMplsLabel(101)])])
Neale Ranns91286372017-12-05 13:24:04 -0800332 bier_route_2 = VppBierRoute(self, bti, 2,
333 [VppRoutePath(nh2, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800334 labels=[VppMplsLabel(102)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700335 bier_route_1.add_vpp_config()
336 bier_route_2.add_vpp_config()
337
338 #
339 # An imposition object with both bit-positions set
340 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700341 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700342 bi.add_vpp_config()
343
344 #
345 # Add a multicast route that will forward into the BIER doamin
346 #
347 route_ing_232_1_1_1 = VppIpMRoute(
348 self,
349 "0.0.0.0",
350 "232.1.1.1", 32,
351 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
352 paths=[VppMRoutePath(self.pg0.sw_if_index,
353 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
354 VppMRoutePath(0xffffffff,
355 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
356 proto=DpoProto.DPO_PROTO_BIER,
357 bier_imp=bi.bi_index)])
358 route_ing_232_1_1_1.add_vpp_config()
359
360 #
Neale Ranns91286372017-12-05 13:24:04 -0800361 # inject an IP packet. We expect it to be BIER encapped and
Neale Rannsd792d9c2017-10-21 10:53:20 -0700362 # replicated.
363 #
364 p = (Ether(dst=self.pg0.local_mac,
365 src=self.pg0.remote_mac) /
366 IP(src="1.1.1.1", dst="232.1.1.1") /
367 UDP(sport=1234, dport=1234))
368
369 self.pg0.add_stream([p])
370 self.pg_enable_capture(self.pg_interfaces)
371 self.pg_start()
372
373 rx = self.pg1.get_capture(2)
374
Neale Ranns91286372017-12-05 13:24:04 -0800375 #
376 # Encap Stack is; eth, MPLS, MPLS, BIER
377 #
378 igp_mpls = rx[0][MPLS]
379 self.assertEqual(igp_mpls.label, 2001)
380 self.assertEqual(igp_mpls.ttl, 64)
381 self.assertEqual(igp_mpls.s, 0)
382 bier_mpls = igp_mpls[MPLS].payload
383 self.assertEqual(bier_mpls.label, 101)
384 self.assertEqual(bier_mpls.ttl, 64)
385 self.assertEqual(bier_mpls.s, 1)
386 self.assertEqual(rx[0][BIER].length, 2)
387
388 igp_mpls = rx[1][MPLS]
389 self.assertEqual(igp_mpls.label, 2002)
390 self.assertEqual(igp_mpls.ttl, 64)
391 self.assertEqual(igp_mpls.s, 0)
392 bier_mpls = igp_mpls[MPLS].payload
393 self.assertEqual(bier_mpls.label, 102)
394 self.assertEqual(bier_mpls.ttl, 64)
395 self.assertEqual(bier_mpls.s, 1)
396 self.assertEqual(rx[0][BIER].length, 2)
397
Neale Rannsd792d9c2017-10-21 10:53:20 -0700398 def test_bier_tail(self):
399 """BIER Tail"""
400
401 #
402 # Add a BIER table for sub-domain 0, set 0, and BSL 256
403 #
404 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
405 bt = VppBierTable(self, bti, 77)
406 bt.add_vpp_config()
407
408 #
409 # disposition table
410 #
411 bdt = VppBierDispTable(self, 8)
412 bdt.add_vpp_config()
413
414 #
415 # BIER route in table that's for-us
416 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800417 bier_route_1 = VppBierRoute(
418 self, bti, 1,
419 [VppRoutePath("0.0.0.0",
420 0xffffffff,
421 proto=DpoProto.DPO_PROTO_BIER,
422 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700423 bier_route_1.add_vpp_config()
424
425 #
426 # An entry in the disposition table
427 #
428 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
429 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800430 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700431 "0.0.0.0", 0, rpf_id=8192)
432 bier_de_1.add_vpp_config()
433
434 #
435 # A multicast route to forward post BIER disposition
436 #
437 route_eg_232_1_1_1 = VppIpMRoute(
438 self,
439 "0.0.0.0",
440 "232.1.1.1", 32,
441 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
442 paths=[VppMRoutePath(self.pg1.sw_if_index,
443 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
444 route_eg_232_1_1_1.add_vpp_config()
445 route_eg_232_1_1_1.update_rpf_id(8192)
446
447 #
448 # A packet with all bits set gets spat out to BP:1
449 #
450 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
451 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800452 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700453 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800454 BFRID=99) /
Neale Rannsd792d9c2017-10-21 10:53:20 -0700455 IP(src="1.1.1.1", dst="232.1.1.1") /
456 UDP(sport=1234, dport=1234) /
457 Raw())
458
459 self.send_and_expect(self.pg0, [p], self.pg1)
460
Neale Rannsceb4d052017-12-13 09:13:41 -0800461 #
462 # A packet that does not match the Disposition entry gets dropped
463 #
464 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
465 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800466 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700467 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800468 BFRID=77) /
Neale Rannsceb4d052017-12-13 09:13:41 -0800469 IP(src="1.1.1.1", dst="232.1.1.1") /
470 UDP(sport=1234, dport=1234) /
471 Raw())
472 self.send_and_assert_no_replies(self.pg0, p*2,
473 "no matching disposition entry")
474
475 #
476 # Add the default route to the disposition table
477 #
478 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
479 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800480 DpoProto.DPO_PROTO_BIER,
Neale Rannsceb4d052017-12-13 09:13:41 -0800481 "0.0.0.0", 0, rpf_id=8192)
482 bier_de_2.add_vpp_config()
483
484 #
485 # now the previous packet is forwarded
486 #
487 self.send_and_expect(self.pg0, [p], self.pg1)
488
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700489 #
490 # A multicast route to forward post BIER disposition that needs
491 # a check against sending back into the BIER core
492 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700493 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700494 bi.add_vpp_config()
495
496 route_eg_232_1_1_2 = VppIpMRoute(
497 self,
498 "0.0.0.0",
499 "232.1.1.2", 32,
500 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
501 paths=[VppMRoutePath(0xffffffff,
502 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
503 proto=DpoProto.DPO_PROTO_BIER,
504 bier_imp=bi.bi_index),
505 VppMRoutePath(self.pg1.sw_if_index,
506 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
507 route_eg_232_1_1_2.add_vpp_config()
508 route_eg_232_1_1_2.update_rpf_id(8192)
509
510 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
511 MPLS(label=77, ttl=255) /
512 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700513 BitString=scapy.compat.chb(255)*32,
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700514 BFRID=77) /
515 IP(src="1.1.1.1", dst="232.1.1.2") /
516 UDP(sport=1234, dport=1234) /
517 Raw())
518 self.send_and_expect(self.pg0, [p], self.pg1)
519
Neale Rannsf0510722018-01-31 11:35:41 -0800520 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
521 """ BIER end-to-end"""
Neale Rannsd792d9c2017-10-21 10:53:20 -0700522
523 #
524 # Add a BIER table for sub-domain 0, set 0, and BSL 256
525 #
Neale Rannsf0510722018-01-31 11:35:41 -0800526 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700527 bt = VppBierTable(self, bti, 77)
528 bt.add_vpp_config()
529
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700530 lowest = [b'\0'] * (n_bytes)
531 lowest[-1] = scapy.compat.chb(1)
532 highest = [b'\0'] * (n_bytes)
533 highest[0] = scapy.compat.chb(128)
Neale Rannsf0510722018-01-31 11:35:41 -0800534
Neale Rannsd792d9c2017-10-21 10:53:20 -0700535 #
Neale Rannsf0510722018-01-31 11:35:41 -0800536 # Impostion Sets bit strings
Neale Rannsd792d9c2017-10-21 10:53:20 -0700537 #
Neale Rannsf0510722018-01-31 11:35:41 -0800538 bi_low = VppBierImp(self, bti, 333, lowest)
539 bi_low.add_vpp_config()
540 bi_high = VppBierImp(self, bti, 334, highest)
541 bi_high.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700542
543 #
544 # Add a multicast route that will forward into the BIER doamin
545 #
546 route_ing_232_1_1_1 = VppIpMRoute(
547 self,
548 "0.0.0.0",
549 "232.1.1.1", 32,
550 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
551 paths=[VppMRoutePath(self.pg0.sw_if_index,
552 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
553 VppMRoutePath(0xffffffff,
554 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
555 proto=DpoProto.DPO_PROTO_BIER,
Neale Rannsf0510722018-01-31 11:35:41 -0800556 bier_imp=bi_low.bi_index)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700557 route_ing_232_1_1_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800558 route_ing_232_1_1_2 = VppIpMRoute(
559 self,
560 "0.0.0.0",
561 "232.1.1.2", 32,
562 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
563 paths=[VppMRoutePath(self.pg0.sw_if_index,
564 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
565 VppMRoutePath(0xffffffff,
566 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
567 proto=DpoProto.DPO_PROTO_BIER,
568 bier_imp=bi_high.bi_index)])
569 route_ing_232_1_1_2.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700570
571 #
572 # disposition table 8
573 #
574 bdt = VppBierDispTable(self, 8)
575 bdt.add_vpp_config()
576
577 #
Neale Rannsf0510722018-01-31 11:35:41 -0800578 # BIER routes in table that are for-us, resolving through
Neale Rannsd792d9c2017-10-21 10:53:20 -0700579 # disp table 8.
580 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800581 bier_route_1 = VppBierRoute(
582 self, bti, 1,
583 [VppRoutePath("0.0.0.0",
584 0xffffffff,
585 proto=DpoProto.DPO_PROTO_BIER,
586 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700587 bier_route_1.add_vpp_config()
Neale Rannsf726f532019-03-11 05:34:50 -0700588 bier_route_max = VppBierRoute(
589 self, bti, max_bp,
590 [VppRoutePath("0.0.0.0",
591 0xffffffff,
592 nh_table_id=8,
593 proto=DpoProto.DPO_PROTO_BIER)])
Neale Rannsf0510722018-01-31 11:35:41 -0800594 bier_route_max.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700595
596 #
597 # An entry in the disposition table for sender 333
598 # lookup in VRF 10
599 #
600 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
601 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800602 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700603 "0.0.0.0", 10, rpf_id=8192)
604 bier_de_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800605 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
606 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
607 DpoProto.DPO_PROTO_BIER,
608 "0.0.0.0", 10, rpf_id=8193)
609 bier_de_1.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700610
611 #
Neale Rannsf0510722018-01-31 11:35:41 -0800612 # Add a multicast routes that will forward the traffic
Neale Rannsd792d9c2017-10-21 10:53:20 -0700613 # post-disposition
614 #
615 route_eg_232_1_1_1 = VppIpMRoute(
616 self,
617 "0.0.0.0",
618 "232.1.1.1", 32,
619 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
620 table_id=10,
621 paths=[VppMRoutePath(self.pg1.sw_if_index,
622 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
623 route_eg_232_1_1_1.add_vpp_config()
624 route_eg_232_1_1_1.update_rpf_id(8192)
Neale Rannsf0510722018-01-31 11:35:41 -0800625 route_eg_232_1_1_2 = VppIpMRoute(
626 self,
627 "0.0.0.0",
628 "232.1.1.2", 32,
629 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
630 table_id=10,
631 paths=[VppMRoutePath(self.pg1.sw_if_index,
632 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
633 route_eg_232_1_1_2.add_vpp_config()
634 route_eg_232_1_1_2.update_rpf_id(8193)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700635
636 #
637 # inject a packet in VRF-0. We expect it to be BIER encapped,
638 # replicated, then hit the disposition and be forwarded
639 # out of VRF 10, i.e. on pg1
640 #
641 p = (Ether(dst=self.pg0.local_mac,
642 src=self.pg0.remote_mac) /
643 IP(src="1.1.1.1", dst="232.1.1.1") /
Neale Rannsf0510722018-01-31 11:35:41 -0800644 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700645 Raw(scapy.compat.chb(5) * 32))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700646
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400647 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
Neale Ranns91286372017-12-05 13:24:04 -0800648
Neale Ranns91286372017-12-05 13:24:04 -0800649 self.assertEqual(rx[0][IP].src, "1.1.1.1")
650 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
651
Neale Rannsf0510722018-01-31 11:35:41 -0800652 p = (Ether(dst=self.pg0.local_mac,
653 src=self.pg0.remote_mac) /
654 IP(src="1.1.1.1", dst="232.1.1.2") /
655 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700656 Raw(scapy.compat.chb(5) * 512))
Neale Rannsf0510722018-01-31 11:35:41 -0800657
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400658 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
Neale Rannsf0510722018-01-31 11:35:41 -0800659 self.assertEqual(rx[0][IP].src, "1.1.1.1")
660 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
661
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800662 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800663 def test_bier_e2e_1024(self):
664 """ BIER end-to-end BSL:1024"""
665 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
666
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800667 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800668 def test_bier_e2e_512(self):
669 """ BIER end-to-end BSL:512"""
670 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
671
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800672 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800673 def test_bier_e2e_256(self):
674 """ BIER end-to-end BSL:256"""
675 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
676
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800677 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800678 def test_bier_e2e_128(self):
679 """ BIER end-to-end BSL:128"""
680 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
681
682 def test_bier_e2e_64(self):
683 """ BIER end-to-end BSL:64"""
684 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
685
Neale Ranns91286372017-12-05 13:24:04 -0800686 def test_bier_head_o_udp(self):
687 """BIER head over UDP"""
688
689 #
690 # Add a BIER table for sub-domain 1, set 0, and BSL 256
691 #
692 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
693 bt = VppBierTable(self, bti, 77)
694 bt.add_vpp_config()
695
696 #
697 # 1 bit positions via 1 next hops
698 #
699 nh1 = "10.0.0.1"
700 ip_route = VppIpRoute(self, nh1, 32,
701 [VppRoutePath(self.pg1.remote_ip4,
702 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800703 labels=[VppMplsLabel(2001)])])
Neale Ranns91286372017-12-05 13:24:04 -0800704 ip_route.add_vpp_config()
705
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700706 udp_encap = VppUdpEncap(self,
Neale Ranns91286372017-12-05 13:24:04 -0800707 self.pg0.local_ip4,
708 nh1,
709 330, 8138)
710 udp_encap.add_vpp_config()
711
Neale Ranns2303cb12018-02-21 04:57:17 -0800712 bier_route = VppBierRoute(
713 self, bti, 1,
714 [VppRoutePath("0.0.0.0",
715 0xFFFFFFFF,
716 is_udp_encap=1,
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700717 next_hop_id=udp_encap.id)])
Neale Ranns91286372017-12-05 13:24:04 -0800718 bier_route.add_vpp_config()
719
720 #
Neale Rannseea537a2018-01-09 04:11:28 -0800721 # An 2 imposition objects with all bit-positions set
722 # only use the second, but creating 2 tests with a non-zero
723 # value index in the route add
Neale Ranns91286372017-12-05 13:24:04 -0800724 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700725 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
Neale Ranns91286372017-12-05 13:24:04 -0800726 bi.add_vpp_config()
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700727 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
Neale Rannseea537a2018-01-09 04:11:28 -0800728 bi2.add_vpp_config()
Neale Ranns91286372017-12-05 13:24:04 -0800729
730 #
731 # Add a multicast route that will forward into the BIER doamin
732 #
733 route_ing_232_1_1_1 = VppIpMRoute(
734 self,
735 "0.0.0.0",
736 "232.1.1.1", 32,
737 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
738 paths=[VppMRoutePath(self.pg0.sw_if_index,
739 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
740 VppMRoutePath(0xffffffff,
741 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
742 proto=DpoProto.DPO_PROTO_BIER,
Neale Rannseea537a2018-01-09 04:11:28 -0800743 bier_imp=bi2.bi_index)])
Neale Ranns91286372017-12-05 13:24:04 -0800744 route_ing_232_1_1_1.add_vpp_config()
745
746 #
747 # inject a packet an IP. We expect it to be BIER and UDP encapped,
748 #
749 p = (Ether(dst=self.pg0.local_mac,
750 src=self.pg0.remote_mac) /
751 IP(src="1.1.1.1", dst="232.1.1.1") /
752 UDP(sport=1234, dport=1234))
753
754 self.pg0.add_stream([p])
755 self.pg_enable_capture(self.pg_interfaces)
756 self.pg_start()
757
758 rx = self.pg1.get_capture(1)
759
760 #
761 # Encap Stack is, eth, IP, UDP, BIFT, BIER
762 #
763 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
764 self.assertEqual(rx[0][IP].dst, nh1)
765 self.assertEqual(rx[0][UDP].sport, 330)
766 self.assertEqual(rx[0][UDP].dport, 8138)
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700767 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
Neale Ranns91286372017-12-05 13:24:04 -0800768 self.assertEqual(rx[0][BIFT].sd, 1)
769 self.assertEqual(rx[0][BIFT].set, 0)
770 self.assertEqual(rx[0][BIFT].ttl, 64)
771 self.assertEqual(rx[0][BIER].length, 2)
772
773 def test_bier_tail_o_udp(self):
774 """BIER Tail over UDP"""
775
776 #
777 # Add a BIER table for sub-domain 0, set 0, and BSL 256
778 #
779 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
780 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
781 bt.add_vpp_config()
782
783 #
784 # disposition table
785 #
786 bdt = VppBierDispTable(self, 8)
787 bdt.add_vpp_config()
788
789 #
790 # BIER route in table that's for-us
791 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800792 bier_route_1 = VppBierRoute(
793 self, bti, 1,
794 [VppRoutePath("0.0.0.0",
795 0xffffffff,
796 proto=DpoProto.DPO_PROTO_BIER,
797 nh_table_id=8)])
Neale Ranns91286372017-12-05 13:24:04 -0800798 bier_route_1.add_vpp_config()
799
800 #
801 # An entry in the disposition table
802 #
803 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
804 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800805 DpoProto.DPO_PROTO_BIER,
Neale Ranns91286372017-12-05 13:24:04 -0800806 "0.0.0.0", 0, rpf_id=8192)
807 bier_de_1.add_vpp_config()
808
809 #
810 # A multicast route to forward post BIER disposition
811 #
812 route_eg_232_1_1_1 = VppIpMRoute(
813 self,
814 "0.0.0.0",
815 "232.1.1.1", 32,
816 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
817 paths=[VppMRoutePath(self.pg1.sw_if_index,
818 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
819 route_eg_232_1_1_1.add_vpp_config()
820 route_eg_232_1_1_1.update_rpf_id(8192)
821
822 #
823 # A packet with all bits set gets spat out to BP:1
824 #
825 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
826 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
827 UDP(sport=333, dport=8138) /
828 BIFT(sd=1, set=0, bsl=2, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800829 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700830 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800831 BFRID=99) /
Neale Ranns91286372017-12-05 13:24:04 -0800832 IP(src="1.1.1.1", dst="232.1.1.1") /
833 UDP(sport=1234, dport=1234) /
834 Raw())
835
836 rx = self.send_and_expect(self.pg0, [p], self.pg1)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700837
838
839if __name__ == '__main__':
840 unittest.main(testRunner=VppTestRunner)