blob: 793c8ca036225e82dbeb3d22e271c2f8c647dafa [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 Ranns097fa662018-05-01 05:17:55 -070010 VppMplsLabel, FibPathProto, FibPathType
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)
Neale Ranns097fa662018-05-01 05:17:55 -0700281
Neale Rannsef90ed02018-09-13 08:45:12 -0700282 for nh in nhs:
283 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
284
285 #
286 # remove first two paths
287 #
288 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
289 labels=[VppMplsLabel(101)]))
290 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
291 labels=[VppMplsLabel(101)]))
292
293 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
294 for nh in nhs[2:]:
295 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
296
297 #
298 # remove the last of the paths, deleteing the entry
299 #
300 bier_route.remove_all_paths()
301
302 self.send_and_assert_no_replies(self.pg0, pkts)
303
Neale Rannsd792d9c2017-10-21 10:53:20 -0700304 def test_bier_head(self):
305 """BIER head"""
306
307 #
308 # Add a BIER table for sub-domain 0, set 0, and BSL 256
309 #
310 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
311 bt = VppBierTable(self, bti, 77)
312 bt.add_vpp_config()
313
314 #
315 # 2 bit positions via two next hops
316 #
317 nh1 = "10.0.0.1"
318 nh2 = "10.0.0.2"
319 ip_route_1 = VppIpRoute(self, nh1, 32,
320 [VppRoutePath(self.pg1.remote_ip4,
321 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800322 labels=[VppMplsLabel(2001)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700323 ip_route_2 = VppIpRoute(self, nh2, 32,
324 [VppRoutePath(self.pg1.remote_ip4,
325 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800326 labels=[VppMplsLabel(2002)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700327 ip_route_1.add_vpp_config()
328 ip_route_2.add_vpp_config()
329
Neale Ranns91286372017-12-05 13:24:04 -0800330 bier_route_1 = VppBierRoute(self, bti, 1,
331 [VppRoutePath(nh1, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800332 labels=[VppMplsLabel(101)])])
Neale Ranns91286372017-12-05 13:24:04 -0800333 bier_route_2 = VppBierRoute(self, bti, 2,
334 [VppRoutePath(nh2, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800335 labels=[VppMplsLabel(102)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700336 bier_route_1.add_vpp_config()
337 bier_route_2.add_vpp_config()
338
339 #
340 # An imposition object with both bit-positions set
341 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700342 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700343 bi.add_vpp_config()
344
345 #
346 # Add a multicast route that will forward into the BIER doamin
347 #
348 route_ing_232_1_1_1 = VppIpMRoute(
349 self,
350 "0.0.0.0",
351 "232.1.1.1", 32,
352 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
353 paths=[VppMRoutePath(self.pg0.sw_if_index,
354 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
355 VppMRoutePath(0xffffffff,
356 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700357 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
358 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700359 bier_imp=bi.bi_index)])
360 route_ing_232_1_1_1.add_vpp_config()
361
362 #
Neale Ranns91286372017-12-05 13:24:04 -0800363 # inject an IP packet. We expect it to be BIER encapped and
Neale Rannsd792d9c2017-10-21 10:53:20 -0700364 # replicated.
365 #
366 p = (Ether(dst=self.pg0.local_mac,
367 src=self.pg0.remote_mac) /
368 IP(src="1.1.1.1", dst="232.1.1.1") /
369 UDP(sport=1234, dport=1234))
370
371 self.pg0.add_stream([p])
372 self.pg_enable_capture(self.pg_interfaces)
373 self.pg_start()
374
375 rx = self.pg1.get_capture(2)
376
Neale Ranns91286372017-12-05 13:24:04 -0800377 #
378 # Encap Stack is; eth, MPLS, MPLS, BIER
379 #
380 igp_mpls = rx[0][MPLS]
381 self.assertEqual(igp_mpls.label, 2001)
382 self.assertEqual(igp_mpls.ttl, 64)
383 self.assertEqual(igp_mpls.s, 0)
384 bier_mpls = igp_mpls[MPLS].payload
385 self.assertEqual(bier_mpls.label, 101)
386 self.assertEqual(bier_mpls.ttl, 64)
387 self.assertEqual(bier_mpls.s, 1)
388 self.assertEqual(rx[0][BIER].length, 2)
389
390 igp_mpls = rx[1][MPLS]
391 self.assertEqual(igp_mpls.label, 2002)
392 self.assertEqual(igp_mpls.ttl, 64)
393 self.assertEqual(igp_mpls.s, 0)
394 bier_mpls = igp_mpls[MPLS].payload
395 self.assertEqual(bier_mpls.label, 102)
396 self.assertEqual(bier_mpls.ttl, 64)
397 self.assertEqual(bier_mpls.s, 1)
398 self.assertEqual(rx[0][BIER].length, 2)
399
Neale Rannsd792d9c2017-10-21 10:53:20 -0700400 def test_bier_tail(self):
401 """BIER Tail"""
402
403 #
404 # Add a BIER table for sub-domain 0, set 0, and BSL 256
405 #
406 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
407 bt = VppBierTable(self, bti, 77)
408 bt.add_vpp_config()
409
410 #
411 # disposition table
412 #
413 bdt = VppBierDispTable(self, 8)
414 bdt.add_vpp_config()
415
416 #
417 # BIER route in table that's for-us
418 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800419 bier_route_1 = VppBierRoute(
420 self, bti, 1,
421 [VppRoutePath("0.0.0.0",
422 0xffffffff,
Neale Ranns097fa662018-05-01 05:17:55 -0700423 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Ranns2303cb12018-02-21 04:57:17 -0800424 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700425 bier_route_1.add_vpp_config()
426
427 #
428 # An entry in the disposition table
429 #
430 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
431 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Ranns097fa662018-05-01 05:17:55 -0700432 FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700433 "0.0.0.0", 0, rpf_id=8192)
434 bier_de_1.add_vpp_config()
435
436 #
437 # A multicast route to forward post BIER disposition
438 #
439 route_eg_232_1_1_1 = VppIpMRoute(
440 self,
441 "0.0.0.0",
442 "232.1.1.1", 32,
443 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
444 paths=[VppMRoutePath(self.pg1.sw_if_index,
445 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
446 route_eg_232_1_1_1.add_vpp_config()
447 route_eg_232_1_1_1.update_rpf_id(8192)
448
449 #
450 # A packet with all bits set gets spat out to BP:1
451 #
452 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
453 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800454 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700455 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800456 BFRID=99) /
Neale Rannsd792d9c2017-10-21 10:53:20 -0700457 IP(src="1.1.1.1", dst="232.1.1.1") /
458 UDP(sport=1234, dport=1234) /
459 Raw())
460
461 self.send_and_expect(self.pg0, [p], self.pg1)
462
Neale Rannsceb4d052017-12-13 09:13:41 -0800463 #
464 # A packet that does not match the Disposition entry gets dropped
465 #
466 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
467 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800468 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700469 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800470 BFRID=77) /
Neale Rannsceb4d052017-12-13 09:13:41 -0800471 IP(src="1.1.1.1", dst="232.1.1.1") /
472 UDP(sport=1234, dport=1234) /
473 Raw())
474 self.send_and_assert_no_replies(self.pg0, p*2,
475 "no matching disposition entry")
476
477 #
478 # Add the default route to the disposition table
479 #
480 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
481 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Ranns097fa662018-05-01 05:17:55 -0700482 FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Rannsceb4d052017-12-13 09:13:41 -0800483 "0.0.0.0", 0, rpf_id=8192)
484 bier_de_2.add_vpp_config()
485
486 #
487 # now the previous packet is forwarded
488 #
489 self.send_and_expect(self.pg0, [p], self.pg1)
490
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700491 #
492 # A multicast route to forward post BIER disposition that needs
493 # a check against sending back into the BIER core
494 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700495 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700496 bi.add_vpp_config()
497
498 route_eg_232_1_1_2 = VppIpMRoute(
499 self,
500 "0.0.0.0",
501 "232.1.1.2", 32,
502 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
503 paths=[VppMRoutePath(0xffffffff,
504 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
505 proto=DpoProto.DPO_PROTO_BIER,
Neale Ranns097fa662018-05-01 05:17:55 -0700506 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700507 bier_imp=bi.bi_index),
508 VppMRoutePath(self.pg1.sw_if_index,
509 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
510 route_eg_232_1_1_2.add_vpp_config()
511 route_eg_232_1_1_2.update_rpf_id(8192)
512
513 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
514 MPLS(label=77, ttl=255) /
515 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700516 BitString=scapy.compat.chb(255)*32,
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700517 BFRID=77) /
518 IP(src="1.1.1.1", dst="232.1.1.2") /
519 UDP(sport=1234, dport=1234) /
520 Raw())
521 self.send_and_expect(self.pg0, [p], self.pg1)
522
Neale Rannsf0510722018-01-31 11:35:41 -0800523 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
524 """ BIER end-to-end"""
Neale Rannsd792d9c2017-10-21 10:53:20 -0700525
526 #
527 # Add a BIER table for sub-domain 0, set 0, and BSL 256
528 #
Neale Rannsf0510722018-01-31 11:35:41 -0800529 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700530 bt = VppBierTable(self, bti, 77)
531 bt.add_vpp_config()
532
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700533 lowest = [b'\0'] * (n_bytes)
534 lowest[-1] = scapy.compat.chb(1)
535 highest = [b'\0'] * (n_bytes)
536 highest[0] = scapy.compat.chb(128)
Neale Rannsf0510722018-01-31 11:35:41 -0800537
Neale Rannsd792d9c2017-10-21 10:53:20 -0700538 #
Neale Rannsf0510722018-01-31 11:35:41 -0800539 # Impostion Sets bit strings
Neale Rannsd792d9c2017-10-21 10:53:20 -0700540 #
Neale Rannsf0510722018-01-31 11:35:41 -0800541 bi_low = VppBierImp(self, bti, 333, lowest)
542 bi_low.add_vpp_config()
543 bi_high = VppBierImp(self, bti, 334, highest)
544 bi_high.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700545
546 #
547 # Add a multicast route that will forward into the BIER doamin
548 #
549 route_ing_232_1_1_1 = VppIpMRoute(
550 self,
551 "0.0.0.0",
552 "232.1.1.1", 32,
553 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
554 paths=[VppMRoutePath(self.pg0.sw_if_index,
555 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
556 VppMRoutePath(0xffffffff,
557 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700558 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
559 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
Neale Rannsf0510722018-01-31 11:35:41 -0800560 bier_imp=bi_low.bi_index)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700561 route_ing_232_1_1_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800562 route_ing_232_1_1_2 = VppIpMRoute(
563 self,
564 "0.0.0.0",
565 "232.1.1.2", 32,
566 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
567 paths=[VppMRoutePath(self.pg0.sw_if_index,
568 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
569 VppMRoutePath(0xffffffff,
570 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700571 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
572 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
Neale Rannsf0510722018-01-31 11:35:41 -0800573 bier_imp=bi_high.bi_index)])
574 route_ing_232_1_1_2.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700575
576 #
577 # disposition table 8
578 #
579 bdt = VppBierDispTable(self, 8)
580 bdt.add_vpp_config()
581
582 #
Neale Rannsf0510722018-01-31 11:35:41 -0800583 # BIER routes in table that are for-us, resolving through
Neale Rannsd792d9c2017-10-21 10:53:20 -0700584 # disp table 8.
585 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800586 bier_route_1 = VppBierRoute(
587 self, bti, 1,
588 [VppRoutePath("0.0.0.0",
589 0xffffffff,
Neale Ranns097fa662018-05-01 05:17:55 -0700590 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Ranns2303cb12018-02-21 04:57:17 -0800591 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700592 bier_route_1.add_vpp_config()
Neale Rannsf726f532019-03-11 05:34:50 -0700593 bier_route_max = VppBierRoute(
594 self, bti, max_bp,
595 [VppRoutePath("0.0.0.0",
596 0xffffffff,
Neale Ranns097fa662018-05-01 05:17:55 -0700597 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
598 nh_table_id=8)])
Neale Rannsf0510722018-01-31 11:35:41 -0800599 bier_route_max.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700600
601 #
602 # An entry in the disposition table for sender 333
603 # lookup in VRF 10
604 #
605 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
606 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Ranns097fa662018-05-01 05:17:55 -0700607 FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700608 "0.0.0.0", 10, rpf_id=8192)
609 bier_de_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800610 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
611 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Ranns097fa662018-05-01 05:17:55 -0700612 FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Rannsf0510722018-01-31 11:35:41 -0800613 "0.0.0.0", 10, rpf_id=8193)
614 bier_de_1.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700615
616 #
Neale Rannsf0510722018-01-31 11:35:41 -0800617 # Add a multicast routes that will forward the traffic
Neale Rannsd792d9c2017-10-21 10:53:20 -0700618 # post-disposition
619 #
620 route_eg_232_1_1_1 = VppIpMRoute(
621 self,
622 "0.0.0.0",
623 "232.1.1.1", 32,
624 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
625 table_id=10,
626 paths=[VppMRoutePath(self.pg1.sw_if_index,
627 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
628 route_eg_232_1_1_1.add_vpp_config()
629 route_eg_232_1_1_1.update_rpf_id(8192)
Neale Rannsf0510722018-01-31 11:35:41 -0800630 route_eg_232_1_1_2 = VppIpMRoute(
631 self,
632 "0.0.0.0",
633 "232.1.1.2", 32,
634 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
635 table_id=10,
636 paths=[VppMRoutePath(self.pg1.sw_if_index,
637 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
638 route_eg_232_1_1_2.add_vpp_config()
639 route_eg_232_1_1_2.update_rpf_id(8193)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700640
641 #
642 # inject a packet in VRF-0. We expect it to be BIER encapped,
643 # replicated, then hit the disposition and be forwarded
644 # out of VRF 10, i.e. on pg1
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.1") /
Neale Rannsf0510722018-01-31 11:35:41 -0800649 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700650 Raw(scapy.compat.chb(5) * 32))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700651
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400652 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
Neale Ranns91286372017-12-05 13:24:04 -0800653
Neale Ranns91286372017-12-05 13:24:04 -0800654 self.assertEqual(rx[0][IP].src, "1.1.1.1")
655 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
656
Neale Rannsf0510722018-01-31 11:35:41 -0800657 p = (Ether(dst=self.pg0.local_mac,
658 src=self.pg0.remote_mac) /
659 IP(src="1.1.1.1", dst="232.1.1.2") /
660 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700661 Raw(scapy.compat.chb(5) * 512))
Neale Rannsf0510722018-01-31 11:35:41 -0800662
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400663 rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1)
Neale Rannsf0510722018-01-31 11:35:41 -0800664 self.assertEqual(rx[0][IP].src, "1.1.1.1")
665 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
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_1024(self):
669 """ BIER end-to-end BSL:1024"""
670 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
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_512(self):
674 """ BIER end-to-end BSL:512"""
675 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
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_256(self):
679 """ BIER end-to-end BSL:256"""
680 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
681
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800682 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800683 def test_bier_e2e_128(self):
684 """ BIER end-to-end BSL:128"""
685 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
686
687 def test_bier_e2e_64(self):
688 """ BIER end-to-end BSL:64"""
689 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
690
Neale Ranns91286372017-12-05 13:24:04 -0800691 def test_bier_head_o_udp(self):
692 """BIER head over UDP"""
693
694 #
695 # Add a BIER table for sub-domain 1, set 0, and BSL 256
696 #
697 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
698 bt = VppBierTable(self, bti, 77)
699 bt.add_vpp_config()
700
701 #
702 # 1 bit positions via 1 next hops
703 #
704 nh1 = "10.0.0.1"
705 ip_route = VppIpRoute(self, nh1, 32,
706 [VppRoutePath(self.pg1.remote_ip4,
707 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800708 labels=[VppMplsLabel(2001)])])
Neale Ranns91286372017-12-05 13:24:04 -0800709 ip_route.add_vpp_config()
710
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700711 udp_encap = VppUdpEncap(self,
Neale Ranns91286372017-12-05 13:24:04 -0800712 self.pg0.local_ip4,
713 nh1,
714 330, 8138)
715 udp_encap.add_vpp_config()
716
Neale Ranns2303cb12018-02-21 04:57:17 -0800717 bier_route = VppBierRoute(
718 self, bti, 1,
719 [VppRoutePath("0.0.0.0",
720 0xFFFFFFFF,
Neale Ranns097fa662018-05-01 05:17:55 -0700721 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700722 next_hop_id=udp_encap.id)])
Neale Ranns91286372017-12-05 13:24:04 -0800723 bier_route.add_vpp_config()
724
725 #
Neale Rannseea537a2018-01-09 04:11:28 -0800726 # An 2 imposition objects with all bit-positions set
727 # only use the second, but creating 2 tests with a non-zero
728 # value index in the route add
Neale Ranns91286372017-12-05 13:24:04 -0800729 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700730 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
Neale Ranns91286372017-12-05 13:24:04 -0800731 bi.add_vpp_config()
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700732 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
Neale Rannseea537a2018-01-09 04:11:28 -0800733 bi2.add_vpp_config()
Neale Ranns91286372017-12-05 13:24:04 -0800734
735 #
736 # Add a multicast route that will forward into the BIER doamin
737 #
738 route_ing_232_1_1_1 = VppIpMRoute(
739 self,
740 "0.0.0.0",
741 "232.1.1.1", 32,
742 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
743 paths=[VppMRoutePath(self.pg0.sw_if_index,
744 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
745 VppMRoutePath(0xffffffff,
746 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700747 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
748 type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
Neale Rannseea537a2018-01-09 04:11:28 -0800749 bier_imp=bi2.bi_index)])
Neale Ranns91286372017-12-05 13:24:04 -0800750 route_ing_232_1_1_1.add_vpp_config()
751
752 #
753 # inject a packet an IP. We expect it to be BIER and UDP encapped,
754 #
755 p = (Ether(dst=self.pg0.local_mac,
756 src=self.pg0.remote_mac) /
757 IP(src="1.1.1.1", dst="232.1.1.1") /
758 UDP(sport=1234, dport=1234))
759
760 self.pg0.add_stream([p])
761 self.pg_enable_capture(self.pg_interfaces)
762 self.pg_start()
763
764 rx = self.pg1.get_capture(1)
765
766 #
767 # Encap Stack is, eth, IP, UDP, BIFT, BIER
768 #
769 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
770 self.assertEqual(rx[0][IP].dst, nh1)
771 self.assertEqual(rx[0][UDP].sport, 330)
772 self.assertEqual(rx[0][UDP].dport, 8138)
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700773 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
Neale Ranns91286372017-12-05 13:24:04 -0800774 self.assertEqual(rx[0][BIFT].sd, 1)
775 self.assertEqual(rx[0][BIFT].set, 0)
776 self.assertEqual(rx[0][BIFT].ttl, 64)
777 self.assertEqual(rx[0][BIER].length, 2)
778
779 def test_bier_tail_o_udp(self):
780 """BIER Tail over UDP"""
781
782 #
783 # Add a BIER table for sub-domain 0, set 0, and BSL 256
784 #
785 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
786 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
787 bt.add_vpp_config()
788
789 #
790 # disposition table
791 #
792 bdt = VppBierDispTable(self, 8)
793 bdt.add_vpp_config()
794
795 #
796 # BIER route in table that's for-us
797 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800798 bier_route_1 = VppBierRoute(
799 self, bti, 1,
800 [VppRoutePath("0.0.0.0",
801 0xffffffff,
Neale Ranns097fa662018-05-01 05:17:55 -0700802 proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Ranns2303cb12018-02-21 04:57:17 -0800803 nh_table_id=8)])
Neale Ranns91286372017-12-05 13:24:04 -0800804 bier_route_1.add_vpp_config()
805
806 #
807 # An entry in the disposition table
808 #
809 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
810 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Ranns097fa662018-05-01 05:17:55 -0700811 FibPathProto.FIB_PATH_NH_PROTO_BIER,
Neale Ranns91286372017-12-05 13:24:04 -0800812 "0.0.0.0", 0, rpf_id=8192)
813 bier_de_1.add_vpp_config()
814
815 #
816 # A multicast route to forward post BIER disposition
817 #
818 route_eg_232_1_1_1 = VppIpMRoute(
819 self,
820 "0.0.0.0",
821 "232.1.1.1", 32,
822 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
823 paths=[VppMRoutePath(self.pg1.sw_if_index,
824 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
825 route_eg_232_1_1_1.add_vpp_config()
826 route_eg_232_1_1_1.update_rpf_id(8192)
827
828 #
829 # A packet with all bits set gets spat out to BP:1
830 #
831 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
832 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
833 UDP(sport=333, dport=8138) /
834 BIFT(sd=1, set=0, bsl=2, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800835 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700836 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800837 BFRID=99) /
Neale Ranns91286372017-12-05 13:24:04 -0800838 IP(src="1.1.1.1", dst="232.1.1.1") /
839 UDP(sport=1234, dport=1234) /
840 Raw())
841
842 rx = self.send_and_expect(self.pg0, [p], self.pg1)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700843
844
845if __name__ == '__main__':
846 unittest.main(testRunner=VppTestRunner)