blob: cd2d4c03af96c534752052a2fa7ef71ab19c0db2 [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
23
24class TestBFIB(VppTestCase):
25 """ BIER FIB Test Case """
26
27 def test_bfib(self):
28 """ BFIB Unit Tests """
29 error = self.vapi.cli("test bier")
30
31 if error:
32 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -080033 self.assertNotIn("Failed", error)
Neale Rannsd792d9c2017-10-21 10:53:20 -070034
35
36class TestBier(VppTestCase):
37 """ BIER Test Case """
38
39 def setUp(self):
40 super(TestBier, self).setUp()
41
42 # create 2 pg interfaces
43 self.create_pg_interfaces(range(3))
44
45 # create the default MPLS table
46 self.tables = []
47 tbl = VppMplsTable(self, 0)
48 tbl.add_vpp_config()
49 self.tables.append(tbl)
50
51 tbl = VppIpTable(self, 10)
52 tbl.add_vpp_config()
53 self.tables.append(tbl)
54
55 # setup both interfaces
56 for i in self.pg_interfaces:
57 if i == self.pg2:
58 i.set_table_ip4(10)
59 i.admin_up()
60 i.config_ip4()
61 i.resolve_arp()
62 i.enable_mpls()
63
64 def tearDown(self):
65 for i in self.pg_interfaces:
66 i.disable_mpls()
67 i.unconfig_ip4()
68 i.set_table_ip4(0)
69 i.admin_down()
70 super(TestBier, self).tearDown()
71
Neale Rannsf0510722018-01-31 11:35:41 -080072 def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
Neale Rannsd792d9c2017-10-21 10:53:20 -070073 """BIER midpoint"""
74
75 #
76 # Add a BIER table for sub-domain 0, set 0, and BSL 256
77 #
Neale Rannsf0510722018-01-31 11:35:41 -080078 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -070079 bt = VppBierTable(self, bti, 77)
80 bt.add_vpp_config()
81
82 #
83 # A packet with no bits set gets dropped
84 #
85 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
86 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -080087 BIER(length=hdr_len_id) /
Neale Rannsd792d9c2017-10-21 10:53:20 -070088 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
89 UDP(sport=1234, dport=1234) /
90 Raw())
91 pkts = [p]
92
93 self.send_and_assert_no_replies(self.pg0, pkts,
94 "Empty Bit-String")
95
96 #
97 # Add a BIER route for each bit-position in the table via a different
98 # next-hop. Testing whether the BIER walk and replicate forwarding
99 # function works for all bit posisitons.
100 #
101 nh_routes = []
102 bier_routes = []
Neale Rannsf0510722018-01-31 11:35:41 -0800103 for i in range(1, max_bp+1):
Neale Rannsd792d9c2017-10-21 10:53:20 -0700104 nh = "10.0.%d.%d" % (i / 255, i % 255)
Neale Ranns31ed7442018-02-23 05:29:09 -0800105 nh_routes.append(
106 VppIpRoute(self, nh, 32,
107 [VppRoutePath(self.pg1.remote_ip4,
108 self.pg1.sw_if_index,
109 labels=[VppMplsLabel(2000+i)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700110 nh_routes[-1].add_vpp_config()
111
Neale Ranns31ed7442018-02-23 05:29:09 -0800112 bier_routes.append(
113 VppBierRoute(self, bti, i,
114 [VppRoutePath(nh, 0xffffffff,
115 labels=[VppMplsLabel(100+i)])]))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700116 bier_routes[-1].add_vpp_config()
117
118 #
Neale Rannsf0510722018-01-31 11:35:41 -0800119 # A packet with all bits set gets replicated once for each bit
Neale Rannsd792d9c2017-10-21 10:53:20 -0700120 #
Neale Rannsf0510722018-01-31 11:35:41 -0800121 pkt_sizes = [64, 1400]
Neale Rannsd792d9c2017-10-21 10:53:20 -0700122
Neale Rannsf0510722018-01-31 11:35:41 -0800123 for pkt_size in pkt_sizes:
124 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
125 MPLS(label=77, ttl=255) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700126 BIER(length=hdr_len_id,
127 BitString=scapy.compat.chb(255)*n_bytes) /
Neale Rannsf0510722018-01-31 11:35:41 -0800128 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
129 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700130 Raw(scapy.compat.chb(5) * pkt_size))
Neale Rannsf0510722018-01-31 11:35:41 -0800131 pkts = p
Neale Rannsd792d9c2017-10-21 10:53:20 -0700132
Neale Rannsf0510722018-01-31 11:35:41 -0800133 self.pg0.add_stream(pkts)
134 self.pg_enable_capture(self.pg_interfaces)
135 self.pg_start()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700136
Neale Rannsf0510722018-01-31 11:35:41 -0800137 rx = self.pg1.get_capture(max_bp)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700138
Neale Rannsf0510722018-01-31 11:35:41 -0800139 for rxp in rx:
140 #
141 # The packets are not required to be sent in bit-position order
142 # when we setup the routes above we used the bit-position to
143 # construct the out-label. so use that here to determine the BP
144 #
145 olabel = rxp[MPLS]
146 bp = olabel.label - 2000
Neale Rannsd792d9c2017-10-21 10:53:20 -0700147
Neale Rannsf0510722018-01-31 11:35:41 -0800148 blabel = olabel[MPLS].payload
149 self.assertEqual(blabel.label, 100+bp)
150 self.assertEqual(blabel.ttl, 254)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700151
Neale Rannsf0510722018-01-31 11:35:41 -0800152 bier_hdr = blabel[MPLS].payload
Neale Rannsd792d9c2017-10-21 10:53:20 -0700153
Neale Rannsf0510722018-01-31 11:35:41 -0800154 self.assertEqual(bier_hdr.id, 5)
155 self.assertEqual(bier_hdr.version, 0)
156 self.assertEqual(bier_hdr.length, hdr_len_id)
157 self.assertEqual(bier_hdr.entropy, 0)
158 self.assertEqual(bier_hdr.OAM, 0)
159 self.assertEqual(bier_hdr.RSV, 0)
160 self.assertEqual(bier_hdr.DSCP, 0)
161 self.assertEqual(bier_hdr.Proto, 5)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700162
Neale Rannsf0510722018-01-31 11:35:41 -0800163 # The bit-string should consist only of the BP given by i.
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700164 byte_array = [b'\0'] * (n_bytes)
165 byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
166 byte_pos = n_bytes - (((bp - 1) // 8) + 1)
Neale Rannsf0510722018-01-31 11:35:41 -0800167 byte_array[byte_pos] = byte_val
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700168 bitstring = ''.join([scapy.compat.chb(x) for x in byte_array])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700169
Neale Rannsf0510722018-01-31 11:35:41 -0800170 self.assertEqual(len(bitstring), len(bier_hdr.BitString))
171 self.assertEqual(bitstring, bier_hdr.BitString)
172
173 #
174 # cleanup. not strictly necessary, but it's much quicker this way
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700175 # because the bier_fib_dump and ip_fib_dump will be empty when the
Neale Rannsf0510722018-01-31 11:35:41 -0800176 # auto-cleanup kicks in
177 #
178 for br in bier_routes:
179 br.remove_vpp_config()
180 for nhr in nh_routes:
181 nhr.remove_vpp_config()
182
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800183 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800184 def test_bier_midpoint_1024(self):
185 """BIER midpoint BSL:1024"""
186 self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024)
187
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800188 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800189 def test_bier_midpoint_512(self):
190 """BIER midpoint BSL:512"""
191 self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512)
192
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800193 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800194 def test_bier_midpoint_256(self):
195 """BIER midpoint BSL:256"""
196 self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256)
197
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800198 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800199 def test_bier_midpoint_128(self):
200 """BIER midpoint BSL:128"""
201 self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128)
202
203 def test_bier_midpoint_64(self):
Neale Rannsc819fc62018-02-16 02:44:05 -0800204 """BIER midpoint BSL:64"""
Neale Rannsf0510722018-01-31 11:35:41 -0800205 self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700206
Neale Rannsef90ed02018-09-13 08:45:12 -0700207 def test_bier_load_balance(self):
208 """BIER load-balance"""
209
210 #
211 # Add a BIER table for sub-domain 0, set 0, and BSL 256
212 #
213 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
214 bt = VppBierTable(self, bti, 77)
215 bt.add_vpp_config()
216
217 #
218 # packets with varying entropy
219 #
220 pkts = []
221 for ii in range(257):
222 pkts.append((Ether(dst=self.pg0.local_mac,
223 src=self.pg0.remote_mac) /
224 MPLS(label=77, ttl=255) /
225 BIER(length=BIERLength.BIER_LEN_64,
226 entropy=ii,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700227 BitString=scapy.compat.chb(255)*16) /
Neale Rannsef90ed02018-09-13 08:45:12 -0700228 IPv6(src=self.pg0.remote_ip6,
229 dst=self.pg0.remote_ip6) /
230 UDP(sport=1234, dport=1234) /
231 Raw()))
232
233 #
234 # 4 next hops
235 #
236 nhs = [{'ip': "10.0.0.1", 'label': 201},
237 {'ip': "10.0.0.2", 'label': 202},
238 {'ip': "10.0.0.3", 'label': 203},
239 {'ip': "10.0.0.4", 'label': 204}]
240
241 for nh in nhs:
242 ipr = VppIpRoute(
243 self, nh['ip'], 32,
244 [VppRoutePath(self.pg1.remote_ip4,
245 self.pg1.sw_if_index,
246 labels=[VppMplsLabel(nh['label'])])])
247 ipr.add_vpp_config()
248
249 bier_route = VppBierRoute(
250 self, bti, 1,
251 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
252 labels=[VppMplsLabel(101)]),
253 VppRoutePath(nhs[1]['ip'], 0xffffffff,
254 labels=[VppMplsLabel(101)])])
255 bier_route.add_vpp_config()
256
257 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
258
259 #
260 # we should have recieved a packet from each neighbor
261 #
262 for nh in nhs[:2]:
263 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
264
265 #
266 # add the other paths
267 #
268 bier_route.update_paths(
269 [VppRoutePath(nhs[0]['ip'], 0xffffffff,
270 labels=[VppMplsLabel(101)]),
271 VppRoutePath(nhs[1]['ip'], 0xffffffff,
272 labels=[VppMplsLabel(101)]),
273 VppRoutePath(nhs[2]['ip'], 0xffffffff,
274 labels=[VppMplsLabel(101)]),
275 VppRoutePath(nhs[3]['ip'], 0xffffffff,
276 labels=[VppMplsLabel(101)])])
277
278 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
279 for nh in nhs:
280 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
281
282 #
283 # remove first two paths
284 #
285 bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff,
286 labels=[VppMplsLabel(101)]))
287 bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff,
288 labels=[VppMplsLabel(101)]))
289
290 rx = self.send_and_expect(self.pg0, pkts, self.pg1)
291 for nh in nhs[2:]:
292 self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))
293
294 #
295 # remove the last of the paths, deleteing the entry
296 #
297 bier_route.remove_all_paths()
298
299 self.send_and_assert_no_replies(self.pg0, pkts)
300
Neale Rannsd792d9c2017-10-21 10:53:20 -0700301 def test_bier_head(self):
302 """BIER head"""
303
304 #
305 # Add a BIER table for sub-domain 0, set 0, and BSL 256
306 #
307 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
308 bt = VppBierTable(self, bti, 77)
309 bt.add_vpp_config()
310
311 #
312 # 2 bit positions via two next hops
313 #
314 nh1 = "10.0.0.1"
315 nh2 = "10.0.0.2"
316 ip_route_1 = VppIpRoute(self, nh1, 32,
317 [VppRoutePath(self.pg1.remote_ip4,
318 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800319 labels=[VppMplsLabel(2001)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700320 ip_route_2 = VppIpRoute(self, nh2, 32,
321 [VppRoutePath(self.pg1.remote_ip4,
322 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 labels=[VppMplsLabel(2002)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700324 ip_route_1.add_vpp_config()
325 ip_route_2.add_vpp_config()
326
Neale Ranns91286372017-12-05 13:24:04 -0800327 bier_route_1 = VppBierRoute(self, bti, 1,
328 [VppRoutePath(nh1, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800329 labels=[VppMplsLabel(101)])])
Neale Ranns91286372017-12-05 13:24:04 -0800330 bier_route_2 = VppBierRoute(self, bti, 2,
331 [VppRoutePath(nh2, 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800332 labels=[VppMplsLabel(102)])])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700333 bier_route_1.add_vpp_config()
334 bier_route_2.add_vpp_config()
335
336 #
337 # An imposition object with both bit-positions set
338 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700339 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700340 bi.add_vpp_config()
341
342 #
343 # Add a multicast route that will forward into the BIER doamin
344 #
345 route_ing_232_1_1_1 = VppIpMRoute(
346 self,
347 "0.0.0.0",
348 "232.1.1.1", 32,
349 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
350 paths=[VppMRoutePath(self.pg0.sw_if_index,
351 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
352 VppMRoutePath(0xffffffff,
353 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
354 proto=DpoProto.DPO_PROTO_BIER,
355 bier_imp=bi.bi_index)])
356 route_ing_232_1_1_1.add_vpp_config()
357
358 #
Neale Ranns91286372017-12-05 13:24:04 -0800359 # inject an IP packet. We expect it to be BIER encapped and
Neale Rannsd792d9c2017-10-21 10:53:20 -0700360 # replicated.
361 #
362 p = (Ether(dst=self.pg0.local_mac,
363 src=self.pg0.remote_mac) /
364 IP(src="1.1.1.1", dst="232.1.1.1") /
365 UDP(sport=1234, dport=1234))
366
367 self.pg0.add_stream([p])
368 self.pg_enable_capture(self.pg_interfaces)
369 self.pg_start()
370
371 rx = self.pg1.get_capture(2)
372
Neale Ranns91286372017-12-05 13:24:04 -0800373 #
374 # Encap Stack is; eth, MPLS, MPLS, BIER
375 #
376 igp_mpls = rx[0][MPLS]
377 self.assertEqual(igp_mpls.label, 2001)
378 self.assertEqual(igp_mpls.ttl, 64)
379 self.assertEqual(igp_mpls.s, 0)
380 bier_mpls = igp_mpls[MPLS].payload
381 self.assertEqual(bier_mpls.label, 101)
382 self.assertEqual(bier_mpls.ttl, 64)
383 self.assertEqual(bier_mpls.s, 1)
384 self.assertEqual(rx[0][BIER].length, 2)
385
386 igp_mpls = rx[1][MPLS]
387 self.assertEqual(igp_mpls.label, 2002)
388 self.assertEqual(igp_mpls.ttl, 64)
389 self.assertEqual(igp_mpls.s, 0)
390 bier_mpls = igp_mpls[MPLS].payload
391 self.assertEqual(bier_mpls.label, 102)
392 self.assertEqual(bier_mpls.ttl, 64)
393 self.assertEqual(bier_mpls.s, 1)
394 self.assertEqual(rx[0][BIER].length, 2)
395
Neale Rannsd792d9c2017-10-21 10:53:20 -0700396 def test_bier_tail(self):
397 """BIER Tail"""
398
399 #
400 # Add a BIER table for sub-domain 0, set 0, and BSL 256
401 #
402 bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
403 bt = VppBierTable(self, bti, 77)
404 bt.add_vpp_config()
405
406 #
407 # disposition table
408 #
409 bdt = VppBierDispTable(self, 8)
410 bdt.add_vpp_config()
411
412 #
413 # BIER route in table that's for-us
414 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800415 bier_route_1 = VppBierRoute(
416 self, bti, 1,
417 [VppRoutePath("0.0.0.0",
418 0xffffffff,
419 proto=DpoProto.DPO_PROTO_BIER,
420 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700421 bier_route_1.add_vpp_config()
422
423 #
424 # An entry in the disposition table
425 #
426 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
427 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800428 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700429 "0.0.0.0", 0, rpf_id=8192)
430 bier_de_1.add_vpp_config()
431
432 #
433 # A multicast route to forward post BIER disposition
434 #
435 route_eg_232_1_1_1 = VppIpMRoute(
436 self,
437 "0.0.0.0",
438 "232.1.1.1", 32,
439 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
440 paths=[VppMRoutePath(self.pg1.sw_if_index,
441 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
442 route_eg_232_1_1_1.add_vpp_config()
443 route_eg_232_1_1_1.update_rpf_id(8192)
444
445 #
446 # A packet with all bits set gets spat out to BP:1
447 #
448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
449 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800450 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700451 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800452 BFRID=99) /
Neale Rannsd792d9c2017-10-21 10:53:20 -0700453 IP(src="1.1.1.1", dst="232.1.1.1") /
454 UDP(sport=1234, dport=1234) /
455 Raw())
456
457 self.send_and_expect(self.pg0, [p], self.pg1)
458
Neale Rannsceb4d052017-12-13 09:13:41 -0800459 #
460 # A packet that does not match the Disposition entry gets dropped
461 #
462 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
463 MPLS(label=77, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800464 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700465 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800466 BFRID=77) /
Neale Rannsceb4d052017-12-13 09:13:41 -0800467 IP(src="1.1.1.1", dst="232.1.1.1") /
468 UDP(sport=1234, dport=1234) /
469 Raw())
470 self.send_and_assert_no_replies(self.pg0, p*2,
471 "no matching disposition entry")
472
473 #
474 # Add the default route to the disposition table
475 #
476 bier_de_2 = VppBierDispEntry(self, bdt.id, 0,
477 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800478 DpoProto.DPO_PROTO_BIER,
Neale Rannsceb4d052017-12-13 09:13:41 -0800479 "0.0.0.0", 0, rpf_id=8192)
480 bier_de_2.add_vpp_config()
481
482 #
483 # now the previous packet is forwarded
484 #
485 self.send_and_expect(self.pg0, [p], self.pg1)
486
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700487 #
488 # A multicast route to forward post BIER disposition that needs
489 # a check against sending back into the BIER core
490 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700491 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700492 bi.add_vpp_config()
493
494 route_eg_232_1_1_2 = VppIpMRoute(
495 self,
496 "0.0.0.0",
497 "232.1.1.2", 32,
498 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
499 paths=[VppMRoutePath(0xffffffff,
500 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
501 proto=DpoProto.DPO_PROTO_BIER,
502 bier_imp=bi.bi_index),
503 VppMRoutePath(self.pg1.sw_if_index,
504 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
505 route_eg_232_1_1_2.add_vpp_config()
506 route_eg_232_1_1_2.update_rpf_id(8192)
507
508 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
509 MPLS(label=77, ttl=255) /
510 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700511 BitString=scapy.compat.chb(255)*32,
Neale Rannsfe4e48f2018-09-24 23:38:37 -0700512 BFRID=77) /
513 IP(src="1.1.1.1", dst="232.1.1.2") /
514 UDP(sport=1234, dport=1234) /
515 Raw())
516 self.send_and_expect(self.pg0, [p], self.pg1)
517
Neale Rannsf0510722018-01-31 11:35:41 -0800518 def bier_e2e(self, hdr_len_id, n_bytes, max_bp):
519 """ BIER end-to-end"""
Neale Rannsd792d9c2017-10-21 10:53:20 -0700520
521 #
522 # Add a BIER table for sub-domain 0, set 0, and BSL 256
523 #
Neale Rannsf0510722018-01-31 11:35:41 -0800524 bti = VppBierTableID(0, 0, hdr_len_id)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700525 bt = VppBierTable(self, bti, 77)
526 bt.add_vpp_config()
527
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700528 lowest = [b'\0'] * (n_bytes)
529 lowest[-1] = scapy.compat.chb(1)
530 highest = [b'\0'] * (n_bytes)
531 highest[0] = scapy.compat.chb(128)
Neale Rannsf0510722018-01-31 11:35:41 -0800532
Neale Rannsd792d9c2017-10-21 10:53:20 -0700533 #
Neale Rannsf0510722018-01-31 11:35:41 -0800534 # Impostion Sets bit strings
Neale Rannsd792d9c2017-10-21 10:53:20 -0700535 #
Neale Rannsf0510722018-01-31 11:35:41 -0800536 bi_low = VppBierImp(self, bti, 333, lowest)
537 bi_low.add_vpp_config()
538 bi_high = VppBierImp(self, bti, 334, highest)
539 bi_high.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700540
541 #
542 # Add a multicast route that will forward into the BIER doamin
543 #
544 route_ing_232_1_1_1 = VppIpMRoute(
545 self,
546 "0.0.0.0",
547 "232.1.1.1", 32,
548 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
549 paths=[VppMRoutePath(self.pg0.sw_if_index,
550 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
551 VppMRoutePath(0xffffffff,
552 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
553 proto=DpoProto.DPO_PROTO_BIER,
Neale Rannsf0510722018-01-31 11:35:41 -0800554 bier_imp=bi_low.bi_index)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700555 route_ing_232_1_1_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800556 route_ing_232_1_1_2 = VppIpMRoute(
557 self,
558 "0.0.0.0",
559 "232.1.1.2", 32,
560 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
561 paths=[VppMRoutePath(self.pg0.sw_if_index,
562 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
563 VppMRoutePath(0xffffffff,
564 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
565 proto=DpoProto.DPO_PROTO_BIER,
566 bier_imp=bi_high.bi_index)])
567 route_ing_232_1_1_2.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700568
569 #
570 # disposition table 8
571 #
572 bdt = VppBierDispTable(self, 8)
573 bdt.add_vpp_config()
574
575 #
Neale Rannsf0510722018-01-31 11:35:41 -0800576 # BIER routes in table that are for-us, resolving through
Neale Rannsd792d9c2017-10-21 10:53:20 -0700577 # disp table 8.
578 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800579 bier_route_1 = VppBierRoute(
580 self, bti, 1,
581 [VppRoutePath("0.0.0.0",
582 0xffffffff,
583 proto=DpoProto.DPO_PROTO_BIER,
584 nh_table_id=8)])
Neale Rannsd792d9c2017-10-21 10:53:20 -0700585 bier_route_1.add_vpp_config()
Neale Rannsf726f532019-03-11 05:34:50 -0700586 bier_route_max = VppBierRoute(
587 self, bti, max_bp,
588 [VppRoutePath("0.0.0.0",
589 0xffffffff,
590 nh_table_id=8,
591 proto=DpoProto.DPO_PROTO_BIER)])
Neale Rannsf0510722018-01-31 11:35:41 -0800592 bier_route_max.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700593
594 #
595 # An entry in the disposition table for sender 333
596 # lookup in VRF 10
597 #
598 bier_de_1 = VppBierDispEntry(self, bdt.id, 333,
599 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800600 DpoProto.DPO_PROTO_BIER,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700601 "0.0.0.0", 10, rpf_id=8192)
602 bier_de_1.add_vpp_config()
Neale Rannsf0510722018-01-31 11:35:41 -0800603 bier_de_1 = VppBierDispEntry(self, bdt.id, 334,
604 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
605 DpoProto.DPO_PROTO_BIER,
606 "0.0.0.0", 10, rpf_id=8193)
607 bier_de_1.add_vpp_config()
Neale Rannsd792d9c2017-10-21 10:53:20 -0700608
609 #
Neale Rannsf0510722018-01-31 11:35:41 -0800610 # Add a multicast routes that will forward the traffic
Neale Rannsd792d9c2017-10-21 10:53:20 -0700611 # post-disposition
612 #
613 route_eg_232_1_1_1 = VppIpMRoute(
614 self,
615 "0.0.0.0",
616 "232.1.1.1", 32,
617 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
618 table_id=10,
619 paths=[VppMRoutePath(self.pg1.sw_if_index,
620 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
621 route_eg_232_1_1_1.add_vpp_config()
622 route_eg_232_1_1_1.update_rpf_id(8192)
Neale Rannsf0510722018-01-31 11:35:41 -0800623 route_eg_232_1_1_2 = VppIpMRoute(
624 self,
625 "0.0.0.0",
626 "232.1.1.2", 32,
627 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
628 table_id=10,
629 paths=[VppMRoutePath(self.pg1.sw_if_index,
630 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
631 route_eg_232_1_1_2.add_vpp_config()
632 route_eg_232_1_1_2.update_rpf_id(8193)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700633
634 #
635 # inject a packet in VRF-0. We expect it to be BIER encapped,
636 # replicated, then hit the disposition and be forwarded
637 # out of VRF 10, i.e. on pg1
638 #
639 p = (Ether(dst=self.pg0.local_mac,
640 src=self.pg0.remote_mac) /
641 IP(src="1.1.1.1", dst="232.1.1.1") /
Neale Rannsf0510722018-01-31 11:35:41 -0800642 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700643 Raw(scapy.compat.chb(5) * 32))
Neale Rannsd792d9c2017-10-21 10:53:20 -0700644
Neale Ranns91286372017-12-05 13:24:04 -0800645 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
646
Neale Ranns91286372017-12-05 13:24:04 -0800647 self.assertEqual(rx[0][IP].src, "1.1.1.1")
648 self.assertEqual(rx[0][IP].dst, "232.1.1.1")
649
Neale Rannsf0510722018-01-31 11:35:41 -0800650 p = (Ether(dst=self.pg0.local_mac,
651 src=self.pg0.remote_mac) /
652 IP(src="1.1.1.1", dst="232.1.1.2") /
653 UDP(sport=1234, dport=1234) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700654 Raw(scapy.compat.chb(5) * 512))
Neale Rannsf0510722018-01-31 11:35:41 -0800655
656 rx = self.send_and_expect(self.pg0, p*65, self.pg1)
657 self.assertEqual(rx[0][IP].src, "1.1.1.1")
658 self.assertEqual(rx[0][IP].dst, "232.1.1.2")
659
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800660 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800661 def test_bier_e2e_1024(self):
662 """ BIER end-to-end BSL:1024"""
663 self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024)
664
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800665 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800666 def test_bier_e2e_512(self):
667 """ BIER end-to-end BSL:512"""
668 self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512)
669
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800670 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800671 def test_bier_e2e_256(self):
672 """ BIER end-to-end BSL:256"""
673 self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256)
674
Paul Vinciguerradefde0f2018-12-06 07:46:13 -0800675 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Neale Rannsf0510722018-01-31 11:35:41 -0800676 def test_bier_e2e_128(self):
677 """ BIER end-to-end BSL:128"""
678 self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128)
679
680 def test_bier_e2e_64(self):
681 """ BIER end-to-end BSL:64"""
682 self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64)
683
Neale Ranns91286372017-12-05 13:24:04 -0800684 def test_bier_head_o_udp(self):
685 """BIER head over UDP"""
686
687 #
688 # Add a BIER table for sub-domain 1, set 0, and BSL 256
689 #
690 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
691 bt = VppBierTable(self, bti, 77)
692 bt.add_vpp_config()
693
694 #
695 # 1 bit positions via 1 next hops
696 #
697 nh1 = "10.0.0.1"
698 ip_route = VppIpRoute(self, nh1, 32,
699 [VppRoutePath(self.pg1.remote_ip4,
700 self.pg1.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800701 labels=[VppMplsLabel(2001)])])
Neale Ranns91286372017-12-05 13:24:04 -0800702 ip_route.add_vpp_config()
703
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700704 udp_encap = VppUdpEncap(self,
Neale Ranns91286372017-12-05 13:24:04 -0800705 self.pg0.local_ip4,
706 nh1,
707 330, 8138)
708 udp_encap.add_vpp_config()
709
Neale Ranns2303cb12018-02-21 04:57:17 -0800710 bier_route = VppBierRoute(
711 self, bti, 1,
712 [VppRoutePath("0.0.0.0",
713 0xFFFFFFFF,
714 is_udp_encap=1,
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700715 next_hop_id=udp_encap.id)])
Neale Ranns91286372017-12-05 13:24:04 -0800716 bier_route.add_vpp_config()
717
718 #
Neale Rannseea537a2018-01-09 04:11:28 -0800719 # An 2 imposition objects with all bit-positions set
720 # only use the second, but creating 2 tests with a non-zero
721 # value index in the route add
Neale Ranns91286372017-12-05 13:24:04 -0800722 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700723 bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
Neale Ranns91286372017-12-05 13:24:04 -0800724 bi.add_vpp_config()
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700725 bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
Neale Rannseea537a2018-01-09 04:11:28 -0800726 bi2.add_vpp_config()
Neale Ranns91286372017-12-05 13:24:04 -0800727
728 #
729 # Add a multicast route that will forward into the BIER doamin
730 #
731 route_ing_232_1_1_1 = VppIpMRoute(
732 self,
733 "0.0.0.0",
734 "232.1.1.1", 32,
735 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
736 paths=[VppMRoutePath(self.pg0.sw_if_index,
737 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
738 VppMRoutePath(0xffffffff,
739 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
740 proto=DpoProto.DPO_PROTO_BIER,
Neale Rannseea537a2018-01-09 04:11:28 -0800741 bier_imp=bi2.bi_index)])
Neale Ranns91286372017-12-05 13:24:04 -0800742 route_ing_232_1_1_1.add_vpp_config()
743
744 #
745 # inject a packet an IP. We expect it to be BIER and UDP encapped,
746 #
747 p = (Ether(dst=self.pg0.local_mac,
748 src=self.pg0.remote_mac) /
749 IP(src="1.1.1.1", dst="232.1.1.1") /
750 UDP(sport=1234, dport=1234))
751
752 self.pg0.add_stream([p])
753 self.pg_enable_capture(self.pg_interfaces)
754 self.pg_start()
755
756 rx = self.pg1.get_capture(1)
757
758 #
759 # Encap Stack is, eth, IP, UDP, BIFT, BIER
760 #
761 self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
762 self.assertEqual(rx[0][IP].dst, nh1)
763 self.assertEqual(rx[0][UDP].sport, 330)
764 self.assertEqual(rx[0][UDP].dport, 8138)
Neale Ranns9c0a3c42018-09-07 08:57:41 -0700765 self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
Neale Ranns91286372017-12-05 13:24:04 -0800766 self.assertEqual(rx[0][BIFT].sd, 1)
767 self.assertEqual(rx[0][BIFT].set, 0)
768 self.assertEqual(rx[0][BIFT].ttl, 64)
769 self.assertEqual(rx[0][BIER].length, 2)
770
771 def test_bier_tail_o_udp(self):
772 """BIER Tail over UDP"""
773
774 #
775 # Add a BIER table for sub-domain 0, set 0, and BSL 256
776 #
777 bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
778 bt = VppBierTable(self, bti, MPLS_LABEL_INVALID)
779 bt.add_vpp_config()
780
781 #
782 # disposition table
783 #
784 bdt = VppBierDispTable(self, 8)
785 bdt.add_vpp_config()
786
787 #
788 # BIER route in table that's for-us
789 #
Neale Ranns2303cb12018-02-21 04:57:17 -0800790 bier_route_1 = VppBierRoute(
791 self, bti, 1,
792 [VppRoutePath("0.0.0.0",
793 0xffffffff,
794 proto=DpoProto.DPO_PROTO_BIER,
795 nh_table_id=8)])
Neale Ranns91286372017-12-05 13:24:04 -0800796 bier_route_1.add_vpp_config()
797
798 #
799 # An entry in the disposition table
800 #
801 bier_de_1 = VppBierDispEntry(self, bdt.id, 99,
802 BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4,
Neale Rannsf0510722018-01-31 11:35:41 -0800803 DpoProto.DPO_PROTO_BIER,
Neale Ranns91286372017-12-05 13:24:04 -0800804 "0.0.0.0", 0, rpf_id=8192)
805 bier_de_1.add_vpp_config()
806
807 #
808 # A multicast route to forward post BIER disposition
809 #
810 route_eg_232_1_1_1 = VppIpMRoute(
811 self,
812 "0.0.0.0",
813 "232.1.1.1", 32,
814 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
815 paths=[VppMRoutePath(self.pg1.sw_if_index,
816 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
817 route_eg_232_1_1_1.add_vpp_config()
818 route_eg_232_1_1_1.update_rpf_id(8192)
819
820 #
821 # A packet with all bits set gets spat out to BP:1
822 #
823 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
824 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
825 UDP(sport=333, dport=8138) /
826 BIFT(sd=1, set=0, bsl=2, ttl=255) /
Neale Rannsf0510722018-01-31 11:35:41 -0800827 BIER(length=BIERLength.BIER_LEN_256,
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700828 BitString=scapy.compat.chb(255)*32,
Neale Rannsf0510722018-01-31 11:35:41 -0800829 BFRID=99) /
Neale Ranns91286372017-12-05 13:24:04 -0800830 IP(src="1.1.1.1", dst="232.1.1.1") /
831 UDP(sport=1234, dport=1234) /
832 Raw())
833
834 rx = self.send_and_expect(self.pg0, [p], self.pg1)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700835
836
837if __name__ == '__main__':
838 unittest.main(testRunner=VppTestRunner)