blob: 6e01a03aea16fc5fdccdd98fbfe4c4455d8221cd [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002
3import unittest
Gabriel Gannea9b2d582016-12-06 10:25:34 +01004import socket
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00006from framework import tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +00007from framework import VppTestCase, VppTestRunner
Neale Rannsd5d7b962019-08-04 03:30:56 -07008from vpp_ip import DpoProto, INVALID_INDEX
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02009from vpp_ip_route import (
10 VppIpRoute,
11 VppRoutePath,
12 VppMplsRoute,
13 VppMplsIpBind,
14 VppIpMRoute,
15 VppMRoutePath,
16 VppIpTable,
17 VppMplsTable,
18 VppMplsLabel,
19 MplsLspMode,
20 find_mpls_route,
21 FibPathProto,
22 FibPathType,
23 FibPathFlags,
24 VppMplsLabel,
25 MplsLspMode,
26)
Neale Ranns0f26c5a2017-03-01 15:12:11 -080027from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns990f6942020-10-20 07:20:17 +000028from vpp_papi import VppEnum
Neale Ranns8fe8cc22016-11-01 10:05:08 +000029
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070030import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000031from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000032from scapy.layers.l2 import Ether, ARP
Neale Rannsfbc633f2022-03-18 13:05:09 +000033from scapy.layers.inet import IP, UDP, ICMP, icmptypes, icmpcodes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034from scapy.layers.inet6 import (
35 IPv6,
36 ICMPv6TimeExceeded,
37 ICMPv6EchoRequest,
38 ICMPv6PacketTooBig,
39)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000040from scapy.contrib.mpls import MPLS
41
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040042NUM_PKTS = 67
43
Neale Ranns1976f362019-11-06 13:13:01 +000044# scapy removed these attributes.
45# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
46# semantic names have more meaning than numbers. so here they are.
47ARP.who_has = 1
48ARP.is_at = 2
49
Klement Sekeradab231a2016-12-21 08:50:14 +010050
Neale Rannsda78f952017-05-24 09:15:43 -070051def verify_filter(capture, sent):
52 if not len(capture) == len(sent):
53 # filter out any IPv6 RAs from the capture
54 for p in capture:
55 if p.haslayer(IPv6):
56 capture.remove(p)
57 return capture
58
59
Neale Ranns31ed7442018-02-23 05:29:09 -080060def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070061 # the rx'd packet has the MPLS label popped
62 eth = rx[Ether]
63 tst.assertEqual(eth.type, 0x8847)
64
65 rx_mpls = rx[MPLS]
66
67 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080068 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
69 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
70 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
71
Neale Rannsda78f952017-05-24 09:15:43 -070072 if ii == len(mpls_labels) - 1:
73 tst.assertEqual(rx_mpls.s, 1)
74 else:
75 # not end of stack
76 tst.assertEqual(rx_mpls.s, 0)
77 # pop the label to expose the next
78 rx_mpls = rx_mpls[MPLS].payload
79
80
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000081@tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +000082class TestMPLS(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020083 """MPLS Test Case"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +000084
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070085 @classmethod
86 def setUpClass(cls):
87 super(TestMPLS, cls).setUpClass()
88
89 @classmethod
90 def tearDownClass(cls):
91 super(TestMPLS, cls).tearDownClass()
92
Neale Ranns8fe8cc22016-11-01 10:05:08 +000093 def setUp(self):
94 super(TestMPLS, self).setUp()
95
96 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080097 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000098
99 # setup both interfaces
100 # assign them different tables.
101 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -0700102 self.tables = []
103
104 tbl = VppMplsTable(self, 0)
105 tbl.add_vpp_config()
106 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000107
108 for i in self.pg_interfaces:
109 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -0700110
111 if table_id != 0:
112 tbl = VppIpTable(self, table_id)
113 tbl.add_vpp_config()
114 self.tables.append(tbl)
115 tbl = VppIpTable(self, table_id, is_ip6=1)
116 tbl.add_vpp_config()
117 self.tables.append(tbl)
118
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000119 i.set_table_ip4(table_id)
120 i.set_table_ip6(table_id)
121 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000122 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000123 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000124 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000125 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000126 table_id += 1
127
128 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800129 for i in self.pg_interfaces:
130 i.unconfig_ip4()
131 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700132 i.set_table_ip4(0)
133 i.set_table_ip6(0)
134 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800135 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700136 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000137
Neale Rannsad422ed2016-11-02 14:20:04 +0000138 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100139 def create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200140 self,
141 src_if,
142 mpls_labels,
143 ping=0,
144 ip_itf=None,
145 dst_ip=None,
146 chksum=None,
147 ip_ttl=64,
148 n=257,
149 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100150 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000151 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800152 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100153 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000154 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000155 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
156
157 for ii in range(len(mpls_labels)):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200158 p = p / MPLS(
159 label=mpls_labels[ii].value,
160 ttl=mpls_labels[ii].ttl,
161 cos=mpls_labels[ii].exp,
162 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100163 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800164 if not dst_ip:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 p = (
166 p
167 / IP(src=src_if.local_ip4, dst=src_if.remote_ip4, ttl=ip_ttl)
168 / UDP(sport=1234, dport=1234)
169 / Raw(payload)
170 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800171 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200172 p = (
173 p
174 / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl)
175 / UDP(sport=1234, dport=1234)
176 / Raw(payload)
177 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100178 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200179 p = (
180 p
181 / IP(src=ip_itf.remote_ip4, dst=ip_itf.local_ip4, ttl=ip_ttl)
182 / ICMP()
183 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100184
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700185 if chksum:
186 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000187 info.data = p.copy()
188 pkts.append(p)
189 return pkts
190
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200191 def create_stream_ip4(
192 self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, payload_size=None
193 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100194 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000195 pkts = []
196 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100197 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000198 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199 p = (
200 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
201 / IP(src=src_if.remote_ip4, dst=dst_ip, ttl=ip_ttl, tos=ip_dscp)
202 / UDP(sport=1234, dport=1234)
203 / Raw(payload)
204 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000205 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200206 if payload_size:
207 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000208 pkts.append(p)
209 return pkts
210
Neale Ranns31ed7442018-02-23 05:29:09 -0800211 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
212 self.reset_packet_infos()
213 pkts = []
214 for i in range(0, 257):
215 info = self.create_packet_info(src_if, src_if)
216 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 p = (
218 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
219 / IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=ip_ttl, tc=ip_dscp)
220 / UDP(sport=1234, dport=1234)
221 / Raw(payload)
222 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800223 info.data = p.copy()
224 pkts.append(p)
225 return pkts
226
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200227 def create_stream_labelled_ip6(
228 self, src_if, mpls_labels, hlim=64, dst_ip=None, ping=0, ip_itf=None
229 ):
Neale Ranns31426c62017-05-24 10:32:58 -0700230 if dst_ip is None:
231 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100232 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000233 pkts = []
234 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100235 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000236 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800237 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
238 for l in mpls_labels:
239 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
240
Neale Rannsf478f752022-02-17 15:41:32 +0000241 if ping:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 p = p / (
243 IPv6(src=ip_itf.remote_ip6, dst=ip_itf.local_ip6)
244 / ICMPv6EchoRequest()
245 )
Neale Rannsf478f752022-02-17 15:41:32 +0000246 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200247 p = p / (
248 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim)
249 / UDP(sport=1234, dport=1234)
250 / Raw(payload)
251 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000252 info.data = p.copy()
253 pkts.append(p)
254 return pkts
255
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 def verify_capture_ip4(
257 self, src_if, capture, sent, ping_resp=0, ip_ttl=None, ip_dscp=0
258 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000259 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700260 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000261
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000262 self.assertEqual(len(capture), len(sent))
263
264 for i in range(len(capture)):
265 tx = sent[i]
266 rx = capture[i]
267
268 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000269 eth = rx[Ether]
270 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000271
272 tx_ip = tx[IP]
273 rx_ip = rx[IP]
274
Neale Rannscb630ff2016-12-14 13:31:29 +0100275 if not ping_resp:
276 self.assertEqual(rx_ip.src, tx_ip.src)
277 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800278 self.assertEqual(rx_ip.tos, ip_dscp)
279 if not ip_ttl:
280 # IP processing post pop has decremented the TTL
281 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
282 else:
283 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100284 else:
285 self.assertEqual(rx_ip.src, tx_ip.dst)
286 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000287
288 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000289 raise
290
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200291 def verify_capture_labelled_ip4(
292 self, src_if, capture, sent, mpls_labels, ip_ttl=None
293 ):
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700295 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000296
297 self.assertEqual(len(capture), len(sent))
298
299 for i in range(len(capture)):
300 tx = sent[i]
301 rx = capture[i]
302 tx_ip = tx[IP]
303 rx_ip = rx[IP]
304
Neale Ranns31ed7442018-02-23 05:29:09 -0800305 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000306
307 self.assertEqual(rx_ip.src, tx_ip.src)
308 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800309 if not ip_ttl:
310 # IP processing post pop has decremented the TTL
311 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
312 else:
313 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000314
315 except:
316 raise
317
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 def verify_capture_labelled_ip6(
319 self, src_if, capture, sent, mpls_labels, ip_ttl=None
320 ):
Neale Ranns31ed7442018-02-23 05:29:09 -0800321 try:
322 capture = verify_filter(capture, sent)
323
324 self.assertEqual(len(capture), len(sent))
325
326 for i in range(len(capture)):
327 tx = sent[i]
328 rx = capture[i]
329 tx_ip = tx[IPv6]
330 rx_ip = rx[IPv6]
331
332 verify_mpls_stack(self, rx, mpls_labels)
333
334 self.assertEqual(rx_ip.src, tx_ip.src)
335 self.assertEqual(rx_ip.dst, tx_ip.dst)
336 if not ip_ttl:
337 # IP processing post pop has decremented the TTL
338 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
339 else:
340 self.assertEqual(rx_ip.hlim, ip_ttl)
341
342 except:
343 raise
344
345 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000346 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700347 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000348
349 self.assertEqual(len(capture), len(sent))
350
351 for i in range(len(capture)):
352 tx = sent[i]
353 rx = capture[i]
354 tx_ip = tx[IP]
355 rx_ip = rx[IP]
356
Neale Ranns31ed7442018-02-23 05:29:09 -0800357 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000358
359 self.assertEqual(rx_ip.src, tx_ip.src)
360 self.assertEqual(rx_ip.dst, tx_ip.dst)
361 # IP processing post pop has decremented the TTL
362 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
363
364 except:
365 raise
366
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 def verify_capture_labelled(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000368 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700369 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000370
371 self.assertEqual(len(capture), len(sent))
372
373 for i in range(len(capture)):
374 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800375 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000376 except:
377 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000378
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 def verify_capture_ip6(
380 self, src_if, capture, sent, ip_hlim=None, ip_dscp=0, ping_resp=0
381 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000382 try:
383 self.assertEqual(len(capture), len(sent))
384
385 for i in range(len(capture)):
386 tx = sent[i]
387 rx = capture[i]
388
389 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000390 eth = rx[Ether]
391 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000392
393 tx_ip = tx[IPv6]
394 rx_ip = rx[IPv6]
395
Neale Rannsf478f752022-02-17 15:41:32 +0000396 if not ping_resp:
397 self.assertEqual(rx_ip.src, tx_ip.src)
398 self.assertEqual(rx_ip.dst, tx_ip.dst)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Rannsf478f752022-02-17 15:41:32 +0000400 # IP processing post pop has decremented the TTL
401 if not ip_hlim:
402 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
403 else:
404 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns31ed7442018-02-23 05:29:09 -0800405 else:
Neale Rannsf478f752022-02-17 15:41:32 +0000406 self.assertEqual(rx_ip.src, tx_ip.dst)
407 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000408 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000409 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000410
Neale Ranns62fe07c2017-10-31 12:28:22 -0700411 def verify_capture_ip6_icmp(self, src_if, capture, sent):
412 try:
Neale Ranns5c6dd172022-02-17 09:08:47 +0000413 # rate limited ICMP
414 self.assertTrue(len(capture) <= len(sent))
Neale Ranns62fe07c2017-10-31 12:28:22 -0700415
416 for i in range(len(capture)):
417 tx = sent[i]
418 rx = capture[i]
419
420 # the rx'd packet has the MPLS label popped
421 eth = rx[Ether]
422 self.assertEqual(eth.type, 0x86DD)
423
424 tx_ip = tx[IPv6]
425 rx_ip = rx[IPv6]
426
427 self.assertEqual(rx_ip.dst, tx_ip.src)
428 # ICMP sourced from the interface's address
429 self.assertEqual(rx_ip.src, src_if.local_ip6)
430 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200431 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700432
433 icmp = rx[ICMPv6TimeExceeded]
434
435 except:
436 raise
437
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200438 def verify_capture_fragmented_labelled_ip4(
439 self, src_if, capture, sent, mpls_labels, ip_ttl=None
440 ):
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530441 try:
442 capture = verify_filter(capture, sent)
443
444 for i in range(len(capture)):
445 tx = sent[0]
446 rx = capture[i]
447 tx_ip = tx[IP]
448 rx_ip = rx[IP]
449
450 verify_mpls_stack(self, rx, mpls_labels)
451
452 self.assertEqual(rx_ip.src, tx_ip.src)
453 self.assertEqual(rx_ip.dst, tx_ip.dst)
454 if not ip_ttl:
455 # IP processing post pop has decremented the TTL
456 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
457 else:
458 self.assertEqual(rx_ip.ttl, ip_ttl)
459
460 except:
461 raise
462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200463 def verify_capture_fragmented_labelled_ip6(
464 self, src_if, capture, sent, mpls_labels, ip_ttl=None
465 ):
Neale Rannsec5371e2022-03-04 11:45:41 +0000466 try:
467 capture = verify_filter(capture, sent)
468
469 for i in range(len(capture)):
470 tx = sent[0]
471 rx = capture[i]
472 tx_ip = tx[IPv6]
473 rx.show()
474 rx_ip = IPv6(rx[MPLS].payload)
475 rx_ip.show()
476
477 verify_mpls_stack(self, rx, mpls_labels)
478
479 self.assertEqual(rx_ip.src, tx_ip.src)
480 self.assertEqual(rx_ip.dst, tx_ip.dst)
481 if not ip_ttl:
482 # IP processing post pop has decremented the hop-limit
483 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
484 else:
485 self.assertEqual(rx_ip.hlim, ip_ttl)
486 except:
487 raise
488
Neale Rannsad422ed2016-11-02 14:20:04 +0000489 def test_swap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 """MPLS label swap tests"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000491
492 #
493 # A simple MPLS xconnect - eos label in label out
494 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200495 route_32_eos = VppMplsRoute(
496 self,
497 32,
498 1,
499 [
500 VppRoutePath(
501 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
502 )
503 ],
504 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000505 route_32_eos.add_vpp_config()
506
Neale Ranns775f73c2018-12-20 03:01:49 -0800507 self.assertTrue(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 find_mpls_route(
509 self,
510 0,
511 32,
512 1,
513 [
514 VppRoutePath(
515 self.pg0.remote_ip4,
516 self.pg0.sw_if_index,
517 labels=[VppMplsLabel(33)],
518 )
519 ],
520 )
521 )
Neale Ranns775f73c2018-12-20 03:01:49 -0800522
Neale Rannsad422ed2016-11-02 14:20:04 +0000523 #
524 # a stream that matches the route for 10.0.0.1
525 # PG0 is in the default table
526 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200527 tx = self.create_stream_labelled_ip4(
528 self.pg0, [VppMplsLabel(32, ttl=32, exp=1)]
529 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800530 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 self.verify_capture_labelled(
532 self.pg0, rx, tx, [VppMplsLabel(33, ttl=31, exp=1)]
533 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000534
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200535 self.assertEqual(route_32_eos.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700536
Neale Rannsad422ed2016-11-02 14:20:04 +0000537 #
538 # A simple MPLS xconnect - non-eos label in label out
539 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200540 route_32_neos = VppMplsRoute(
541 self,
542 32,
543 0,
544 [
545 VppRoutePath(
546 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
547 )
548 ],
549 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000550 route_32_neos.add_vpp_config()
551
552 #
553 # a stream that matches the route for 10.0.0.1
554 # PG0 is in the default table
555 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200556 tx = self.create_stream_labelled_ip4(
557 self.pg0, [VppMplsLabel(32, ttl=21, exp=7), VppMplsLabel(99)]
558 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800559 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200560 self.verify_capture_labelled(
561 self.pg0, rx, tx, [VppMplsLabel(33, ttl=20, exp=7), VppMplsLabel(99)]
562 )
563 self.assertEqual(route_32_neos.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000564
Neale Ranns31ed7442018-02-23 05:29:09 -0800565 #
566 # A simple MPLS xconnect - non-eos label in label out, uniform mode
567 #
568 route_42_neos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200569 self,
570 42,
571 0,
572 [
573 VppRoutePath(
574 self.pg0.remote_ip4,
575 self.pg0.sw_if_index,
576 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)],
577 )
578 ],
579 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000581
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200582 tx = self.create_stream_labelled_ip4(
583 self.pg0, [VppMplsLabel(42, ttl=21, exp=7), VppMplsLabel(99)]
584 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800585 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 self.verify_capture_labelled(
587 self.pg0, rx, tx, [VppMplsLabel(43, ttl=20, exp=7), VppMplsLabel(99)]
588 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000589
590 #
591 # An MPLS xconnect - EOS label in IP out
592 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200593 route_33_eos = VppMplsRoute(
594 self,
595 33,
596 1,
597 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
598 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000599 route_33_eos.add_vpp_config()
600
Neale Ranns31ed7442018-02-23 05:29:09 -0800601 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
602 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000603 self.verify_capture_ip4(self.pg0, rx, tx)
604
605 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700606 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700607 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200608 tx = self.create_stream_labelled_ip4(
609 self.pg0, [VppMplsLabel(33)], dst_ip=self.pg0.remote_ip4, n=65, chksum=1
610 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700611 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
612
613 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800614 # An MPLS xconnect - EOS label in IP out, uniform mode
615 #
616 route_3333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200617 self,
618 3333,
619 1,
620 [
621 VppRoutePath(
622 self.pg0.remote_ip4,
623 self.pg0.sw_if_index,
624 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
625 )
626 ],
627 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800628 route_3333_eos.add_vpp_config()
629
630 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200631 self.pg0, [VppMplsLabel(3333, ttl=55, exp=3)]
632 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800633 rx = self.send_and_expect(self.pg0, tx, self.pg0)
634 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
635 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200636 self.pg0, [VppMplsLabel(3333, ttl=66, exp=4)]
637 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800638 rx = self.send_and_expect(self.pg0, tx, self.pg0)
639 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
640
641 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700642 # An MPLS xconnect - EOS label in IPv6 out
643 #
644 route_333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200645 self,
646 333,
647 1,
648 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[])],
649 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
650 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700651 route_333_eos.add_vpp_config()
652
Neale Ranns31ed7442018-02-23 05:29:09 -0800653 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
654 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700655 self.verify_capture_ip6(self.pg0, rx, tx)
656
657 #
658 # disposed packets have an TTL expired
659 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200660 tx = self.create_stream_labelled_ip6(
661 self.pg0, [VppMplsLabel(333, ttl=64)], dst_ip=self.pg1.remote_ip6, hlim=1
662 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000663 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700664 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
665
666 #
667 # An MPLS xconnect - EOS label in IPv6 out w imp-null
668 #
669 route_334_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200670 self,
671 334,
672 1,
673 [
674 VppRoutePath(
675 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(3)]
676 )
677 ],
678 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
679 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700680 route_334_eos.add_vpp_config()
681
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200682 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334, ttl=64)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800683 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700684 self.verify_capture_ip6(self.pg0, rx, tx)
685
686 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800687 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
688 #
689 route_335_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200690 self,
691 335,
692 1,
693 [
694 VppRoutePath(
695 self.pg0.remote_ip6,
696 self.pg0.sw_if_index,
697 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
698 )
699 ],
700 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
701 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800702 route_335_eos.add_vpp_config()
703
704 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 self.pg0, [VppMplsLabel(335, ttl=27, exp=4)]
706 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800707 rx = self.send_and_expect(self.pg0, tx, self.pg0)
708 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
709
710 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700711 # disposed packets have an TTL expired
712 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200713 tx = self.create_stream_labelled_ip6(
714 self.pg0, [VppMplsLabel(334)], dst_ip=self.pg1.remote_ip6, hlim=0
715 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000716 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700717 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
718
719 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000720 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
721 # so this traffic should be dropped.
722 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200723 route_33_neos = VppMplsRoute(
724 self,
725 33,
726 0,
727 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
728 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000729 route_33_neos.add_vpp_config()
730
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200731 tx = self.create_stream_labelled_ip4(
732 self.pg0, [VppMplsLabel(33), VppMplsLabel(99)]
733 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800734 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200735 self.pg0, tx, "MPLS non-EOS packets popped and forwarded"
736 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000737
738 #
739 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800740 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000741 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200742 route_34_eos = VppMplsRoute(
743 self,
744 34,
745 1,
746 [
747 VppRoutePath(
748 "0.0.0.0",
749 0xFFFFFFFF,
750 nh_via_label=32,
751 labels=[VppMplsLabel(44), VppMplsLabel(45)],
752 )
753 ],
754 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700756 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000757
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200758 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800759 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200760 self.verify_capture_labelled(
761 self.pg0,
762 rx,
763 tx,
764 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(45, ttl=2)],
765 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000766
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200767 self.assertEqual(route_34_eos.get_stats_to()["packets"], 257)
768 self.assertEqual(route_32_neos.get_stats_via()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700769
Neale Ranns31ed7442018-02-23 05:29:09 -0800770 #
771 # A recursive EOS x-connect, which resolves through another x-connect
772 # in uniform mode
773 #
774 route_35_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 self,
776 35,
777 1,
778 [
779 VppRoutePath(
780 "0.0.0.0", 0xFFFFFFFF, nh_via_label=42, labels=[VppMplsLabel(44)]
781 )
782 ],
783 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800784 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000785
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200786 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(35, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800787 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200788 self.verify_capture_labelled(
789 self.pg0, rx, tx, [VppMplsLabel(43, ttl=2), VppMplsLabel(44, ttl=2)]
790 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000791
792 #
Matej Klottondeb69842016-12-09 15:05:46 +0100793 # A recursive non-EOS x-connect, which resolves through another
794 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000795 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200796 route_34_neos = VppMplsRoute(
797 self,
798 34,
799 0,
800 [
801 VppRoutePath(
802 "0.0.0.0",
803 0xFFFFFFFF,
804 nh_via_label=32,
805 labels=[VppMplsLabel(44), VppMplsLabel(46)],
806 )
807 ],
808 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000809 route_34_neos.add_vpp_config()
810
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200811 tx = self.create_stream_labelled_ip4(
812 self.pg0, [VppMplsLabel(34, ttl=45), VppMplsLabel(99)]
813 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800814 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100815 # it's the 2nd (counting from 0) label in the stack that is swapped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200816 self.verify_capture_labelled(
817 self.pg0,
818 rx,
819 tx,
820 [
821 VppMplsLabel(33),
822 VppMplsLabel(44),
823 VppMplsLabel(46, ttl=44),
824 VppMplsLabel(99),
825 ],
826 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000827
828 #
Matej Klottondeb69842016-12-09 15:05:46 +0100829 # an recursive IP route that resolves through the recursive non-eos
830 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000831 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200832 ip_10_0_0_1 = VppIpRoute(
833 self,
834 "10.0.0.1",
835 32,
836 [
837 VppRoutePath(
838 "0.0.0.0", 0xFFFFFFFF, nh_via_label=34, labels=[VppMplsLabel(55)]
839 )
840 ],
841 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000842 ip_10_0_0_1.add_vpp_config()
843
Neale Rannsad422ed2016-11-02 14:20:04 +0000844 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800845 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200846 self.verify_capture_labelled_ip4(
847 self.pg0,
848 rx,
849 tx,
850 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(55)],
851 )
852 self.assertEqual(ip_10_0_0_1.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000853
854 ip_10_0_0_1.remove_vpp_config()
855 route_34_neos.remove_vpp_config()
856 route_34_eos.remove_vpp_config()
857 route_33_neos.remove_vpp_config()
858 route_33_eos.remove_vpp_config()
859 route_32_neos.remove_vpp_config()
860 route_32_eos.remove_vpp_config()
861
862 def test_bind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 """MPLS Local Label Binding test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000864
865 #
866 # Add a non-recursive route with a single out label
867 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200868 route_10_0_0_1 = VppIpRoute(
869 self,
870 "10.0.0.1",
871 32,
872 [
873 VppRoutePath(
874 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
875 )
876 ],
877 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000878 route_10_0_0_1.add_vpp_config()
879
880 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800881 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000882 binding.add_vpp_config()
883
884 # non-EOS stream
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200885 tx = self.create_stream_labelled_ip4(
886 self.pg0, [VppMplsLabel(44), VppMplsLabel(99)]
887 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800888 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200889 self.verify_capture_labelled(
890 self.pg0, rx, tx, [VppMplsLabel(45, ttl=63), VppMplsLabel(99)]
891 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000892
893 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800894 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
895 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200896 self.verify_capture_labelled(self.pg0, rx, tx, [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000897
898 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000899 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800900 rx = self.send_and_expect(self.pg0, tx, self.pg0)
901 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000902
903 #
904 # cleanup
905 #
906 binding.remove_vpp_config()
907 route_10_0_0_1.remove_vpp_config()
908
909 def test_imposition(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200910 """MPLS label imposition test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000911
912 #
913 # Add a non-recursive route with a single out label
914 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200915 route_10_0_0_1 = VppIpRoute(
916 self,
917 "10.0.0.1",
918 32,
919 [
920 VppRoutePath(
921 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
922 )
923 ],
924 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000925 route_10_0_0_1.add_vpp_config()
926
927 #
928 # a stream that matches the route for 10.0.0.1
929 # PG0 is in the default table
930 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000931 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800932 rx = self.send_and_expect(self.pg0, tx, self.pg0)
933 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000934
935 #
936 # Add a non-recursive route with a 3 out labels
937 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200938 route_10_0_0_2 = VppIpRoute(
939 self,
940 "10.0.0.2",
941 32,
942 [
943 VppRoutePath(
944 self.pg0.remote_ip4,
945 self.pg0.sw_if_index,
946 labels=[VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
947 )
948 ],
949 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000950 route_10_0_0_2.add_vpp_config()
951
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200952 tx = self.create_stream_ip4(self.pg0, "10.0.0.2", ip_ttl=44, ip_dscp=0xFF)
Neale Ranns31ed7442018-02-23 05:29:09 -0800953 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200954 self.verify_capture_labelled_ip4(
955 self.pg0,
956 rx,
957 tx,
958 [VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
959 ip_ttl=43,
960 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000961
Neale Ranns31ed7442018-02-23 05:29:09 -0800962 #
963 # Add a non-recursive route with a single out label in uniform mode
964 #
965 route_10_0_0_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200966 self,
967 "10.0.0.3",
968 32,
969 [
970 VppRoutePath(
971 self.pg0.remote_ip4,
972 self.pg0.sw_if_index,
973 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
974 )
975 ],
976 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800977 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000978
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200979 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -0800980 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200981 self.verify_capture_labelled_ip4(
982 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
983 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800984
985 #
986 # Add a IPv6 non-recursive route with a single out label in
987 # uniform mode
988 #
989 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200990 self,
991 "2001::3",
992 128,
993 [
994 VppRoutePath(
995 self.pg0.remote_ip6,
996 self.pg0.sw_if_index,
997 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
998 )
999 ],
1000 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001001 route_2001_3.add_vpp_config()
1002
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001003 tx = self.create_stream_ip6(self.pg0, "2001::3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -08001004 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001005 self.verify_capture_labelled_ip6(
1006 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
1007 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001008
1009 #
Matej Klottondeb69842016-12-09 15:05:46 +01001010 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +00001011 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 route_11_0_0_1 = VppIpRoute(
1013 self,
1014 "11.0.0.1",
1015 32,
1016 [VppRoutePath("10.0.0.1", 0xFFFFFFFF, labels=[VppMplsLabel(44)])],
1017 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001018 route_11_0_0_1.add_vpp_config()
1019
1020 #
1021 # a stream that matches the route for 11.0.0.1, should pick up
1022 # the label stack for 11.0.0.1 and 10.0.0.1
1023 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001024 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001025 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001026 self.verify_capture_labelled_ip4(
1027 self.pg0, rx, tx, [VppMplsLabel(32), VppMplsLabel(44)]
1028 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001030 self.assertEqual(route_11_0_0_1.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001031
Neale Rannsad422ed2016-11-02 14:20:04 +00001032 #
1033 # add a recursive path, with 2 labels, via the 3 label route
1034 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001035 route_11_0_0_2 = VppIpRoute(
1036 self,
1037 "11.0.0.2",
1038 32,
1039 [
1040 VppRoutePath(
1041 "10.0.0.2", 0xFFFFFFFF, labels=[VppMplsLabel(44), VppMplsLabel(45)]
1042 )
1043 ],
1044 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001045 route_11_0_0_2.add_vpp_config()
1046
1047 #
1048 # a stream that matches the route for 11.0.0.1, should pick up
1049 # the label stack for 11.0.0.1 and 10.0.0.1
1050 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001051 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -08001052 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001053 self.verify_capture_labelled_ip4(
1054 self.pg0,
1055 rx,
1056 tx,
1057 [
1058 VppMplsLabel(32),
1059 VppMplsLabel(33),
1060 VppMplsLabel(34),
1061 VppMplsLabel(44),
1062 VppMplsLabel(45),
1063 ],
1064 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001065
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001066 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001067
1068 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 self.verify_capture_labelled_ip4(
1070 self.pg0,
1071 rx,
1072 tx,
1073 [
1074 VppMplsLabel(32),
1075 VppMplsLabel(33),
1076 VppMplsLabel(34),
1077 VppMplsLabel(44),
1078 VppMplsLabel(45),
1079 ],
1080 )
Neale Ranns008dbe12018-09-07 09:32:36 -07001081
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 514)
Neale Ranns008dbe12018-09-07 09:32:36 -07001083
Neale Rannsad422ed2016-11-02 14:20:04 +00001084 #
1085 # cleanup
1086 #
1087 route_11_0_0_2.remove_vpp_config()
1088 route_11_0_0_1.remove_vpp_config()
1089 route_10_0_0_2.remove_vpp_config()
1090 route_10_0_0_1.remove_vpp_config()
1091
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301092 def test_imposition_fragmentation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001093 """MPLS label imposition fragmentation test"""
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301094
1095 #
1096 # Add a ipv4 non-recursive route with a single out label
1097 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001098 route_10_0_0_1 = VppIpRoute(
1099 self,
1100 "10.0.0.1",
1101 32,
1102 [
1103 VppRoutePath(
1104 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1105 )
1106 ],
1107 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301108 route_10_0_0_1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 route_1000_1 = VppIpRoute(
1110 self,
1111 "1000::1",
1112 128,
1113 [
1114 VppRoutePath(
1115 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1116 )
1117 ],
1118 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001119 route_1000_1.add_vpp_config()
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301120
1121 #
1122 # a stream that matches the route for 10.0.0.1
1123 # PG0 is in the default table
1124 #
1125 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
1126 for i in range(0, 257):
1127 self.extend_packet(tx[i], 10000)
1128
1129 #
1130 # 5 fragments per packet (257*5=1285)
1131 #
1132 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001133 self.verify_capture_fragmented_labelled_ip4(
1134 self.pg0, rx, tx, [VppMplsLabel(32)]
1135 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301136
Neale Rannsec5371e2022-03-04 11:45:41 +00001137 # packets with DF bit set generate ICMP
1138 for t in tx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001139 t[IP].flags = "DF"
Neale Rannsec5371e2022-03-04 11:45:41 +00001140 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1141
1142 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001143 self.assertEqual(icmptypes[rx[ICMP].type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001144 self.assertEqual(
1145 icmpcodes[rx[ICMP].type][rx[ICMP].code], "fragmentation-needed"
1146 )
Neale Rannsfbc633f2022-03-18 13:05:09 +00001147 # the link MTU is 9000, the MPLS over head is 4 bytes
1148 self.assertEqual(rx[ICMP].nexthopmtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001149
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001150 self.assertEqual(
1151 self.statistics.get_err_counter(
1152 "/err/mpls-frag/can't fragment this packet"
1153 ),
1154 len(tx),
1155 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001156 #
1157 # a stream that matches the route for 1000::1/128
1158 # PG0 is in the default table
1159 #
1160 tx = self.create_stream_ip6(self.pg0, "1000::1")
1161 for i in range(0, 257):
1162 self.extend_packet(tx[i], 10000)
1163
1164 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1165 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001166 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001167
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301168 #
1169 # cleanup
1170 #
1171 route_10_0_0_1.remove_vpp_config()
1172
Neale Ranns31ed7442018-02-23 05:29:09 -08001173 def test_tunnel_pipe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001174 """MPLS Tunnel Tests - Pipe"""
Neale Rannsad422ed2016-11-02 14:20:04 +00001175
1176 #
Ole Troaneb284a12019-10-09 13:33:19 +02001177 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +00001178 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001179 mpls_tun = VppMPLSTunnelInterface(
1180 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001181 [
1182 VppRoutePath(
1183 self.pg0.remote_ip4,
1184 self.pg0.sw_if_index,
1185 labels=[VppMplsLabel(44), VppMplsLabel(46)],
1186 )
1187 ],
1188 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001189 mpls_tun.add_vpp_config()
1190 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +00001191
1192 #
1193 # add an unlabelled route through the new tunnel
1194 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001195 route_10_0_0_3 = VppIpRoute(
1196 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1197 )
Neale Ranns5a8123b2017-01-26 01:18:23 -08001198 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +00001199
1200 self.vapi.cli("clear trace")
1201 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1202 self.pg0.add_stream(tx)
1203
1204 self.pg_enable_capture(self.pg_interfaces)
1205 self.pg_start()
1206
1207 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001208 self.verify_capture_tunneled_ip4(
1209 self.pg0, rx, tx, [VppMplsLabel(44), VppMplsLabel(46)]
1210 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001211
Neale Ranns8c4611b2017-05-23 03:43:47 -07001212 #
1213 # add a labelled route through the new tunnel
1214 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001215 route_10_0_0_4 = VppIpRoute(
1216 self,
1217 "10.0.0.4",
1218 32,
1219 [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index, labels=[33])],
1220 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001221 route_10_0_0_4.add_vpp_config()
1222
1223 self.vapi.cli("clear trace")
1224 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1225 self.pg0.add_stream(tx)
1226
1227 self.pg_enable_capture(self.pg_interfaces)
1228 self.pg_start()
1229
1230 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001231 self.verify_capture_tunneled_ip4(
1232 self.pg0,
1233 rx,
1234 tx,
1235 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1236 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001237
Ole Troaneb284a12019-10-09 13:33:19 +02001238 #
1239 # change tunnel's MTU to a low value
1240 #
1241 mpls_tun.set_l3_mtu(1200)
1242
1243 # send IP into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001244 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", payload_size=1500)
1245 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001246
1247 fake_tx = []
1248 for p in tx:
1249 fake_tx.append(p)
1250 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001251 self.verify_capture_tunneled_ip4(
1252 self.pg0, rx, fake_tx, [VppMplsLabel(44), VppMplsLabel(46)]
1253 )
Ole Troaneb284a12019-10-09 13:33:19 +02001254
1255 # send MPLS into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001256 tx = self.create_stream_ip4(self.pg0, "10.0.0.4", payload_size=1500)
1257 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001258
1259 fake_tx = []
1260 for p in tx:
1261 fake_tx.append(p)
1262 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001263 self.verify_capture_tunneled_ip4(
1264 self.pg0,
1265 rx,
1266 fake_tx,
1267 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1268 )
Ole Troaneb284a12019-10-09 13:33:19 +02001269
Neale Ranns31ed7442018-02-23 05:29:09 -08001270 def test_tunnel_uniform(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001271 """MPLS Tunnel Tests - Uniform"""
Neale Ranns31ed7442018-02-23 05:29:09 -08001272
1273 #
1274 # Create a tunnel with a single out label
1275 # The label stack is specified here from outer to inner
1276 #
1277 mpls_tun = VppMPLSTunnelInterface(
1278 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001279 [
1280 VppRoutePath(
1281 self.pg0.remote_ip4,
1282 self.pg0.sw_if_index,
1283 labels=[
1284 VppMplsLabel(44, ttl=32),
1285 VppMplsLabel(46, MplsLspMode.UNIFORM),
1286 ],
1287 )
1288 ],
1289 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001290 mpls_tun.add_vpp_config()
1291 mpls_tun.admin_up()
1292
1293 #
1294 # add an unlabelled route through the new tunnel
1295 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001296 route_10_0_0_3 = VppIpRoute(
1297 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1298 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001299 route_10_0_0_3.add_vpp_config()
1300
1301 self.vapi.cli("clear trace")
1302 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1303 self.pg0.add_stream(tx)
1304
1305 self.pg_enable_capture(self.pg_interfaces)
1306 self.pg_start()
1307
1308 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001309 self.verify_capture_tunneled_ip4(
1310 self.pg0, rx, tx, [VppMplsLabel(44, ttl=32), VppMplsLabel(46, ttl=23)]
1311 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001312
1313 #
1314 # add a labelled route through the new tunnel
1315 #
1316 route_10_0_0_4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001317 self,
1318 "10.0.0.4",
1319 32,
1320 [
1321 VppRoutePath(
1322 "0.0.0.0", mpls_tun._sw_if_index, labels=[VppMplsLabel(33, ttl=47)]
1323 )
1324 ],
1325 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001326 route_10_0_0_4.add_vpp_config()
1327
1328 self.vapi.cli("clear trace")
1329 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1330 self.pg0.add_stream(tx)
1331
1332 self.pg_enable_capture(self.pg_interfaces)
1333 self.pg_start()
1334
1335 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001336 self.verify_capture_tunneled_ip4(
1337 self.pg0,
1338 rx,
1339 tx,
1340 [
1341 VppMplsLabel(44, ttl=32),
1342 VppMplsLabel(46, ttl=47),
1343 VppMplsLabel(33, ttl=47),
1344 ],
1345 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001346
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001347 def test_mpls_tunnel_many(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001348 """MPLS Multiple Tunnels"""
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001349
Neale Ranns397228d2021-10-21 12:02:53 +00001350 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001351 mpls_tun = VppMPLSTunnelInterface(
1352 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001353 [
1354 VppRoutePath(
1355 self.pg0.remote_ip4,
1356 self.pg0.sw_if_index,
1357 labels=[
1358 VppMplsLabel(44, ttl=32),
1359 VppMplsLabel(46, MplsLspMode.UNIFORM),
1360 ],
1361 )
1362 ],
1363 )
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001364 mpls_tun.add_vpp_config()
1365 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001366 for ii in range(100):
1367 mpls_tun = VppMPLSTunnelInterface(
1368 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001369 [
1370 VppRoutePath(
1371 self.pg0.remote_ip4,
1372 self.pg0.sw_if_index,
1373 labels=[
1374 VppMplsLabel(44, ttl=32),
1375 VppMplsLabel(46, MplsLspMode.UNIFORM),
1376 ],
1377 )
1378 ],
1379 is_l2=1,
1380 )
Neale Ranns397228d2021-10-21 12:02:53 +00001381 mpls_tun.add_vpp_config()
1382 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001383
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001384 def test_v4_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001385 """MPLS V4 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001386
1387 #
1388 # The first test case has an MPLS TTL of 0
1389 # all packet should be dropped
1390 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001391 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0, ttl=0)])
1392 self.send_and_assert_no_replies(self.pg0, tx, "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001393
1394 #
1395 # a stream with a non-zero MPLS TTL
1396 # PG0 is in the default table
1397 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001398 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1399 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001400 self.verify_capture_ip4(self.pg0, rx, tx)
1401
1402 #
1403 # a stream with a non-zero MPLS TTL
1404 # PG1 is in table 1
1405 # we are ensuring the post-pop lookup occurs in the VRF table
1406 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001407 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1408 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1409 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001410
1411 def test_v6_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001412 """MPLS V6 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001413
1414 #
1415 # a stream with a non-zero MPLS TTL
1416 # PG0 is in the default table
1417 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001418 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1419 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001420 self.verify_capture_ip6(self.pg0, rx, tx)
1421
1422 #
1423 # a stream with a non-zero MPLS TTL
1424 # PG1 is in table 1
1425 # we are ensuring the post-pop lookup occurs in the VRF table
1426 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001427 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1428 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001429 self.verify_capture_ip6(self.pg0, rx, tx)
1430
Neale Rannscb630ff2016-12-14 13:31:29 +01001431 def test_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001432 """MPLS Deagg"""
Neale Rannscb630ff2016-12-14 13:31:29 +01001433
1434 #
1435 # A de-agg route - next-hop lookup in default table
1436 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001437 route_34_eos = VppMplsRoute(
1438 self, 34, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
1439 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001440 route_34_eos.add_vpp_config()
1441
1442 #
1443 # ping an interface in the default table
1444 # PG0 is in the default table
1445 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 tx = self.create_stream_labelled_ip4(
1447 self.pg0, [VppMplsLabel(34)], ping=1, ip_itf=self.pg0
1448 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001449 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001450 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1451
1452 #
1453 # A de-agg route - next-hop lookup in non-default table
1454 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001455 route_35_eos = VppMplsRoute(
1456 self, 35, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
1457 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001458 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001459 route_356_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001460 self,
1461 356,
1462 1,
1463 [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=1)],
1464 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1465 )
Neale Rannsf478f752022-02-17 15:41:32 +00001466 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001467
1468 #
1469 # ping an interface in the non-default table
1470 # PG0 is in the default table. packet arrive labelled in the
1471 # default table and egress unlabelled in the non-default
1472 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001473 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001474 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1475 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001476 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001477 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001478 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001479 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1
1480 )
Neale Rannsf478f752022-02-17 15:41:32 +00001481 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1482 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001483
Neale Ranns6af1c042017-05-26 03:48:53 -07001484 #
1485 # Double pop
1486 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001487 route_36_neos = VppMplsRoute(self, 36, 0, [VppRoutePath("0.0.0.0", 0xFFFFFFFF)])
Neale Ranns6af1c042017-05-26 03:48:53 -07001488 route_36_neos.add_vpp_config()
1489
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001490 tx = self.create_stream_labelled_ip4(
1491 self.pg0, [VppMplsLabel(36), VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1492 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001493 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001494 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1495
1496 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001497 route_35_eos.remove_vpp_config()
1498 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001499
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001500 def test_interface_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001501 """MPLS Interface Receive"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001502
1503 #
1504 # Add a non-recursive route that will forward the traffic
1505 # post-interface-rx
1506 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001507 route_10_0_0_1 = VppIpRoute(
1508 self,
1509 "10.0.0.1",
1510 32,
1511 table_id=1,
1512 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1513 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001514 route_10_0_0_1.add_vpp_config()
1515
1516 #
1517 # An interface receive label that maps traffic to RX on interface
1518 # pg1
1519 # by injecting the packet in on pg0, which is in table 0
1520 # doing an interface-rx on pg1 and matching a route in table 1
1521 # if the packet egresses, then we must have swapped to pg1
1522 # so as to have matched the route in table 1
1523 #
Neale Ranns097fa662018-05-01 05:17:55 -07001524 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001525 self,
1526 34,
1527 1,
1528 [
1529 VppRoutePath(
1530 "0.0.0.0",
1531 self.pg1.sw_if_index,
1532 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1533 )
1534 ],
1535 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001536 route_34_eos.add_vpp_config()
1537
1538 #
1539 # ping an interface in the default table
1540 # PG0 is in the default table
1541 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001542 tx = self.create_stream_labelled_ip4(
1543 self.pg0, [VppMplsLabel(34)], dst_ip="10.0.0.1"
1544 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001545 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001546 self.verify_capture_ip4(self.pg1, rx, tx)
1547
1548 def test_mcast_mid_point(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001549 """MPLS Multicast Mid Point"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001550
1551 #
1552 # Add a non-recursive route that will forward the traffic
1553 # post-interface-rx
1554 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 route_10_0_0_1 = VppIpRoute(
1556 self,
1557 "10.0.0.1",
1558 32,
1559 table_id=1,
1560 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1561 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001562 route_10_0_0_1.add_vpp_config()
1563
1564 #
1565 # Add a mcast entry that replicate to pg2 and pg3
1566 # and replicate to a interface-rx (like a bud node would)
1567 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001568 route_3400_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001569 self,
1570 3400,
1571 1,
1572 [
1573 VppRoutePath(
1574 self.pg2.remote_ip4,
1575 self.pg2.sw_if_index,
1576 labels=[VppMplsLabel(3401)],
1577 ),
1578 VppRoutePath(
1579 self.pg3.remote_ip4,
1580 self.pg3.sw_if_index,
1581 labels=[VppMplsLabel(3402)],
1582 ),
1583 VppRoutePath(
1584 "0.0.0.0",
1585 self.pg1.sw_if_index,
1586 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1587 ),
1588 ],
1589 is_multicast=1,
1590 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001591 route_3400_eos.add_vpp_config()
1592
1593 #
1594 # ping an interface in the default table
1595 # PG0 is in the default table
1596 #
1597 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001598 tx = self.create_stream_labelled_ip4(
1599 self.pg0, [VppMplsLabel(3400, ttl=64)], n=257, dst_ip="10.0.0.1"
1600 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001601 self.pg0.add_stream(tx)
1602
1603 self.pg_enable_capture(self.pg_interfaces)
1604 self.pg_start()
1605
1606 rx = self.pg1.get_capture(257)
1607 self.verify_capture_ip4(self.pg1, rx, tx)
1608
1609 rx = self.pg2.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001610 self.verify_capture_labelled(self.pg2, rx, tx, [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001611 rx = self.pg3.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001612 self.verify_capture_labelled(self.pg3, rx, tx, [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001613
1614 def test_mcast_head(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001615 """MPLS Multicast Head-end"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001616
Neale Ranns990f6942020-10-20 07:20:17 +00001617 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1618 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1619
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001620 #
1621 # Create a multicast tunnel with two replications
1622 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001623 mpls_tun = VppMPLSTunnelInterface(
1624 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001625 [
1626 VppRoutePath(
1627 self.pg2.remote_ip4, self.pg2.sw_if_index, labels=[VppMplsLabel(42)]
1628 ),
1629 VppRoutePath(
1630 self.pg3.remote_ip4, self.pg3.sw_if_index, labels=[VppMplsLabel(43)]
1631 ),
1632 ],
1633 is_multicast=1,
1634 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001635 mpls_tun.add_vpp_config()
1636 mpls_tun.admin_up()
1637
1638 #
1639 # add an unlabelled route through the new tunnel
1640 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001641 route_10_0_0_3 = VppIpRoute(
1642 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1643 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001644 route_10_0_0_3.add_vpp_config()
1645
1646 self.vapi.cli("clear trace")
1647 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1648 self.pg0.add_stream(tx)
1649
1650 self.pg_enable_capture(self.pg_interfaces)
1651 self.pg_start()
1652
1653 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001654 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001655 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001656 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001657
1658 #
1659 # An an IP multicast route via the tunnel
1660 # A (*,G).
1661 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1662 #
1663 route_232_1_1_1 = VppIpMRoute(
1664 self,
1665 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001666 "232.1.1.1",
1667 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001668 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001669 [
1670 VppMRoutePath(
1671 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1672 ),
1673 VppMRoutePath(
1674 mpls_tun._sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1675 ),
1676 ],
1677 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001678 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001679 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001680
1681 self.vapi.cli("clear trace")
1682 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1683 self.pg0.add_stream(tx)
1684
1685 self.pg_enable_capture(self.pg_interfaces)
1686 self.pg_start()
1687
1688 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001689 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001690 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001691 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001692
Neale Ranns31426c62017-05-24 10:32:58 -07001693 def test_mcast_ip4_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 """MPLS IPv4 Multicast Tail"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001695
Neale Ranns990f6942020-10-20 07:20:17 +00001696 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1697 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1698
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001699 #
1700 # Add a multicast route that will forward the traffic
1701 # post-disposition
1702 #
1703 route_232_1_1_1 = VppIpMRoute(
1704 self,
1705 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001706 "232.1.1.1",
1707 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001708 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001709 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001710 paths=[
1711 VppMRoutePath(
1712 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1713 )
1714 ],
1715 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001716 route_232_1_1_1.add_vpp_config()
1717
1718 #
1719 # An interface receive label that maps traffic to RX on interface
1720 # pg1
1721 # by injecting the packet in on pg0, which is in table 0
1722 # doing an rpf-id and matching a route in table 1
1723 # if the packet egresses, then we must have matched the route in
1724 # table 1
1725 #
Neale Ranns097fa662018-05-01 05:17:55 -07001726 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001727 self,
1728 34,
1729 1,
1730 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001731 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001732 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1733 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001734
1735 route_34_eos.add_vpp_config()
1736
1737 #
1738 # Drop due to interface lookup miss
1739 #
1740 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001741 tx = self.create_stream_labelled_ip4(
1742 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=1
1743 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001744 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1745
1746 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001747 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001748 #
1749 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001750 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001751
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001752 tx = self.create_stream_labelled_ip4(
1753 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1754 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001755 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001756 self.verify_capture_ip4(self.pg1, rx, tx)
1757
1758 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001759 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001760 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001761 tx = self.create_stream_labelled_ip4(
1762 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=65, chksum=1
1763 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001764 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1765
1766 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001767 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001768 #
1769 route_232_1_1_1.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001770 tx = self.create_stream_labelled_ip4(
1771 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1772 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001773 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1774
Neale Ranns31426c62017-05-24 10:32:58 -07001775 def test_mcast_ip6_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001776 """MPLS IPv6 Multicast Tail"""
Neale Ranns31426c62017-05-24 10:32:58 -07001777
Neale Ranns990f6942020-10-20 07:20:17 +00001778 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1779 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1780
Neale Ranns31426c62017-05-24 10:32:58 -07001781 #
1782 # Add a multicast route that will forward the traffic
1783 # post-disposition
1784 #
1785 route_ff = VppIpMRoute(
1786 self,
1787 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001788 "ff01::1",
1789 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001790 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001791 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001792 paths=[
1793 VppMRoutePath(
1794 self.pg1.sw_if_index,
1795 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1796 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1797 )
1798 ],
1799 )
Neale Ranns31426c62017-05-24 10:32:58 -07001800 route_ff.add_vpp_config()
1801
1802 #
1803 # An interface receive label that maps traffic to RX on interface
1804 # pg1
1805 # by injecting the packet in on pg0, which is in table 0
1806 # doing an rpf-id and matching a route in table 1
1807 # if the packet egresses, then we must have matched the route in
1808 # table 1
1809 #
1810 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001811 self,
1812 34,
1813 1,
1814 [VppRoutePath("::", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001815 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001816 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1817 )
Neale Ranns31426c62017-05-24 10:32:58 -07001818
1819 route_34_eos.add_vpp_config()
1820
1821 #
1822 # Drop due to interface lookup miss
1823 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001824 tx = self.create_stream_labelled_ip6(
1825 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1826 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001827 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001828
1829 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001830 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001831 #
1832 route_ff.update_rpf_id(55)
1833
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001834 tx = self.create_stream_labelled_ip6(
1835 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1836 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001837 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001838 self.verify_capture_ip6(self.pg1, rx, tx)
1839
1840 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001841 # disposed packets have hop-limit = 1
1842 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001843 tx = self.create_stream_labelled_ip6(
1844 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1", hlim=1
1845 )
Neale Ranns5c6dd172022-02-17 09:08:47 +00001846 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001847 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001848
1849 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001850 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001851 #
1852 route_ff.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001853 tx = self.create_stream_labelled_ip6(
1854 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1855 )
Neale Ranns31426c62017-05-24 10:32:58 -07001856 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1857
Neale Rannsd5d7b962019-08-04 03:30:56 -07001858 def test_6pe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001859 """MPLS 6PE"""
Neale Rannsd5d7b962019-08-04 03:30:56 -07001860
1861 #
1862 # Add a non-recursive route with a single out label
1863 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001864 route_10_0_0_1 = VppIpRoute(
1865 self,
1866 "10.0.0.1",
1867 32,
1868 [
1869 VppRoutePath(
1870 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
1871 )
1872 ],
1873 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001874 route_10_0_0_1.add_vpp_config()
1875
1876 # bind a local label to the route
1877 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1878 binding.add_vpp_config()
1879
1880 #
1881 # a labelled v6 route that resolves through the v4
1882 #
1883 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001884 self,
1885 "2001::3",
1886 128,
1887 [VppRoutePath("10.0.0.1", INVALID_INDEX, labels=[VppMplsLabel(32)])],
1888 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001889 route_2001_3.add_vpp_config()
1890
1891 tx = self.create_stream_ip6(self.pg0, "2001::3")
1892 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1893
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001894 self.verify_capture_labelled_ip6(
1895 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32)]
1896 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001897
1898 #
1899 # and a v4 recursive via the v6
1900 #
1901 route_20_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 self,
1903 "20.0.0.3",
1904 32,
1905 [VppRoutePath("2001::3", INVALID_INDEX, labels=[VppMplsLabel(99)])],
1906 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001907 route_20_3.add_vpp_config()
1908
1909 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1910 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1911
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001912 self.verify_capture_labelled_ip4(
1913 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32), VppMplsLabel(99)]
1914 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001915
Neale Ranns53962fb2021-12-20 18:18:42 +00001916 def test_attached(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001917 """Attach Routes with Local Label"""
Neale Ranns53962fb2021-12-20 18:18:42 +00001918
1919 #
1920 # test that if a local label is associated with an attached/connected
1921 # prefix, that we can reach hosts in the prefix.
1922 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001923 binding = VppMplsIpBind(
1924 self, 44, self.pg0._local_ip4_subnet, self.pg0.local_ip4_prefix_len
1925 )
Neale Ranns53962fb2021-12-20 18:18:42 +00001926 binding.add_vpp_config()
1927
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001928 tx = (
1929 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1930 / MPLS(label=44, ttl=64)
1931 / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
1932 / UDP(sport=1234, dport=1234)
1933 / Raw(b"\xa5" * 100)
1934 )
Neale Ranns53962fb2021-12-20 18:18:42 +00001935 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
1936 for rx in rxs:
1937 # if there's an ARP then the label is linked to the glean
1938 # which is wrong.
1939 self.assertFalse(rx.haslayer(ARP))
1940 # it should be unicasted to the host
1941 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1942 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
1943
Neale Ranns180279b2017-03-16 15:49:09 -04001944
1945class TestMPLSDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001946 """MPLS disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04001947
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001948 @classmethod
1949 def setUpClass(cls):
1950 super(TestMPLSDisabled, cls).setUpClass()
1951
1952 @classmethod
1953 def tearDownClass(cls):
1954 super(TestMPLSDisabled, cls).tearDownClass()
1955
Neale Ranns180279b2017-03-16 15:49:09 -04001956 def setUp(self):
1957 super(TestMPLSDisabled, self).setUp()
1958
1959 # create 2 pg interfaces
1960 self.create_pg_interfaces(range(2))
1961
Neale Ranns15002542017-09-10 04:39:11 -07001962 self.tbl = VppMplsTable(self, 0)
1963 self.tbl.add_vpp_config()
1964
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001965 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001966 self.pg0.admin_up()
1967 self.pg0.config_ip4()
1968 self.pg0.resolve_arp()
1969 self.pg0.enable_mpls()
1970
1971 # PG 1 is not MPLS enabled
1972 self.pg1.admin_up()
1973
1974 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001975 for i in self.pg_interfaces:
1976 i.unconfig_ip4()
1977 i.admin_down()
1978
Neale Ranns15002542017-09-10 04:39:11 -07001979 self.pg0.disable_mpls()
1980 super(TestMPLSDisabled, self).tearDown()
1981
Neale Ranns180279b2017-03-16 15:49:09 -04001982 def test_mpls_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001983 """MPLS Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04001984
Neale Rannsde0b3b52021-06-15 12:43:12 +00001985 self.logger.info(self.vapi.cli("show mpls interface"))
1986 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1987 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1988
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001989 tx = (
1990 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1991 / MPLS(label=32, ttl=64)
1992 / IPv6(src="2001::1", dst=self.pg0.remote_ip6)
1993 / UDP(sport=1234, dport=1234)
1994 / Raw(b"\xa5" * 100)
1995 )
Neale Ranns180279b2017-03-16 15:49:09 -04001996
1997 #
1998 # A simple MPLS xconnect - eos label in label out
1999 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002000 route_32_eos = VppMplsRoute(
2001 self,
2002 32,
2003 1,
2004 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[33])],
2005 )
Neale Ranns180279b2017-03-16 15:49:09 -04002006 route_32_eos.add_vpp_config()
2007
2008 #
2009 # PG1 does not forward IP traffic
2010 #
2011 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
2012
2013 #
2014 # MPLS enable PG1
2015 #
2016 self.pg1.enable_mpls()
2017
Neale Rannsde0b3b52021-06-15 12:43:12 +00002018 self.logger.info(self.vapi.cli("show mpls interface"))
2019 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2020
Neale Ranns180279b2017-03-16 15:49:09 -04002021 #
2022 # Now we get packets through
2023 #
2024 self.pg1.add_stream(tx)
2025 self.pg_enable_capture(self.pg_interfaces)
2026 self.pg_start()
2027
2028 rx = self.pg0.get_capture(1)
2029
2030 #
2031 # Disable PG1
2032 #
2033 self.pg1.disable_mpls()
2034
2035 #
2036 # PG1 does not forward IP traffic
2037 #
2038 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2039 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2040
2041
Neale Rannsf12a83f2017-04-18 09:09:40 -07002042class TestMPLSPIC(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002043 """MPLS Prefix-Independent Convergence (PIC) edge convergence"""
Neale Rannsf12a83f2017-04-18 09:09:40 -07002044
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002045 @classmethod
2046 def setUpClass(cls):
2047 super(TestMPLSPIC, cls).setUpClass()
2048
2049 @classmethod
2050 def tearDownClass(cls):
2051 super(TestMPLSPIC, cls).tearDownClass()
2052
Neale Rannsf12a83f2017-04-18 09:09:40 -07002053 def setUp(self):
2054 super(TestMPLSPIC, self).setUp()
2055
2056 # create 2 pg interfaces
2057 self.create_pg_interfaces(range(4))
2058
Neale Ranns15002542017-09-10 04:39:11 -07002059 mpls_tbl = VppMplsTable(self, 0)
2060 mpls_tbl.add_vpp_config()
2061 tbl4 = VppIpTable(self, 1)
2062 tbl4.add_vpp_config()
2063 tbl6 = VppIpTable(self, 1, is_ip6=1)
2064 tbl6.add_vpp_config()
2065
Neale Rannsf12a83f2017-04-18 09:09:40 -07002066 # core links
2067 self.pg0.admin_up()
2068 self.pg0.config_ip4()
2069 self.pg0.resolve_arp()
2070 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002071
Neale Rannsf12a83f2017-04-18 09:09:40 -07002072 self.pg1.admin_up()
2073 self.pg1.config_ip4()
2074 self.pg1.resolve_arp()
2075 self.pg1.enable_mpls()
2076
2077 # VRF (customer facing) link
2078 self.pg2.admin_up()
2079 self.pg2.set_table_ip4(1)
2080 self.pg2.config_ip4()
2081 self.pg2.resolve_arp()
2082 self.pg2.set_table_ip6(1)
2083 self.pg2.config_ip6()
2084 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002085
Neale Rannsf12a83f2017-04-18 09:09:40 -07002086 self.pg3.admin_up()
2087 self.pg3.set_table_ip4(1)
2088 self.pg3.config_ip4()
2089 self.pg3.resolve_arp()
2090 self.pg3.set_table_ip6(1)
2091 self.pg3.config_ip6()
2092 self.pg3.resolve_ndp()
2093
2094 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002095 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07002096 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002097 for i in self.pg_interfaces:
2098 i.unconfig_ip4()
2099 i.unconfig_ip6()
2100 i.set_table_ip4(0)
2101 i.set_table_ip6(0)
2102 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002103 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002104
2105 def test_mpls_ibgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002106 """MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002107
2108 1) setup many iBGP VPN routes via a pair of iBGP peers.
2109 2) Check EMCP forwarding to these peers
2110 3) withdraw the IGP route to one of these peers.
2111 4) check forwarding continues to the remaining peer
2112 """
2113
2114 #
2115 # IGP+LDP core routes
2116 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002117 core_10_0_0_45 = VppIpRoute(
2118 self,
2119 "10.0.0.45",
2120 32,
2121 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[45])],
2122 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002123 core_10_0_0_45.add_vpp_config()
2124
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 core_10_0_0_46 = VppIpRoute(
2126 self,
2127 "10.0.0.46",
2128 32,
2129 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[46])],
2130 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002131 core_10_0_0_46.add_vpp_config()
2132
2133 #
2134 # Lot's of VPN routes. We need more the 64 so VPP will build
2135 # the fast convergence indirection
2136 #
2137 vpn_routes = []
2138 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002139 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002140 dst = "192.168.1.%d" % ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002141 vpn_routes.append(
2142 VppIpRoute(
2143 self,
2144 dst,
2145 32,
2146 [
2147 VppRoutePath(
2148 "10.0.0.45",
2149 0xFFFFFFFF,
2150 labels=[145],
2151 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2152 ),
2153 VppRoutePath(
2154 "10.0.0.46",
2155 0xFFFFFFFF,
2156 labels=[146],
2157 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2158 ),
2159 ],
2160 table_id=1,
2161 )
2162 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002163 vpn_routes[ii].add_vpp_config()
2164
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002165 pkts.append(
2166 Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac)
2167 / IP(src=self.pg2.remote_ip4, dst=dst)
2168 / UDP(sport=1234, dport=1234)
2169 / Raw(b"\xa5" * 100)
2170 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002171
2172 #
2173 # Send the packet stream (one pkt to each VPN route)
2174 # - expect a 50-50 split of the traffic
2175 #
2176 self.pg2.add_stream(pkts)
2177 self.pg_enable_capture(self.pg_interfaces)
2178 self.pg_start()
2179
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002180 rx0 = self.pg0._get_capture(NUM_PKTS)
2181 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002182
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002183 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07002184 # with the split ratio, just as long as neither is 0
2185 self.assertNotEqual(0, len(rx0))
2186 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002187 self.assertEqual(
2188 len(pkts),
2189 len(rx0) + len(rx1),
2190 "Expected all (%s) packets across both ECMP paths. "
2191 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2192 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002193
2194 #
2195 # use a test CLI command to stop the FIB walk process, this
2196 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002197 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002198 #
2199 self.vapi.ppcli("test fib-walk-process disable")
2200
2201 #
2202 # Withdraw one of the IGP routes
2203 #
2204 core_10_0_0_46.remove_vpp_config()
2205
2206 #
2207 # now all packets should be forwarded through the remaining peer
2208 #
2209 self.vapi.ppcli("clear trace")
2210 self.pg2.add_stream(pkts)
2211 self.pg_enable_capture(self.pg_interfaces)
2212 self.pg_start()
2213
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002214 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002215 self.assertEqual(
2216 len(pkts),
2217 len(rx0),
2218 "Expected all (%s) packets across single path. "
2219 "rx0: %s." % (len(pkts), len(rx0)),
2220 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002221
2222 #
2223 # enable the FIB walk process to converge the FIB
2224 #
2225 self.vapi.ppcli("test fib-walk-process enable")
2226
2227 #
2228 # packets should still be forwarded through the remaining peer
2229 #
2230 self.pg2.add_stream(pkts)
2231 self.pg_enable_capture(self.pg_interfaces)
2232 self.pg_start()
2233
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002234 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002235 self.assertEqual(
2236 len(pkts),
2237 len(rx0),
2238 "Expected all (%s) packets across single path. "
2239 "rx0: %s." % (len(pkts), len(rx0)),
2240 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002241
2242 #
2243 # Add the IGP route back and we return to load-balancing
2244 #
2245 core_10_0_0_46.add_vpp_config()
2246
2247 self.pg2.add_stream(pkts)
2248 self.pg_enable_capture(self.pg_interfaces)
2249 self.pg_start()
2250
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002251 rx0 = self.pg0._get_capture(NUM_PKTS)
2252 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002253 self.assertNotEqual(0, len(rx0))
2254 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002255 self.assertEqual(
2256 len(pkts),
2257 len(rx0) + len(rx1),
2258 "Expected all (%s) packets across both ECMP paths. "
2259 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2260 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002261
2262 def test_mpls_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002263 """MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002264
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002265 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07002266 2) Check EMCP forwarding to these peers
2267 3) withdraw one eBGP path - expect LB across remaining eBGP
2268 """
2269
2270 #
2271 # Lot's of VPN routes. We need more the 64 so VPP will build
2272 # the fast convergence indirection
2273 #
2274 vpn_routes = []
2275 vpn_bindings = []
2276 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002277 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002278 dst = "192.168.1.%d" % ii
2279 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002280 vpn_routes.append(
2281 VppIpRoute(
2282 self,
2283 dst,
2284 32,
2285 [
2286 VppRoutePath(
2287 self.pg2.remote_ip4,
2288 0xFFFFFFFF,
2289 nh_table_id=1,
2290 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2291 ),
2292 VppRoutePath(
2293 self.pg3.remote_ip4,
2294 0xFFFFFFFF,
2295 nh_table_id=1,
2296 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2297 ),
2298 ],
2299 table_id=1,
2300 )
2301 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002302 vpn_routes[ii].add_vpp_config()
2303
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002304 vpn_bindings.append(
2305 VppMplsIpBind(self, local_label, dst, 32, ip_table_id=1)
2306 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002307 vpn_bindings[ii].add_vpp_config()
2308
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002309 pkts.append(
2310 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2311 / MPLS(label=local_label, ttl=64)
2312 / IP(src=self.pg0.remote_ip4, dst=dst)
2313 / UDP(sport=1234, dport=1234)
2314 / Raw(b"\xa5" * 100)
2315 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002316
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002317 #
2318 # Send the packet stream (one pkt to each VPN route)
2319 # - expect a 50-50 split of the traffic
2320 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002321 self.pg0.add_stream(pkts)
2322 self.pg_enable_capture(self.pg_interfaces)
2323 self.pg_start()
2324
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002325 rx0 = self.pg2._get_capture(NUM_PKTS)
2326 rx1 = self.pg3._get_capture(NUM_PKTS)
2327
2328 # not testing the LB hashing algorithm so we're not concerned
2329 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002330 self.assertNotEqual(0, len(rx0))
2331 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 self.assertEqual(
2333 len(pkts),
2334 len(rx0) + len(rx1),
2335 "Expected all (%s) packets across both ECMP paths. "
2336 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2337 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002338
2339 #
2340 # use a test CLI command to stop the FIB walk process, this
2341 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002342 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002343 #
2344 self.vapi.ppcli("test fib-walk-process disable")
2345
2346 #
2347 # withdraw the connected prefix on the interface.
2348 #
2349 self.pg2.unconfig_ip4()
2350
2351 #
2352 # now all packets should be forwarded through the remaining peer
2353 #
2354 self.pg0.add_stream(pkts)
2355 self.pg_enable_capture(self.pg_interfaces)
2356 self.pg_start()
2357
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002358 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002359 self.assertEqual(
2360 len(pkts),
2361 len(rx0),
2362 "Expected all (%s) packets across single path. "
2363 "rx0: %s." % (len(pkts), len(rx0)),
2364 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002365
2366 #
2367 # enable the FIB walk process to converge the FIB
2368 #
2369 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002370
2371 #
2372 # packets should still be forwarded through the remaining peer
2373 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002374 self.pg0.add_stream(pkts)
2375 self.pg_enable_capture(self.pg_interfaces)
2376 self.pg_start()
2377
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002378 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002379 self.assertEqual(
2380 len(pkts),
2381 len(rx0),
2382 "Expected all (%s) packets across single path. "
2383 "rx0: %s." % (len(pkts), len(rx0)),
2384 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002385
2386 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002387 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002388 #
2389 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002390 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002391
2392 self.pg0.add_stream(pkts)
2393 self.pg_enable_capture(self.pg_interfaces)
2394 self.pg_start()
2395
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002396 rx0 = self.pg2._get_capture(NUM_PKTS)
2397 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002398 self.assertNotEqual(0, len(rx0))
2399 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002400 self.assertEqual(
2401 len(pkts),
2402 len(rx0) + len(rx1),
2403 "Expected all (%s) packets across both ECMP paths. "
2404 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2405 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002406
2407 def test_mpls_v6_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002408 """MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002409
2410 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2411 2) Check EMCP forwarding to these peers
2412 3) withdraw one eBGP path - expect LB across remaining eBGP
2413 """
2414
2415 #
2416 # Lot's of VPN routes. We need more the 64 so VPP will build
2417 # the fast convergence indirection
2418 #
2419 vpn_routes = []
2420 vpn_bindings = []
2421 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002422 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002423 dst = "3000::%d" % ii
2424 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002425 vpn_routes.append(
2426 VppIpRoute(
2427 self,
2428 dst,
2429 128,
2430 [
2431 VppRoutePath(
2432 self.pg2.remote_ip6,
2433 0xFFFFFFFF,
2434 nh_table_id=1,
2435 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2436 ),
2437 VppRoutePath(
2438 self.pg3.remote_ip6,
2439 0xFFFFFFFF,
2440 nh_table_id=1,
2441 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2442 ),
2443 ],
2444 table_id=1,
2445 )
2446 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002447 vpn_routes[ii].add_vpp_config()
2448
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002449 vpn_bindings.append(
2450 VppMplsIpBind(self, local_label, dst, 128, ip_table_id=1)
2451 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002452 vpn_bindings[ii].add_vpp_config()
2453
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002454 pkts.append(
2455 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2456 / MPLS(label=local_label, ttl=64)
2457 / IPv6(src=self.pg0.remote_ip6, dst=dst)
2458 / UDP(sport=1234, dport=1234)
2459 / Raw(b"\xa5" * 100)
2460 )
Neale Ranns097fa662018-05-01 05:17:55 -07002461 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002462
2463 self.pg0.add_stream(pkts)
2464 self.pg_enable_capture(self.pg_interfaces)
2465 self.pg_start()
2466
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002467 rx0 = self.pg2._get_capture(NUM_PKTS)
2468 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002469 self.assertNotEqual(0, len(rx0))
2470 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002471 self.assertEqual(
2472 len(pkts),
2473 len(rx0) + len(rx1),
2474 "Expected all (%s) packets across both ECMP paths. "
2475 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2476 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002477
2478 #
2479 # use a test CLI command to stop the FIB walk process, this
2480 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002481 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002482 #
2483 self.vapi.ppcli("test fib-walk-process disable")
2484
2485 #
2486 # withdraw the connected prefix on the interface.
2487 # and shutdown the interface so the ND cache is flushed.
2488 #
2489 self.pg2.unconfig_ip6()
2490 self.pg2.admin_down()
2491
2492 #
2493 # now all packets should be forwarded through the remaining peer
2494 #
2495 self.pg0.add_stream(pkts)
2496 self.pg_enable_capture(self.pg_interfaces)
2497 self.pg_start()
2498
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002499 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002500 self.assertEqual(
2501 len(pkts),
2502 len(rx0),
2503 "Expected all (%s) packets across single path. "
2504 "rx0: %s." % (len(pkts), len(rx0)),
2505 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002506
2507 #
2508 # enable the FIB walk process to converge the FIB
2509 #
2510 self.vapi.ppcli("test fib-walk-process enable")
2511 self.pg0.add_stream(pkts)
2512 self.pg_enable_capture(self.pg_interfaces)
2513 self.pg_start()
2514
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002515 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002516 self.assertEqual(
2517 len(pkts),
2518 len(rx0),
2519 "Expected all (%s) packets across single path. "
2520 "rx0: %s." % (len(pkts), len(rx0)),
2521 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002522
2523 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002524 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002525 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002526 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002527 self.pg2.admin_up()
2528 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002529 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002530
2531 self.pg0.add_stream(pkts)
2532 self.pg_enable_capture(self.pg_interfaces)
2533 self.pg_start()
2534
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002535 rx0 = self.pg2._get_capture(NUM_PKTS)
2536 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002537 self.assertNotEqual(0, len(rx0))
2538 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002539 self.assertEqual(
2540 len(pkts),
2541 len(rx0) + len(rx1),
2542 "Expected all (%s) packets across both ECMP paths. "
2543 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2544 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002545
2546
Neale Rannsda78f952017-05-24 09:15:43 -07002547class TestMPLSL2(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002548 """MPLS-L2"""
Neale Rannsda78f952017-05-24 09:15:43 -07002549
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002550 @classmethod
2551 def setUpClass(cls):
2552 super(TestMPLSL2, cls).setUpClass()
2553
2554 @classmethod
2555 def tearDownClass(cls):
2556 super(TestMPLSL2, cls).tearDownClass()
2557
Neale Rannsda78f952017-05-24 09:15:43 -07002558 def setUp(self):
2559 super(TestMPLSL2, self).setUp()
2560
2561 # create 2 pg interfaces
2562 self.create_pg_interfaces(range(2))
2563
Neale Ranns15002542017-09-10 04:39:11 -07002564 # create the default MPLS table
2565 self.tables = []
2566 tbl = VppMplsTable(self, 0)
2567 tbl.add_vpp_config()
2568 self.tables.append(tbl)
2569
Neale Ranns1976f362019-11-06 13:13:01 +00002570 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002571 self.pg0.admin_up()
2572 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002573 self.pg0.enable_mpls()
2574
Neale Ranns15002542017-09-10 04:39:11 -07002575 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002576 for i in self.pg_interfaces[1:]:
2577 i.admin_up()
2578
2579 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002580 for i in self.pg_interfaces[1:]:
2581 i.admin_down()
2582
2583 self.pg0.disable_mpls()
2584 self.pg0.unconfig_ip4()
2585 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002586 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002587
Neale Ranns31ed7442018-02-23 05:29:09 -08002588 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002589 capture = verify_filter(capture, sent)
2590
2591 self.assertEqual(len(capture), len(sent))
2592
2593 for i in range(len(capture)):
2594 tx = sent[i]
2595 rx = capture[i]
2596
2597 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002598 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002599
2600 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002601 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002602
2603 self.assertEqual(rx_eth.src, tx_eth.src)
2604 self.assertEqual(rx_eth.dst, tx_eth.dst)
2605
Neale Ranns1976f362019-11-06 13:13:01 +00002606 def verify_arp_req(self, rx, smac, sip, dip):
2607 ether = rx[Ether]
2608 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2609 self.assertEqual(ether.src, smac)
2610
2611 arp = rx[ARP]
2612 self.assertEqual(arp.hwtype, 1)
2613 self.assertEqual(arp.ptype, 0x800)
2614 self.assertEqual(arp.hwlen, 6)
2615 self.assertEqual(arp.plen, 4)
2616 self.assertEqual(arp.op, ARP.who_has)
2617 self.assertEqual(arp.hwsrc, smac)
2618 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2619 self.assertEqual(arp.psrc, sip)
2620 self.assertEqual(arp.pdst, dip)
2621
Neale Rannsda78f952017-05-24 09:15:43 -07002622 def test_vpws(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002623 """Virtual Private Wire Service"""
Neale Rannsda78f952017-05-24 09:15:43 -07002624
2625 #
2626 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002627 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2628 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002629 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002630 mpls_tun_1 = VppMPLSTunnelInterface(
2631 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002632 [
2633 VppRoutePath(
2634 self.pg0.remote_ip4,
2635 self.pg0.sw_if_index,
2636 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)],
2637 )
2638 ],
2639 is_l2=1,
2640 )
Neale Rannsda78f952017-05-24 09:15:43 -07002641 mpls_tun_1.add_vpp_config()
2642 mpls_tun_1.admin_up()
2643
2644 #
2645 # Create a label entry to for 55 that does L2 input to the tunnel
2646 #
2647 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002648 self,
2649 55,
2650 1,
2651 [
2652 VppRoutePath(
2653 "0.0.0.0",
2654 mpls_tun_1.sw_if_index,
2655 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2656 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2657 )
2658 ],
2659 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2660 )
Neale Rannsda78f952017-05-24 09:15:43 -07002661 route_55_eos.add_vpp_config()
2662
2663 #
2664 # Cross-connect the tunnel with one of the customers L2 interfaces
2665 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002666 self.vapi.sw_interface_set_l2_xconnect(
2667 self.pg1.sw_if_index, mpls_tun_1.sw_if_index, enable=1
2668 )
2669 self.vapi.sw_interface_set_l2_xconnect(
2670 mpls_tun_1.sw_if_index, self.pg1.sw_if_index, enable=1
2671 )
Neale Rannsda78f952017-05-24 09:15:43 -07002672
2673 #
2674 # inject a packet from the core
2675 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002676 pcore = (
2677 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2678 / MPLS(label=55, ttl=64)
2679 / Ether(dst="00:00:de:ad:ba:be", src="00:00:de:ad:be:ef")
2680 / IP(src="10.10.10.10", dst="11.11.11.11")
2681 / UDP(sport=1234, dport=1234)
2682 / Raw(b"\xa5" * 100)
2683 )
Neale Rannsda78f952017-05-24 09:15:43 -07002684
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002685 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002686 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2687 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002688
Neale Ranns31ed7442018-02-23 05:29:09 -08002689 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2690 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002691
2692 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002693 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002694 # there's no resolved ARP entry so the first packet we see should be
2695 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002696 #
Neale Ranns1976f362019-11-06 13:13:01 +00002697 tx1 = pcore[MPLS].payload
2698 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2699
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002700 self.verify_arp_req(
2701 rx1[0], self.pg0.local_mac, self.pg0.local_ip4, self.pg0.remote_ip4
2702 )
Neale Ranns1976f362019-11-06 13:13:01 +00002703
2704 #
2705 # resolve the ARP entries and send again
2706 #
2707 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002708 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002709 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002710
Neale Ranns31ed7442018-02-23 05:29:09 -08002711 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002712
2713 def test_vpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002714 """Virtual Private LAN Service"""
Neale Ranns1976f362019-11-06 13:13:01 +00002715
2716 # we skipped this in the setup
2717 self.pg0.resolve_arp()
2718
Neale Rannsda78f952017-05-24 09:15:43 -07002719 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002720 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002721 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002722 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002723 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002724 [
2725 VppRoutePath(
2726 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(42)]
2727 )
2728 ],
2729 is_l2=1,
2730 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002731 mpls_tun1.add_vpp_config()
2732 mpls_tun1.admin_up()
2733
2734 mpls_tun2 = VppMPLSTunnelInterface(
2735 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002736 [
2737 VppRoutePath(
2738 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(43)]
2739 )
2740 ],
2741 is_l2=1,
2742 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002743 mpls_tun2.add_vpp_config()
2744 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002745
2746 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002747 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2748 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002749 #
2750 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002751 self,
2752 55,
2753 1,
2754 [
2755 VppRoutePath(
2756 "0.0.0.0",
2757 mpls_tun1.sw_if_index,
2758 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2759 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2760 )
2761 ],
2762 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2763 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002764
2765 route_56_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002766 self,
2767 56,
2768 1,
2769 [
2770 VppRoutePath(
2771 "0.0.0.0",
2772 mpls_tun2.sw_if_index,
2773 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2774 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2775 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2776 )
2777 ],
2778 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2779 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002780
2781 # move me
2782 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002783 route_55_eos.add_vpp_config()
2784
Neale Ranns1dbcf302019-07-19 11:44:53 +00002785 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2786
Neale Rannsda78f952017-05-24 09:15:43 -07002787 #
2788 # add to tunnel to the customers bridge-domain
2789 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002790 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002791 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1
2792 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002793 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002794 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1
2795 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002796 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002797 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1
2798 )
Neale Rannsda78f952017-05-24 09:15:43 -07002799
2800 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002801 # Packet from host on the customer interface to each host
2802 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002803 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002804 p_cust1 = (
2805 Ether(dst="00:00:de:ad:ba:b1", src="00:00:de:ad:be:ef")
2806 / IP(src="10.10.10.10", dst="11.11.11.11")
2807 / UDP(sport=1234, dport=1234)
2808 / Raw(b"\xa5" * 100)
2809 )
2810 p_cust2 = (
2811 Ether(dst="00:00:de:ad:ba:b2", src="00:00:de:ad:be:ef")
2812 / IP(src="10.10.10.10", dst="11.11.11.12")
2813 / UDP(sport=1234, dport=1234)
2814 / Raw(b"\xa5" * 100)
2815 )
2816 p_core1 = (
2817 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2818 / MPLS(label=55, ttl=64)
2819 / Ether(src="00:00:de:ad:ba:b1", dst="00:00:de:ad:be:ef")
2820 / IP(dst="10.10.10.10", src="11.11.11.11")
2821 / UDP(sport=1234, dport=1234)
2822 / Raw(b"\xa5" * 100)
2823 )
2824 p_core2 = (
2825 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2826 / MPLS(label=56, ttl=64)
2827 / Raw(b"\x01" * 4)
2828 / Ether(src="00:00:de:ad:ba:b2", dst="00:00:de:ad:be:ef") # PW CW
2829 / IP(dst="10.10.10.10", src="11.11.11.12")
2830 / UDP(sport=1234, dport=1234)
2831 / Raw(b"\xa5" * 100)
2832 )
Neale Rannsda78f952017-05-24 09:15:43 -07002833
2834 #
2835 # The BD is learning, so send in one of each packet to learn
2836 #
Neale Rannsda78f952017-05-24 09:15:43 -07002837
Neale Ranns1dbcf302019-07-19 11:44:53 +00002838 # 2 packets due to BD flooding
2839 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2840 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002841
Neale Ranns1dbcf302019-07-19 11:44:53 +00002842 # we've learnt this so expect it be be forwarded not flooded
2843 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2844 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2845 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002846
Neale Ranns1dbcf302019-07-19 11:44:53 +00002847 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2848 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2849 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002850
2851 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002852 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002853 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002854 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002855 self.verify_capture_tunneled_ethernet(
2856 rx, p_cust1 * NUM_PKTS, [VppMplsLabel(42)]
2857 )
Neale Rannsda78f952017-05-24 09:15:43 -07002858
Neale Ranns1dbcf302019-07-19 11:44:53 +00002859 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002860 self.verify_capture_tunneled_ethernet(
2861 rx, p_cust2 * NUM_PKTS, [VppMplsLabel(43)]
2862 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002863
2864 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2865 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2866
Neale Rannsda78f952017-05-24 09:15:43 -07002867 #
2868 # remove interfaces from customers bridge-domain
2869 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002870 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002871 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0
2872 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002873 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002874 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0
2875 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002876 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002877 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0
2878 )
Neale Rannsda78f952017-05-24 09:15:43 -07002879
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002880
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002881if __name__ == "__main__":
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002882 unittest.main(testRunner=VppTestRunner)