blob: daa0d967d2ed778664e1d1a04ed5c3132a266e4a [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
Neale Ranns8fe8cc22016-11-01 10:05:08 +00004
Dave Wallace8800f732023-08-31 00:47:44 -04005from framework import VppTestCase
6from asfframework import VppTestRunner, tag_fixme_vpp_workers
7from vpp_ip import INVALID_INDEX
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02008from vpp_ip_route import (
9 VppIpRoute,
10 VppRoutePath,
11 VppMplsRoute,
12 VppMplsIpBind,
13 VppIpMRoute,
14 VppMRoutePath,
15 VppIpTable,
16 VppMplsTable,
17 VppMplsLabel,
18 MplsLspMode,
19 find_mpls_route,
20 FibPathProto,
21 FibPathType,
22 FibPathFlags,
23 VppMplsLabel,
24 MplsLspMode,
25)
Neale Ranns0f26c5a2017-03-01 15:12:11 -080026from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns990f6942020-10-20 07:20:17 +000027from vpp_papi import VppEnum
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000028from config import config
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(
Vladislav Grishenko302db472024-01-24 16:17:23 +0500192 self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, payload_size=None, n=257
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200193 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100194 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000195 pkts = []
Vladislav Grishenko302db472024-01-24 16:17:23 +0500196 for i in range(0, n):
197 dst = dst_ip[i % len(dst_ip)] if isinstance(dst_ip, list) else dst_ip
Klement Sekeradab231a2016-12-21 08:50:14 +0100198 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000199 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200200 p = (
201 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
Vladislav Grishenko302db472024-01-24 16:17:23 +0500202 / IP(src=src_if.remote_ip4, dst=dst, ttl=ip_ttl, tos=ip_dscp)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200203 / UDP(sport=1234, dport=1234)
204 / Raw(payload)
205 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000206 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200207 if payload_size:
208 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000209 pkts.append(p)
210 return pkts
211
Vladislav Grishenko302db472024-01-24 16:17:23 +0500212 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, n=257):
Neale Ranns31ed7442018-02-23 05:29:09 -0800213 self.reset_packet_infos()
214 pkts = []
Vladislav Grishenko302db472024-01-24 16:17:23 +0500215 for i in range(0, n):
216 dst = dst_ip[i % len(dst_ip)] if isinstance(dst_ip, list) else dst_ip
Neale Ranns31ed7442018-02-23 05:29:09 -0800217 info = self.create_packet_info(src_if, src_if)
218 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200219 p = (
220 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
Vladislav Grishenko302db472024-01-24 16:17:23 +0500221 / IPv6(src=src_if.remote_ip6, dst=dst, hlim=ip_ttl, tc=ip_dscp)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 / UDP(sport=1234, dport=1234)
223 / Raw(payload)
224 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800225 info.data = p.copy()
226 pkts.append(p)
227 return pkts
228
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200229 def create_stream_labelled_ip6(
230 self, src_if, mpls_labels, hlim=64, dst_ip=None, ping=0, ip_itf=None
231 ):
Neale Ranns31426c62017-05-24 10:32:58 -0700232 if dst_ip is None:
233 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100234 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000235 pkts = []
236 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100237 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000238 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800239 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
240 for l in mpls_labels:
241 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
242
Neale Rannsf478f752022-02-17 15:41:32 +0000243 if ping:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200244 p = p / (
245 IPv6(src=ip_itf.remote_ip6, dst=ip_itf.local_ip6)
246 / ICMPv6EchoRequest()
247 )
Neale Rannsf478f752022-02-17 15:41:32 +0000248 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200249 p = p / (
250 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim)
251 / UDP(sport=1234, dport=1234)
252 / Raw(payload)
253 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000254 info.data = p.copy()
255 pkts.append(p)
256 return pkts
257
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200258 def verify_capture_ip4(
259 self, src_if, capture, sent, ping_resp=0, ip_ttl=None, ip_dscp=0
260 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000261 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700262 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000263
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000264 self.assertEqual(len(capture), len(sent))
265
266 for i in range(len(capture)):
267 tx = sent[i]
268 rx = capture[i]
269
270 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000271 eth = rx[Ether]
272 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000273
274 tx_ip = tx[IP]
275 rx_ip = rx[IP]
276
Neale Rannscb630ff2016-12-14 13:31:29 +0100277 if not ping_resp:
278 self.assertEqual(rx_ip.src, tx_ip.src)
279 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800280 self.assertEqual(rx_ip.tos, ip_dscp)
281 if not ip_ttl:
282 # IP processing post pop has decremented the TTL
283 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
284 else:
285 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100286 else:
287 self.assertEqual(rx_ip.src, tx_ip.dst)
288 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000289
290 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000291 raise
292
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 def verify_capture_labelled_ip4(
294 self, src_if, capture, sent, mpls_labels, ip_ttl=None
295 ):
Neale Rannsad422ed2016-11-02 14:20:04 +0000296 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700297 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000298
299 self.assertEqual(len(capture), len(sent))
300
301 for i in range(len(capture)):
302 tx = sent[i]
303 rx = capture[i]
304 tx_ip = tx[IP]
305 rx_ip = rx[IP]
306
Neale Ranns31ed7442018-02-23 05:29:09 -0800307 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000308
309 self.assertEqual(rx_ip.src, tx_ip.src)
310 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800311 if not ip_ttl:
312 # IP processing post pop has decremented the TTL
313 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
314 else:
315 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000316
317 except:
318 raise
319
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200320 def verify_capture_labelled_ip6(
321 self, src_if, capture, sent, mpls_labels, ip_ttl=None
322 ):
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 try:
324 capture = verify_filter(capture, sent)
325
326 self.assertEqual(len(capture), len(sent))
327
328 for i in range(len(capture)):
329 tx = sent[i]
330 rx = capture[i]
331 tx_ip = tx[IPv6]
332 rx_ip = rx[IPv6]
333
334 verify_mpls_stack(self, rx, mpls_labels)
335
336 self.assertEqual(rx_ip.src, tx_ip.src)
337 self.assertEqual(rx_ip.dst, tx_ip.dst)
338 if not ip_ttl:
339 # IP processing post pop has decremented the TTL
340 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
341 else:
342 self.assertEqual(rx_ip.hlim, ip_ttl)
343
344 except:
345 raise
346
347 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000348 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700349 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000350
351 self.assertEqual(len(capture), len(sent))
352
353 for i in range(len(capture)):
354 tx = sent[i]
355 rx = capture[i]
356 tx_ip = tx[IP]
357 rx_ip = rx[IP]
358
Neale Ranns31ed7442018-02-23 05:29:09 -0800359 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000360
361 self.assertEqual(rx_ip.src, tx_ip.src)
362 self.assertEqual(rx_ip.dst, tx_ip.dst)
363 # IP processing post pop has decremented the TTL
364 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
365
366 except:
367 raise
368
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200369 def verify_capture_labelled(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000370 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700371 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000372
373 self.assertEqual(len(capture), len(sent))
374
375 for i in range(len(capture)):
376 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800377 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000378 except:
379 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000380
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200381 def verify_capture_ip6(
382 self, src_if, capture, sent, ip_hlim=None, ip_dscp=0, ping_resp=0
383 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000384 try:
385 self.assertEqual(len(capture), len(sent))
386
387 for i in range(len(capture)):
388 tx = sent[i]
389 rx = capture[i]
390
391 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000392 eth = rx[Ether]
393 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000394
395 tx_ip = tx[IPv6]
396 rx_ip = rx[IPv6]
397
Neale Rannsf478f752022-02-17 15:41:32 +0000398 if not ping_resp:
399 self.assertEqual(rx_ip.src, tx_ip.src)
400 self.assertEqual(rx_ip.dst, tx_ip.dst)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Rannsf478f752022-02-17 15:41:32 +0000402 # IP processing post pop has decremented the TTL
403 if not ip_hlim:
404 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
405 else:
406 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns31ed7442018-02-23 05:29:09 -0800407 else:
Neale Rannsf478f752022-02-17 15:41:32 +0000408 self.assertEqual(rx_ip.src, tx_ip.dst)
409 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000410 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000411 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000412
Neale Ranns62fe07c2017-10-31 12:28:22 -0700413 def verify_capture_ip6_icmp(self, src_if, capture, sent):
414 try:
Neale Ranns5c6dd172022-02-17 09:08:47 +0000415 # rate limited ICMP
416 self.assertTrue(len(capture) <= len(sent))
Neale Ranns62fe07c2017-10-31 12:28:22 -0700417
418 for i in range(len(capture)):
419 tx = sent[i]
420 rx = capture[i]
421
422 # the rx'd packet has the MPLS label popped
423 eth = rx[Ether]
424 self.assertEqual(eth.type, 0x86DD)
425
426 tx_ip = tx[IPv6]
427 rx_ip = rx[IPv6]
428
429 self.assertEqual(rx_ip.dst, tx_ip.src)
430 # ICMP sourced from the interface's address
431 self.assertEqual(rx_ip.src, src_if.local_ip6)
432 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200433 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700434
435 icmp = rx[ICMPv6TimeExceeded]
436
437 except:
438 raise
439
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200440 def verify_capture_fragmented_labelled_ip4(
441 self, src_if, capture, sent, mpls_labels, ip_ttl=None
442 ):
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530443 try:
444 capture = verify_filter(capture, sent)
445
446 for i in range(len(capture)):
447 tx = sent[0]
448 rx = capture[i]
449 tx_ip = tx[IP]
450 rx_ip = rx[IP]
451
452 verify_mpls_stack(self, rx, mpls_labels)
453
454 self.assertEqual(rx_ip.src, tx_ip.src)
455 self.assertEqual(rx_ip.dst, tx_ip.dst)
456 if not ip_ttl:
457 # IP processing post pop has decremented the TTL
458 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
459 else:
460 self.assertEqual(rx_ip.ttl, ip_ttl)
461
462 except:
463 raise
464
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200465 def verify_capture_fragmented_labelled_ip6(
466 self, src_if, capture, sent, mpls_labels, ip_ttl=None
467 ):
Neale Rannsec5371e2022-03-04 11:45:41 +0000468 try:
469 capture = verify_filter(capture, sent)
470
471 for i in range(len(capture)):
472 tx = sent[0]
473 rx = capture[i]
474 tx_ip = tx[IPv6]
475 rx.show()
476 rx_ip = IPv6(rx[MPLS].payload)
477 rx_ip.show()
478
479 verify_mpls_stack(self, rx, mpls_labels)
480
481 self.assertEqual(rx_ip.src, tx_ip.src)
482 self.assertEqual(rx_ip.dst, tx_ip.dst)
483 if not ip_ttl:
484 # IP processing post pop has decremented the hop-limit
485 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
486 else:
487 self.assertEqual(rx_ip.hlim, ip_ttl)
488 except:
489 raise
490
Neale Rannsad422ed2016-11-02 14:20:04 +0000491 def test_swap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200492 """MPLS label swap tests"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000493
494 #
495 # A simple MPLS xconnect - eos label in label out
496 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200497 route_32_eos = VppMplsRoute(
498 self,
499 32,
500 1,
501 [
502 VppRoutePath(
503 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
504 )
505 ],
506 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000507 route_32_eos.add_vpp_config()
508
Neale Ranns775f73c2018-12-20 03:01:49 -0800509 self.assertTrue(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 find_mpls_route(
511 self,
512 0,
513 32,
514 1,
515 [
516 VppRoutePath(
517 self.pg0.remote_ip4,
518 self.pg0.sw_if_index,
519 labels=[VppMplsLabel(33)],
520 )
521 ],
522 )
523 )
Neale Ranns775f73c2018-12-20 03:01:49 -0800524
Neale Rannsad422ed2016-11-02 14:20:04 +0000525 #
526 # a stream that matches the route for 10.0.0.1
527 # PG0 is in the default table
528 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200529 tx = self.create_stream_labelled_ip4(
530 self.pg0, [VppMplsLabel(32, ttl=32, exp=1)]
531 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800532 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200533 self.verify_capture_labelled(
534 self.pg0, rx, tx, [VppMplsLabel(33, ttl=31, exp=1)]
535 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000536
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200537 self.assertEqual(route_32_eos.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700538
Neale Rannsad422ed2016-11-02 14:20:04 +0000539 #
540 # A simple MPLS xconnect - non-eos label in label out
541 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200542 route_32_neos = VppMplsRoute(
543 self,
544 32,
545 0,
546 [
547 VppRoutePath(
548 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
549 )
550 ],
551 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 route_32_neos.add_vpp_config()
553
554 #
555 # a stream that matches the route for 10.0.0.1
556 # PG0 is in the default table
557 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 tx = self.create_stream_labelled_ip4(
559 self.pg0, [VppMplsLabel(32, ttl=21, exp=7), VppMplsLabel(99)]
560 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800561 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200562 self.verify_capture_labelled(
563 self.pg0, rx, tx, [VppMplsLabel(33, ttl=20, exp=7), VppMplsLabel(99)]
564 )
565 self.assertEqual(route_32_neos.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000566
Neale Ranns31ed7442018-02-23 05:29:09 -0800567 #
568 # A simple MPLS xconnect - non-eos label in label out, uniform mode
569 #
570 route_42_neos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200571 self,
572 42,
573 0,
574 [
575 VppRoutePath(
576 self.pg0.remote_ip4,
577 self.pg0.sw_if_index,
578 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)],
579 )
580 ],
581 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800582 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000583
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200584 tx = self.create_stream_labelled_ip4(
585 self.pg0, [VppMplsLabel(42, ttl=21, exp=7), VppMplsLabel(99)]
586 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800587 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200588 self.verify_capture_labelled(
589 self.pg0, rx, tx, [VppMplsLabel(43, ttl=20, exp=7), VppMplsLabel(99)]
590 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000591
592 #
593 # An MPLS xconnect - EOS label in IP out
594 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 route_33_eos = VppMplsRoute(
596 self,
597 33,
598 1,
599 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
600 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000601 route_33_eos.add_vpp_config()
602
Neale Ranns31ed7442018-02-23 05:29:09 -0800603 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
604 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000605 self.verify_capture_ip4(self.pg0, rx, tx)
606
607 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700608 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700609 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200610 tx = self.create_stream_labelled_ip4(
611 self.pg0, [VppMplsLabel(33)], dst_ip=self.pg0.remote_ip4, n=65, chksum=1
612 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700613 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
614
615 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800616 # An MPLS xconnect - EOS label in IP out, uniform mode
617 #
618 route_3333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200619 self,
620 3333,
621 1,
622 [
623 VppRoutePath(
624 self.pg0.remote_ip4,
625 self.pg0.sw_if_index,
626 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
627 )
628 ],
629 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800630 route_3333_eos.add_vpp_config()
631
632 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200633 self.pg0, [VppMplsLabel(3333, ttl=55, exp=3)]
634 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800635 rx = self.send_and_expect(self.pg0, tx, self.pg0)
636 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
637 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200638 self.pg0, [VppMplsLabel(3333, ttl=66, exp=4)]
639 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800640 rx = self.send_and_expect(self.pg0, tx, self.pg0)
641 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
642
643 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700644 # An MPLS xconnect - EOS label in IPv6 out
645 #
646 route_333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200647 self,
648 333,
649 1,
650 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[])],
651 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
652 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700653 route_333_eos.add_vpp_config()
654
Neale Ranns31ed7442018-02-23 05:29:09 -0800655 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
656 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700657 self.verify_capture_ip6(self.pg0, rx, tx)
658
659 #
660 # disposed packets have an TTL expired
661 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200662 tx = self.create_stream_labelled_ip6(
663 self.pg0, [VppMplsLabel(333, ttl=64)], dst_ip=self.pg1.remote_ip6, hlim=1
664 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000665 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700666 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
667
668 #
669 # An MPLS xconnect - EOS label in IPv6 out w imp-null
670 #
671 route_334_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200672 self,
673 334,
674 1,
675 [
676 VppRoutePath(
677 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(3)]
678 )
679 ],
680 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
681 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700682 route_334_eos.add_vpp_config()
683
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200684 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334, ttl=64)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800685 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700686 self.verify_capture_ip6(self.pg0, rx, tx)
687
688 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800689 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
690 #
691 route_335_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 self,
693 335,
694 1,
695 [
696 VppRoutePath(
697 self.pg0.remote_ip6,
698 self.pg0.sw_if_index,
699 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
700 )
701 ],
702 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
703 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800704 route_335_eos.add_vpp_config()
705
706 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200707 self.pg0, [VppMplsLabel(335, ttl=27, exp=4)]
708 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800709 rx = self.send_and_expect(self.pg0, tx, self.pg0)
710 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
711
712 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700713 # disposed packets have an TTL expired
714 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200715 tx = self.create_stream_labelled_ip6(
716 self.pg0, [VppMplsLabel(334)], dst_ip=self.pg1.remote_ip6, hlim=0
717 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000718 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700719 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
720
721 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000722 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
723 # so this traffic should be dropped.
724 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200725 route_33_neos = VppMplsRoute(
726 self,
727 33,
728 0,
729 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
730 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000731 route_33_neos.add_vpp_config()
732
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200733 tx = self.create_stream_labelled_ip4(
734 self.pg0, [VppMplsLabel(33), VppMplsLabel(99)]
735 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800736 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200737 self.pg0, tx, "MPLS non-EOS packets popped and forwarded"
738 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000739
740 #
741 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800742 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000743 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 route_34_eos = VppMplsRoute(
745 self,
746 34,
747 1,
748 [
749 VppRoutePath(
750 "0.0.0.0",
751 0xFFFFFFFF,
752 nh_via_label=32,
753 labels=[VppMplsLabel(44), VppMplsLabel(45)],
754 )
755 ],
756 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000757 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700758 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000759
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200760 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800761 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200762 self.verify_capture_labelled(
763 self.pg0,
764 rx,
765 tx,
766 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(45, ttl=2)],
767 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000768
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200769 self.assertEqual(route_34_eos.get_stats_to()["packets"], 257)
770 self.assertEqual(route_32_neos.get_stats_via()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700771
Neale Ranns31ed7442018-02-23 05:29:09 -0800772 #
773 # A recursive EOS x-connect, which resolves through another x-connect
774 # in uniform mode
775 #
776 route_35_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200777 self,
778 35,
779 1,
780 [
781 VppRoutePath(
782 "0.0.0.0", 0xFFFFFFFF, nh_via_label=42, labels=[VppMplsLabel(44)]
783 )
784 ],
785 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800786 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000787
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200788 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(35, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800789 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200790 self.verify_capture_labelled(
791 self.pg0, rx, tx, [VppMplsLabel(43, ttl=2), VppMplsLabel(44, ttl=2)]
792 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000793
794 #
Matej Klottondeb69842016-12-09 15:05:46 +0100795 # A recursive non-EOS x-connect, which resolves through another
796 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000797 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200798 route_34_neos = VppMplsRoute(
799 self,
800 34,
801 0,
802 [
803 VppRoutePath(
804 "0.0.0.0",
805 0xFFFFFFFF,
806 nh_via_label=32,
807 labels=[VppMplsLabel(44), VppMplsLabel(46)],
808 )
809 ],
810 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000811 route_34_neos.add_vpp_config()
812
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200813 tx = self.create_stream_labelled_ip4(
814 self.pg0, [VppMplsLabel(34, ttl=45), VppMplsLabel(99)]
815 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800816 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100817 # it's the 2nd (counting from 0) label in the stack that is swapped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200818 self.verify_capture_labelled(
819 self.pg0,
820 rx,
821 tx,
822 [
823 VppMplsLabel(33),
824 VppMplsLabel(44),
825 VppMplsLabel(46, ttl=44),
826 VppMplsLabel(99),
827 ],
828 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000829
830 #
Matej Klottondeb69842016-12-09 15:05:46 +0100831 # an recursive IP route that resolves through the recursive non-eos
832 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000833 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200834 ip_10_0_0_1 = VppIpRoute(
835 self,
836 "10.0.0.1",
837 32,
838 [
839 VppRoutePath(
840 "0.0.0.0", 0xFFFFFFFF, nh_via_label=34, labels=[VppMplsLabel(55)]
841 )
842 ],
843 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000844 ip_10_0_0_1.add_vpp_config()
845
Neale Rannsad422ed2016-11-02 14:20:04 +0000846 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800847 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200848 self.verify_capture_labelled_ip4(
849 self.pg0,
850 rx,
851 tx,
852 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(55)],
853 )
854 self.assertEqual(ip_10_0_0_1.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000855
856 ip_10_0_0_1.remove_vpp_config()
857 route_34_neos.remove_vpp_config()
858 route_34_eos.remove_vpp_config()
859 route_33_neos.remove_vpp_config()
860 route_33_eos.remove_vpp_config()
861 route_32_neos.remove_vpp_config()
862 route_32_eos.remove_vpp_config()
863
864 def test_bind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200865 """MPLS Local Label Binding test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000866
867 #
868 # Add a non-recursive route with a single out label
869 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200870 route_10_0_0_1 = VppIpRoute(
871 self,
872 "10.0.0.1",
873 32,
874 [
875 VppRoutePath(
876 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
877 )
878 ],
879 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000880 route_10_0_0_1.add_vpp_config()
881
882 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800883 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000884 binding.add_vpp_config()
885
886 # non-EOS stream
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200887 tx = self.create_stream_labelled_ip4(
888 self.pg0, [VppMplsLabel(44), VppMplsLabel(99)]
889 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800890 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200891 self.verify_capture_labelled(
892 self.pg0, rx, tx, [VppMplsLabel(45, ttl=63), VppMplsLabel(99)]
893 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000894
895 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800896 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
897 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200898 self.verify_capture_labelled(self.pg0, rx, tx, [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000899
900 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000901 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800902 rx = self.send_and_expect(self.pg0, tx, self.pg0)
903 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000904
905 #
906 # cleanup
907 #
908 binding.remove_vpp_config()
909 route_10_0_0_1.remove_vpp_config()
910
911 def test_imposition(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200912 """MPLS label imposition test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000913
914 #
915 # Add a non-recursive route with a single out label
916 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200917 route_10_0_0_1 = VppIpRoute(
918 self,
919 "10.0.0.1",
920 32,
921 [
922 VppRoutePath(
923 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
924 )
925 ],
926 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000927 route_10_0_0_1.add_vpp_config()
928
929 #
930 # a stream that matches the route for 10.0.0.1
931 # PG0 is in the default table
932 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000933 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800934 rx = self.send_and_expect(self.pg0, tx, self.pg0)
935 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000936
937 #
938 # Add a non-recursive route with a 3 out labels
939 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200940 route_10_0_0_2 = VppIpRoute(
941 self,
942 "10.0.0.2",
943 32,
944 [
945 VppRoutePath(
946 self.pg0.remote_ip4,
947 self.pg0.sw_if_index,
948 labels=[VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
949 )
950 ],
951 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000952 route_10_0_0_2.add_vpp_config()
953
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200954 tx = self.create_stream_ip4(self.pg0, "10.0.0.2", ip_ttl=44, ip_dscp=0xFF)
Neale Ranns31ed7442018-02-23 05:29:09 -0800955 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200956 self.verify_capture_labelled_ip4(
957 self.pg0,
958 rx,
959 tx,
960 [VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
961 ip_ttl=43,
962 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000963
Neale Ranns31ed7442018-02-23 05:29:09 -0800964 #
965 # Add a non-recursive route with a single out label in uniform mode
966 #
967 route_10_0_0_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 self,
969 "10.0.0.3",
970 32,
971 [
972 VppRoutePath(
973 self.pg0.remote_ip4,
974 self.pg0.sw_if_index,
975 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
976 )
977 ],
978 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800979 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000980
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200981 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -0800982 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200983 self.verify_capture_labelled_ip4(
984 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
985 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800986
987 #
988 # Add a IPv6 non-recursive route with a single out label in
989 # uniform mode
990 #
991 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 self,
993 "2001::3",
994 128,
995 [
996 VppRoutePath(
997 self.pg0.remote_ip6,
998 self.pg0.sw_if_index,
999 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
1000 )
1001 ],
1002 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001003 route_2001_3.add_vpp_config()
1004
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001005 tx = self.create_stream_ip6(self.pg0, "2001::3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -08001006 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001007 self.verify_capture_labelled_ip6(
1008 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
1009 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001010
1011 #
Matej Klottondeb69842016-12-09 15:05:46 +01001012 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +00001013 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001014 route_11_0_0_1 = VppIpRoute(
1015 self,
1016 "11.0.0.1",
1017 32,
1018 [VppRoutePath("10.0.0.1", 0xFFFFFFFF, labels=[VppMplsLabel(44)])],
1019 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001020 route_11_0_0_1.add_vpp_config()
1021
1022 #
1023 # a stream that matches the route for 11.0.0.1, should pick up
1024 # the label stack for 11.0.0.1 and 10.0.0.1
1025 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001026 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001027 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001028 self.verify_capture_labelled_ip4(
1029 self.pg0, rx, tx, [VppMplsLabel(32), VppMplsLabel(44)]
1030 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001031
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 self.assertEqual(route_11_0_0_1.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001033
Neale Rannsad422ed2016-11-02 14:20:04 +00001034 #
1035 # add a recursive path, with 2 labels, via the 3 label route
1036 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001037 route_11_0_0_2 = VppIpRoute(
1038 self,
1039 "11.0.0.2",
1040 32,
1041 [
1042 VppRoutePath(
1043 "10.0.0.2", 0xFFFFFFFF, labels=[VppMplsLabel(44), VppMplsLabel(45)]
1044 )
1045 ],
1046 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001047 route_11_0_0_2.add_vpp_config()
1048
1049 #
1050 # a stream that matches the route for 11.0.0.1, should pick up
1051 # the label stack for 11.0.0.1 and 10.0.0.1
1052 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001053 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -08001054 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001055 self.verify_capture_labelled_ip4(
1056 self.pg0,
1057 rx,
1058 tx,
1059 [
1060 VppMplsLabel(32),
1061 VppMplsLabel(33),
1062 VppMplsLabel(34),
1063 VppMplsLabel(44),
1064 VppMplsLabel(45),
1065 ],
1066 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001067
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001068 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001069
1070 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001071 self.verify_capture_labelled_ip4(
1072 self.pg0,
1073 rx,
1074 tx,
1075 [
1076 VppMplsLabel(32),
1077 VppMplsLabel(33),
1078 VppMplsLabel(34),
1079 VppMplsLabel(44),
1080 VppMplsLabel(45),
1081 ],
1082 )
Neale Ranns008dbe12018-09-07 09:32:36 -07001083
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001084 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 514)
Neale Ranns008dbe12018-09-07 09:32:36 -07001085
Neale Rannsad422ed2016-11-02 14:20:04 +00001086 #
1087 # cleanup
1088 #
1089 route_11_0_0_2.remove_vpp_config()
1090 route_11_0_0_1.remove_vpp_config()
1091 route_10_0_0_2.remove_vpp_config()
1092 route_10_0_0_1.remove_vpp_config()
1093
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301094 def test_imposition_fragmentation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001095 """MPLS label imposition fragmentation test"""
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301096
1097 #
1098 # Add a ipv4 non-recursive route with a single out label
1099 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001100 route_10_0_0_1 = VppIpRoute(
1101 self,
1102 "10.0.0.1",
1103 32,
1104 [
1105 VppRoutePath(
1106 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1107 )
1108 ],
1109 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301110 route_10_0_0_1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001111 route_1000_1 = VppIpRoute(
1112 self,
1113 "1000::1",
1114 128,
1115 [
1116 VppRoutePath(
1117 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1118 )
1119 ],
1120 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001121 route_1000_1.add_vpp_config()
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301122
1123 #
1124 # a stream that matches the route for 10.0.0.1
1125 # PG0 is in the default table
1126 #
1127 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
1128 for i in range(0, 257):
1129 self.extend_packet(tx[i], 10000)
1130
1131 #
1132 # 5 fragments per packet (257*5=1285)
1133 #
1134 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001135 self.verify_capture_fragmented_labelled_ip4(
1136 self.pg0, rx, tx, [VppMplsLabel(32)]
1137 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301138
Neale Rannsec5371e2022-03-04 11:45:41 +00001139 # packets with DF bit set generate ICMP
1140 for t in tx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001141 t[IP].flags = "DF"
Neale Rannsec5371e2022-03-04 11:45:41 +00001142 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1143
1144 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001145 self.assertEqual(icmptypes[rx[ICMP].type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001146 self.assertEqual(
1147 icmpcodes[rx[ICMP].type][rx[ICMP].code], "fragmentation-needed"
1148 )
Neale Rannsfbc633f2022-03-18 13:05:09 +00001149 # the link MTU is 9000, the MPLS over head is 4 bytes
1150 self.assertEqual(rx[ICMP].nexthopmtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001151
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001152 self.assertEqual(
Neale Rannse22a7042022-08-09 03:03:29 +00001153 self.statistics.get_err_counter("/err/mpls-frag/dont_fragment_set"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001154 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
Vladislav Grishenko302db472024-01-24 16:17:23 +05001347 def test_tunnel_ecmp(self):
1348 """MPLS Tunnel Tests - ECMP"""
1349
1350 #
1351 # Create a tunnel with multiple paths and labels
1352 #
1353 self.pg0.generate_remote_hosts(2)
1354 self.pg0.configure_ipv4_neighbors()
1355 mpls_tun = VppMPLSTunnelInterface(
1356 self,
1357 [
1358 VppRoutePath(
1359 self.pg0.remote_hosts[0].ip4,
1360 self.pg0.sw_if_index,
1361 labels=[VppMplsLabel(3)],
1362 ),
1363 VppRoutePath(
1364 self.pg0.remote_hosts[1].ip4,
1365 self.pg0.sw_if_index,
1366 labels=[VppMplsLabel(44)],
1367 ),
1368 ],
1369 )
1370 mpls_tun.add_vpp_config()
1371 mpls_tun.admin_up()
1372
1373 self.vapi.cli("clear trace")
1374 pkts = self.create_stream_ip4(
1375 self.pg0, ["10.0.0.%d" % i for i in range(NUM_PKTS)], n=NUM_PKTS
1376 )
1377
1378 def send_and_expect_mpls_lb(pkts, path_labels, min_ratio):
1379 self.pg0.add_stream(pkts)
1380
1381 self.pg_enable_capture(self.pg_interfaces)
1382 self.pg_start()
1383
1384 rx = self.pg0.get_capture()
1385
1386 paths = {}
1387 for packet in rx:
1388 eth = packet[Ether]
1389 self.assertEqual(eth.type, 0x8847)
1390
1391 mpls = packet[MPLS]
1392 labels = []
1393 while True:
1394 labels.append(mpls.label)
1395 if mpls.s == 1:
1396 break
1397 mpls = mpls[MPLS].payload
1398 self.assertIn(labels, path_labels)
1399
1400 key = "{}-{}".format(eth.dst, "-".join(str(i) for i in labels))
1401 paths[key] = paths.get(key, 0) + 1
1402
1403 #
1404 # Check distribution over multiple mpls paths
1405 #
1406 self.assertEqual(len(paths), len(path_labels))
1407 for n in paths.values():
1408 self.assertGreaterEqual(n, NUM_PKTS / len(paths) * min_ratio)
1409
1410 #
1411 # Add labelled route through the new tunnel,
1412 # traffic should be balanced over all tunnel paths only.
1413 #
1414 route_10_0_0_0 = VppIpRoute(
1415 self,
1416 "10.0.0.0",
1417 16,
1418 [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index, labels=[33])],
1419 )
1420 route_10_0_0_0.add_vpp_config()
1421 send_and_expect_mpls_lb(pkts, [[33], [44, 33]], 0.85)
1422
1423 #
1424 # Add labelled multipath route through the new tunnel,
1425 # traffic should be balanced over both paths first and
1426 # then over all tunnel paths.
1427 #
1428 route_10_0_0_0 = VppIpRoute(
1429 self,
1430 "10.0.0.0",
1431 16,
1432 [
1433 VppRoutePath("0.0.0.1", mpls_tun._sw_if_index, labels=[33]),
1434 VppRoutePath("0.0.0.2", mpls_tun._sw_if_index, labels=[34]),
1435 ],
1436 )
1437 route_10_0_0_0.add_vpp_config()
1438 send_and_expect_mpls_lb(pkts, [[33], [44, 33], [34], [44, 34]], 0.70)
1439
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001440 def test_mpls_tunnel_many(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001441 """MPLS Multiple Tunnels"""
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001442
Neale Ranns397228d2021-10-21 12:02:53 +00001443 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001444 mpls_tun = VppMPLSTunnelInterface(
1445 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 [
1447 VppRoutePath(
1448 self.pg0.remote_ip4,
1449 self.pg0.sw_if_index,
1450 labels=[
1451 VppMplsLabel(44, ttl=32),
1452 VppMplsLabel(46, MplsLspMode.UNIFORM),
1453 ],
1454 )
1455 ],
1456 )
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001457 mpls_tun.add_vpp_config()
1458 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001459 for ii in range(100):
1460 mpls_tun = VppMPLSTunnelInterface(
1461 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001462 [
1463 VppRoutePath(
1464 self.pg0.remote_ip4,
1465 self.pg0.sw_if_index,
1466 labels=[
1467 VppMplsLabel(44, ttl=32),
1468 VppMplsLabel(46, MplsLspMode.UNIFORM),
1469 ],
1470 )
1471 ],
1472 is_l2=1,
1473 )
Neale Ranns397228d2021-10-21 12:02:53 +00001474 mpls_tun.add_vpp_config()
1475 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001476
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001477 def test_v4_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001478 """MPLS V4 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001479
1480 #
1481 # The first test case has an MPLS TTL of 0
1482 # all packet should be dropped
1483 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001484 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0, ttl=0)])
1485 self.send_and_assert_no_replies(self.pg0, tx, "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001486
1487 #
1488 # a stream with a non-zero MPLS TTL
1489 # PG0 is in the default table
1490 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001491 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1492 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001493 self.verify_capture_ip4(self.pg0, rx, tx)
1494
1495 #
1496 # a stream with a non-zero MPLS TTL
1497 # PG1 is in table 1
1498 # we are ensuring the post-pop lookup occurs in the VRF table
1499 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001500 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1501 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1502 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001503
1504 def test_v6_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001505 """MPLS V6 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001506
1507 #
1508 # a stream with a non-zero MPLS TTL
1509 # PG0 is in the default table
1510 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001511 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1512 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001513 self.verify_capture_ip6(self.pg0, rx, tx)
1514
1515 #
1516 # a stream with a non-zero MPLS TTL
1517 # PG1 is in table 1
1518 # we are ensuring the post-pop lookup occurs in the VRF table
1519 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001520 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1521 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001522 self.verify_capture_ip6(self.pg0, rx, tx)
1523
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001524 @unittest.skipIf(
1525 "ping" in config.excluded_plugins, "Exclude tests requiring Ping plugin"
1526 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001527 def test_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001528 """MPLS Deagg"""
Neale Rannscb630ff2016-12-14 13:31:29 +01001529
1530 #
1531 # A de-agg route - next-hop lookup in default table
1532 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001533 route_34_eos = VppMplsRoute(
1534 self, 34, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
1535 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001536 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)], ping=1, ip_itf=self.pg0
1544 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001545 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001546 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1547
1548 #
1549 # A de-agg route - next-hop lookup in non-default table
1550 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001551 route_35_eos = VppMplsRoute(
1552 self, 35, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
1553 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001554 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001555 route_356_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001556 self,
1557 356,
1558 1,
1559 [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=1)],
1560 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1561 )
Neale Rannsf478f752022-02-17 15:41:32 +00001562 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001563
1564 #
1565 # ping an interface in the non-default table
1566 # PG0 is in the default table. packet arrive labelled in the
1567 # default table and egress unlabelled in the non-default
1568 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001569 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001570 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1571 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001572 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001573 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001574 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001575 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1
1576 )
Neale Rannsf478f752022-02-17 15:41:32 +00001577 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1578 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001579
Neale Ranns6af1c042017-05-26 03:48:53 -07001580 #
1581 # Double pop
1582 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001583 route_36_neos = VppMplsRoute(self, 36, 0, [VppRoutePath("0.0.0.0", 0xFFFFFFFF)])
Neale Ranns6af1c042017-05-26 03:48:53 -07001584 route_36_neos.add_vpp_config()
1585
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001586 tx = self.create_stream_labelled_ip4(
1587 self.pg0, [VppMplsLabel(36), VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1588 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001589 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001590 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1591
1592 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001593 route_35_eos.remove_vpp_config()
1594 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001595
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001596 def test_interface_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001597 """MPLS Interface Receive"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001598
1599 #
1600 # Add a non-recursive route that will forward the traffic
1601 # post-interface-rx
1602 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001603 route_10_0_0_1 = VppIpRoute(
1604 self,
1605 "10.0.0.1",
1606 32,
1607 table_id=1,
1608 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1609 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001610 route_10_0_0_1.add_vpp_config()
1611
1612 #
1613 # An interface receive label that maps traffic to RX on interface
1614 # pg1
1615 # by injecting the packet in on pg0, which is in table 0
1616 # doing an interface-rx on pg1 and matching a route in table 1
1617 # if the packet egresses, then we must have swapped to pg1
1618 # so as to have matched the route in table 1
1619 #
Neale Ranns097fa662018-05-01 05:17:55 -07001620 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001621 self,
1622 34,
1623 1,
1624 [
1625 VppRoutePath(
1626 "0.0.0.0",
1627 self.pg1.sw_if_index,
1628 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1629 )
1630 ],
1631 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001632 route_34_eos.add_vpp_config()
1633
1634 #
1635 # ping an interface in the default table
1636 # PG0 is in the default table
1637 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001638 tx = self.create_stream_labelled_ip4(
1639 self.pg0, [VppMplsLabel(34)], dst_ip="10.0.0.1"
1640 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001641 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001642 self.verify_capture_ip4(self.pg1, rx, tx)
1643
1644 def test_mcast_mid_point(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001645 """MPLS Multicast Mid Point"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001646
1647 #
1648 # Add a non-recursive route that will forward the traffic
1649 # post-interface-rx
1650 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001651 route_10_0_0_1 = VppIpRoute(
1652 self,
1653 "10.0.0.1",
1654 32,
1655 table_id=1,
1656 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1657 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001658 route_10_0_0_1.add_vpp_config()
1659
1660 #
1661 # Add a mcast entry that replicate to pg2 and pg3
1662 # and replicate to a interface-rx (like a bud node would)
1663 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001664 route_3400_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001665 self,
1666 3400,
1667 1,
1668 [
1669 VppRoutePath(
1670 self.pg2.remote_ip4,
1671 self.pg2.sw_if_index,
1672 labels=[VppMplsLabel(3401)],
1673 ),
1674 VppRoutePath(
1675 self.pg3.remote_ip4,
1676 self.pg3.sw_if_index,
1677 labels=[VppMplsLabel(3402)],
1678 ),
1679 VppRoutePath(
1680 "0.0.0.0",
1681 self.pg1.sw_if_index,
1682 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1683 ),
1684 ],
1685 is_multicast=1,
1686 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001687 route_3400_eos.add_vpp_config()
1688
1689 #
1690 # ping an interface in the default table
1691 # PG0 is in the default table
1692 #
1693 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 tx = self.create_stream_labelled_ip4(
1695 self.pg0, [VppMplsLabel(3400, ttl=64)], n=257, dst_ip="10.0.0.1"
1696 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001697 self.pg0.add_stream(tx)
1698
1699 self.pg_enable_capture(self.pg_interfaces)
1700 self.pg_start()
1701
1702 rx = self.pg1.get_capture(257)
1703 self.verify_capture_ip4(self.pg1, rx, tx)
1704
1705 rx = self.pg2.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001706 self.verify_capture_labelled(self.pg2, rx, tx, [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001707 rx = self.pg3.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001708 self.verify_capture_labelled(self.pg3, rx, tx, [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001709
1710 def test_mcast_head(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001711 """MPLS Multicast Head-end"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001712
Neale Ranns990f6942020-10-20 07:20:17 +00001713 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1714 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1715
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001716 #
1717 # Create a multicast tunnel with two replications
1718 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001719 mpls_tun = VppMPLSTunnelInterface(
1720 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001721 [
1722 VppRoutePath(
1723 self.pg2.remote_ip4, self.pg2.sw_if_index, labels=[VppMplsLabel(42)]
1724 ),
1725 VppRoutePath(
1726 self.pg3.remote_ip4, self.pg3.sw_if_index, labels=[VppMplsLabel(43)]
1727 ),
1728 ],
1729 is_multicast=1,
1730 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001731 mpls_tun.add_vpp_config()
1732 mpls_tun.admin_up()
1733
1734 #
1735 # add an unlabelled route through the new tunnel
1736 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001737 route_10_0_0_3 = VppIpRoute(
1738 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1739 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001740 route_10_0_0_3.add_vpp_config()
1741
1742 self.vapi.cli("clear trace")
1743 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1744 self.pg0.add_stream(tx)
1745
1746 self.pg_enable_capture(self.pg_interfaces)
1747 self.pg_start()
1748
1749 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001750 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001751 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001752 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001753
1754 #
1755 # An an IP multicast route via the tunnel
1756 # A (*,G).
1757 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1758 #
1759 route_232_1_1_1 = VppIpMRoute(
1760 self,
1761 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001762 "232.1.1.1",
1763 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001764 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001765 [
1766 VppMRoutePath(
1767 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1768 ),
1769 VppMRoutePath(
1770 mpls_tun._sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1771 ),
1772 ],
1773 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001774 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001775 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001776
1777 self.vapi.cli("clear trace")
1778 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1779 self.pg0.add_stream(tx)
1780
1781 self.pg_enable_capture(self.pg_interfaces)
1782 self.pg_start()
1783
1784 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001785 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001786 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001787 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001788
Neale Ranns31426c62017-05-24 10:32:58 -07001789 def test_mcast_ip4_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001790 """MPLS IPv4 Multicast Tail"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001791
Neale Ranns990f6942020-10-20 07:20:17 +00001792 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1793 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1794
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001795 #
1796 # Add a multicast route that will forward the traffic
1797 # post-disposition
1798 #
1799 route_232_1_1_1 = VppIpMRoute(
1800 self,
1801 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 "232.1.1.1",
1803 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001804 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001805 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001806 paths=[
1807 VppMRoutePath(
1808 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1809 )
1810 ],
1811 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001812 route_232_1_1_1.add_vpp_config()
1813
1814 #
1815 # An interface receive label that maps traffic to RX on interface
1816 # pg1
1817 # by injecting the packet in on pg0, which is in table 0
1818 # doing an rpf-id and matching a route in table 1
1819 # if the packet egresses, then we must have matched the route in
1820 # table 1
1821 #
Neale Ranns097fa662018-05-01 05:17:55 -07001822 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001823 self,
1824 34,
1825 1,
1826 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001827 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001828 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1829 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001830
1831 route_34_eos.add_vpp_config()
1832
1833 #
1834 # Drop due to interface lookup miss
1835 #
1836 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001837 tx = self.create_stream_labelled_ip4(
1838 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=1
1839 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001840 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1841
1842 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001843 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001844 #
1845 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001846 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001847
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001848 tx = self.create_stream_labelled_ip4(
1849 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1850 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001851 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001852 self.verify_capture_ip4(self.pg1, rx, tx)
1853
1854 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001855 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001856 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001857 tx = self.create_stream_labelled_ip4(
1858 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=65, chksum=1
1859 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001860 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1861
1862 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001863 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001864 #
1865 route_232_1_1_1.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001866 tx = self.create_stream_labelled_ip4(
1867 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1868 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001869 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1870
Neale Ranns31426c62017-05-24 10:32:58 -07001871 def test_mcast_ip6_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001872 """MPLS IPv6 Multicast Tail"""
Neale Ranns31426c62017-05-24 10:32:58 -07001873
Neale Ranns990f6942020-10-20 07:20:17 +00001874 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1875 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1876
Neale Ranns31426c62017-05-24 10:32:58 -07001877 #
1878 # Add a multicast route that will forward the traffic
1879 # post-disposition
1880 #
1881 route_ff = VppIpMRoute(
1882 self,
1883 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001884 "ff01::1",
1885 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001886 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001887 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001888 paths=[
1889 VppMRoutePath(
1890 self.pg1.sw_if_index,
1891 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1892 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1893 )
1894 ],
1895 )
Neale Ranns31426c62017-05-24 10:32:58 -07001896 route_ff.add_vpp_config()
1897
1898 #
1899 # An interface receive label that maps traffic to RX on interface
1900 # pg1
1901 # by injecting the packet in on pg0, which is in table 0
1902 # doing an rpf-id and matching a route in table 1
1903 # if the packet egresses, then we must have matched the route in
1904 # table 1
1905 #
1906 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001907 self,
1908 34,
1909 1,
1910 [VppRoutePath("::", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001911 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001912 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1913 )
Neale Ranns31426c62017-05-24 10:32:58 -07001914
1915 route_34_eos.add_vpp_config()
1916
1917 #
1918 # Drop due to interface lookup miss
1919 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001920 tx = self.create_stream_labelled_ip6(
1921 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1922 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001923 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001924
1925 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001926 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001927 #
1928 route_ff.update_rpf_id(55)
1929
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001930 tx = self.create_stream_labelled_ip6(
1931 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1932 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001933 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001934 self.verify_capture_ip6(self.pg1, rx, tx)
1935
1936 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001937 # disposed packets have hop-limit = 1
1938 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001939 tx = self.create_stream_labelled_ip6(
1940 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1", hlim=1
1941 )
Neale Ranns5c6dd172022-02-17 09:08:47 +00001942 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001943 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001944
1945 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001946 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001947 #
1948 route_ff.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001949 tx = self.create_stream_labelled_ip6(
1950 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1951 )
Neale Ranns31426c62017-05-24 10:32:58 -07001952 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1953
Neale Rannsd5d7b962019-08-04 03:30:56 -07001954 def test_6pe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001955 """MPLS 6PE"""
Neale Rannsd5d7b962019-08-04 03:30:56 -07001956
1957 #
1958 # Add a non-recursive route with a single out label
1959 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001960 route_10_0_0_1 = VppIpRoute(
1961 self,
1962 "10.0.0.1",
1963 32,
1964 [
1965 VppRoutePath(
1966 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
1967 )
1968 ],
1969 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001970 route_10_0_0_1.add_vpp_config()
1971
1972 # bind a local label to the route
1973 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1974 binding.add_vpp_config()
1975
1976 #
1977 # a labelled v6 route that resolves through the v4
1978 #
1979 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001980 self,
1981 "2001::3",
1982 128,
1983 [VppRoutePath("10.0.0.1", INVALID_INDEX, labels=[VppMplsLabel(32)])],
1984 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001985 route_2001_3.add_vpp_config()
1986
1987 tx = self.create_stream_ip6(self.pg0, "2001::3")
1988 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1989
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001990 self.verify_capture_labelled_ip6(
1991 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32)]
1992 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001993
1994 #
1995 # and a v4 recursive via the v6
1996 #
1997 route_20_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001998 self,
1999 "20.0.0.3",
2000 32,
2001 [VppRoutePath("2001::3", INVALID_INDEX, labels=[VppMplsLabel(99)])],
2002 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07002003 route_20_3.add_vpp_config()
2004
2005 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
2006 rx = self.send_and_expect(self.pg0, tx, self.pg0)
2007
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002008 self.verify_capture_labelled_ip4(
2009 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32), VppMplsLabel(99)]
2010 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07002011
Neale Ranns53962fb2021-12-20 18:18:42 +00002012 def test_attached(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002013 """Attach Routes with Local Label"""
Neale Ranns53962fb2021-12-20 18:18:42 +00002014
2015 #
2016 # test that if a local label is associated with an attached/connected
2017 # prefix, that we can reach hosts in the prefix.
2018 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002019 binding = VppMplsIpBind(
2020 self, 44, self.pg0._local_ip4_subnet, self.pg0.local_ip4_prefix_len
2021 )
Neale Ranns53962fb2021-12-20 18:18:42 +00002022 binding.add_vpp_config()
2023
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002024 tx = (
Steven Luonge4238aa2024-04-19 09:49:20 -07002025 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002026 / MPLS(label=44, ttl=64)
2027 / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
2028 / UDP(sport=1234, dport=1234)
2029 / Raw(b"\xa5" * 100)
2030 )
Neale Ranns53962fb2021-12-20 18:18:42 +00002031 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
2032 for rx in rxs:
2033 # if there's an ARP then the label is linked to the glean
2034 # which is wrong.
2035 self.assertFalse(rx.haslayer(ARP))
2036 # it should be unicasted to the host
2037 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
2038 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
2039
Neale Ranns180279b2017-03-16 15:49:09 -04002040
2041class TestMPLSDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002042 """MPLS disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04002043
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002044 @classmethod
2045 def setUpClass(cls):
2046 super(TestMPLSDisabled, cls).setUpClass()
2047
2048 @classmethod
2049 def tearDownClass(cls):
2050 super(TestMPLSDisabled, cls).tearDownClass()
2051
Neale Ranns180279b2017-03-16 15:49:09 -04002052 def setUp(self):
2053 super(TestMPLSDisabled, self).setUp()
2054
2055 # create 2 pg interfaces
2056 self.create_pg_interfaces(range(2))
2057
Neale Ranns15002542017-09-10 04:39:11 -07002058 self.tbl = VppMplsTable(self, 0)
2059 self.tbl.add_vpp_config()
2060
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002061 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04002062 self.pg0.admin_up()
2063 self.pg0.config_ip4()
2064 self.pg0.resolve_arp()
2065 self.pg0.enable_mpls()
2066
2067 # PG 1 is not MPLS enabled
2068 self.pg1.admin_up()
2069
2070 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04002071 for i in self.pg_interfaces:
2072 i.unconfig_ip4()
2073 i.admin_down()
2074
Neale Ranns15002542017-09-10 04:39:11 -07002075 self.pg0.disable_mpls()
2076 super(TestMPLSDisabled, self).tearDown()
2077
Neale Ranns180279b2017-03-16 15:49:09 -04002078 def test_mpls_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079 """MPLS Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04002080
Neale Rannsde0b3b52021-06-15 12:43:12 +00002081 self.logger.info(self.vapi.cli("show mpls interface"))
2082 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2083 self.logger.info(self.vapi.cli("show mpls interface pg0"))
2084
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002085 tx = (
2086 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2087 / MPLS(label=32, ttl=64)
2088 / IPv6(src="2001::1", dst=self.pg0.remote_ip6)
2089 / UDP(sport=1234, dport=1234)
2090 / Raw(b"\xa5" * 100)
2091 )
Neale Ranns180279b2017-03-16 15:49:09 -04002092
2093 #
2094 # A simple MPLS xconnect - eos label in label out
2095 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002096 route_32_eos = VppMplsRoute(
2097 self,
2098 32,
2099 1,
2100 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[33])],
2101 )
Neale Ranns180279b2017-03-16 15:49:09 -04002102 route_32_eos.add_vpp_config()
2103
2104 #
2105 # PG1 does not forward IP traffic
2106 #
2107 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
2108
2109 #
2110 # MPLS enable PG1
2111 #
2112 self.pg1.enable_mpls()
2113
Neale Rannsde0b3b52021-06-15 12:43:12 +00002114 self.logger.info(self.vapi.cli("show mpls interface"))
2115 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2116
Neale Ranns180279b2017-03-16 15:49:09 -04002117 #
2118 # Now we get packets through
2119 #
2120 self.pg1.add_stream(tx)
2121 self.pg_enable_capture(self.pg_interfaces)
2122 self.pg_start()
2123
2124 rx = self.pg0.get_capture(1)
2125
2126 #
2127 # Disable PG1
2128 #
2129 self.pg1.disable_mpls()
2130
2131 #
2132 # PG1 does not forward IP traffic
2133 #
2134 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2135 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2136
2137
Neale Rannsf12a83f2017-04-18 09:09:40 -07002138class TestMPLSPIC(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002139 """MPLS Prefix-Independent Convergence (PIC) edge convergence"""
Neale Rannsf12a83f2017-04-18 09:09:40 -07002140
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002141 @classmethod
2142 def setUpClass(cls):
2143 super(TestMPLSPIC, cls).setUpClass()
2144
2145 @classmethod
2146 def tearDownClass(cls):
2147 super(TestMPLSPIC, cls).tearDownClass()
2148
Neale Rannsf12a83f2017-04-18 09:09:40 -07002149 def setUp(self):
2150 super(TestMPLSPIC, self).setUp()
2151
2152 # create 2 pg interfaces
2153 self.create_pg_interfaces(range(4))
2154
Neale Ranns15002542017-09-10 04:39:11 -07002155 mpls_tbl = VppMplsTable(self, 0)
2156 mpls_tbl.add_vpp_config()
2157 tbl4 = VppIpTable(self, 1)
2158 tbl4.add_vpp_config()
2159 tbl6 = VppIpTable(self, 1, is_ip6=1)
2160 tbl6.add_vpp_config()
2161
Neale Rannsf12a83f2017-04-18 09:09:40 -07002162 # core links
2163 self.pg0.admin_up()
2164 self.pg0.config_ip4()
2165 self.pg0.resolve_arp()
2166 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002167
Neale Rannsf12a83f2017-04-18 09:09:40 -07002168 self.pg1.admin_up()
2169 self.pg1.config_ip4()
2170 self.pg1.resolve_arp()
2171 self.pg1.enable_mpls()
2172
2173 # VRF (customer facing) link
2174 self.pg2.admin_up()
2175 self.pg2.set_table_ip4(1)
2176 self.pg2.config_ip4()
2177 self.pg2.resolve_arp()
2178 self.pg2.set_table_ip6(1)
2179 self.pg2.config_ip6()
2180 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002181
Neale Rannsf12a83f2017-04-18 09:09:40 -07002182 self.pg3.admin_up()
2183 self.pg3.set_table_ip4(1)
2184 self.pg3.config_ip4()
2185 self.pg3.resolve_arp()
2186 self.pg3.set_table_ip6(1)
2187 self.pg3.config_ip6()
2188 self.pg3.resolve_ndp()
2189
2190 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002191 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07002192 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002193 for i in self.pg_interfaces:
2194 i.unconfig_ip4()
2195 i.unconfig_ip6()
2196 i.set_table_ip4(0)
2197 i.set_table_ip6(0)
2198 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002199 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002200
2201 def test_mpls_ibgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002202 """MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002203
2204 1) setup many iBGP VPN routes via a pair of iBGP peers.
2205 2) Check EMCP forwarding to these peers
2206 3) withdraw the IGP route to one of these peers.
2207 4) check forwarding continues to the remaining peer
2208 """
2209
2210 #
2211 # IGP+LDP core routes
2212 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002213 core_10_0_0_45 = VppIpRoute(
2214 self,
2215 "10.0.0.45",
2216 32,
2217 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[45])],
2218 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002219 core_10_0_0_45.add_vpp_config()
2220
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002221 core_10_0_0_46 = VppIpRoute(
2222 self,
2223 "10.0.0.46",
2224 32,
2225 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[46])],
2226 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002227 core_10_0_0_46.add_vpp_config()
2228
2229 #
2230 # Lot's of VPN routes. We need more the 64 so VPP will build
2231 # the fast convergence indirection
2232 #
2233 vpn_routes = []
2234 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002235 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002236 dst = "192.168.1.%d" % ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002237 vpn_routes.append(
2238 VppIpRoute(
2239 self,
2240 dst,
2241 32,
2242 [
2243 VppRoutePath(
2244 "10.0.0.45",
2245 0xFFFFFFFF,
2246 labels=[145],
2247 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2248 ),
2249 VppRoutePath(
2250 "10.0.0.46",
2251 0xFFFFFFFF,
2252 labels=[146],
2253 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2254 ),
2255 ],
2256 table_id=1,
2257 )
2258 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002259 vpn_routes[ii].add_vpp_config()
2260
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002261 pkts.append(
2262 Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac)
2263 / IP(src=self.pg2.remote_ip4, dst=dst)
2264 / UDP(sport=1234, dport=1234)
2265 / Raw(b"\xa5" * 100)
2266 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002267
2268 #
2269 # Send the packet stream (one pkt to each VPN route)
2270 # - expect a 50-50 split of the traffic
2271 #
2272 self.pg2.add_stream(pkts)
2273 self.pg_enable_capture(self.pg_interfaces)
2274 self.pg_start()
2275
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002276 rx0 = self.pg0._get_capture(NUM_PKTS)
2277 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002278
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002279 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07002280 # with the split ratio, just as long as neither is 0
2281 self.assertNotEqual(0, len(rx0))
2282 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002283 self.assertEqual(
2284 len(pkts),
2285 len(rx0) + len(rx1),
2286 "Expected all (%s) packets across both ECMP paths. "
2287 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2288 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002289
2290 #
2291 # use a test CLI command to stop the FIB walk process, this
2292 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002293 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002294 #
2295 self.vapi.ppcli("test fib-walk-process disable")
2296
2297 #
2298 # Withdraw one of the IGP routes
2299 #
2300 core_10_0_0_46.remove_vpp_config()
2301
2302 #
2303 # now all packets should be forwarded through the remaining peer
2304 #
2305 self.vapi.ppcli("clear trace")
2306 self.pg2.add_stream(pkts)
2307 self.pg_enable_capture(self.pg_interfaces)
2308 self.pg_start()
2309
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002310 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002311 self.assertEqual(
2312 len(pkts),
2313 len(rx0),
2314 "Expected all (%s) packets across single path. "
2315 "rx0: %s." % (len(pkts), len(rx0)),
2316 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002317
2318 #
2319 # enable the FIB walk process to converge the FIB
2320 #
2321 self.vapi.ppcli("test fib-walk-process enable")
2322
2323 #
2324 # packets should still be forwarded through the remaining peer
2325 #
2326 self.pg2.add_stream(pkts)
2327 self.pg_enable_capture(self.pg_interfaces)
2328 self.pg_start()
2329
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002330 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002331 self.assertEqual(
2332 len(pkts),
2333 len(rx0),
2334 "Expected all (%s) packets across single path. "
2335 "rx0: %s." % (len(pkts), len(rx0)),
2336 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002337
2338 #
2339 # Add the IGP route back and we return to load-balancing
2340 #
2341 core_10_0_0_46.add_vpp_config()
2342
2343 self.pg2.add_stream(pkts)
2344 self.pg_enable_capture(self.pg_interfaces)
2345 self.pg_start()
2346
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002347 rx0 = self.pg0._get_capture(NUM_PKTS)
2348 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002349 self.assertNotEqual(0, len(rx0))
2350 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002351 self.assertEqual(
2352 len(pkts),
2353 len(rx0) + len(rx1),
2354 "Expected all (%s) packets across both ECMP paths. "
2355 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2356 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002357
2358 def test_mpls_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002359 """MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002360
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002361 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07002362 2) Check EMCP forwarding to these peers
2363 3) withdraw one eBGP path - expect LB across remaining eBGP
2364 """
2365
2366 #
2367 # Lot's of VPN routes. We need more the 64 so VPP will build
2368 # the fast convergence indirection
2369 #
2370 vpn_routes = []
2371 vpn_bindings = []
2372 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002373 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002374 dst = "192.168.1.%d" % ii
2375 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002376 vpn_routes.append(
2377 VppIpRoute(
2378 self,
2379 dst,
2380 32,
2381 [
2382 VppRoutePath(
2383 self.pg2.remote_ip4,
2384 0xFFFFFFFF,
2385 nh_table_id=1,
2386 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2387 ),
2388 VppRoutePath(
2389 self.pg3.remote_ip4,
2390 0xFFFFFFFF,
2391 nh_table_id=1,
2392 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2393 ),
2394 ],
2395 table_id=1,
2396 )
2397 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002398 vpn_routes[ii].add_vpp_config()
2399
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002400 vpn_bindings.append(
2401 VppMplsIpBind(self, local_label, dst, 32, ip_table_id=1)
2402 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002403 vpn_bindings[ii].add_vpp_config()
2404
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002405 pkts.append(
2406 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2407 / MPLS(label=local_label, ttl=64)
2408 / IP(src=self.pg0.remote_ip4, dst=dst)
2409 / UDP(sport=1234, dport=1234)
2410 / Raw(b"\xa5" * 100)
2411 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002412
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002413 #
2414 # Send the packet stream (one pkt to each VPN route)
2415 # - expect a 50-50 split of the traffic
2416 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002417 self.pg0.add_stream(pkts)
2418 self.pg_enable_capture(self.pg_interfaces)
2419 self.pg_start()
2420
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002421 rx0 = self.pg2._get_capture(NUM_PKTS)
2422 rx1 = self.pg3._get_capture(NUM_PKTS)
2423
2424 # not testing the LB hashing algorithm so we're not concerned
2425 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002426 self.assertNotEqual(0, len(rx0))
2427 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002428 self.assertEqual(
2429 len(pkts),
2430 len(rx0) + len(rx1),
2431 "Expected all (%s) packets across both ECMP paths. "
2432 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2433 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002434
2435 #
2436 # use a test CLI command to stop the FIB walk process, this
2437 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002438 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002439 #
2440 self.vapi.ppcli("test fib-walk-process disable")
2441
2442 #
2443 # withdraw the connected prefix on the interface.
2444 #
2445 self.pg2.unconfig_ip4()
2446
2447 #
2448 # now all packets should be forwarded through the remaining peer
2449 #
2450 self.pg0.add_stream(pkts)
2451 self.pg_enable_capture(self.pg_interfaces)
2452 self.pg_start()
2453
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002454 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002455 self.assertEqual(
2456 len(pkts),
2457 len(rx0),
2458 "Expected all (%s) packets across single path. "
2459 "rx0: %s." % (len(pkts), len(rx0)),
2460 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002461
2462 #
2463 # enable the FIB walk process to converge the FIB
2464 #
2465 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002466
2467 #
2468 # packets should still be forwarded through the remaining peer
2469 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002470 self.pg0.add_stream(pkts)
2471 self.pg_enable_capture(self.pg_interfaces)
2472 self.pg_start()
2473
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002474 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002475 self.assertEqual(
2476 len(pkts),
2477 len(rx0),
2478 "Expected all (%s) packets across single path. "
2479 "rx0: %s." % (len(pkts), len(rx0)),
2480 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002481
2482 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002483 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002484 #
2485 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002486 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002487
2488 self.pg0.add_stream(pkts)
2489 self.pg_enable_capture(self.pg_interfaces)
2490 self.pg_start()
2491
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002492 rx0 = self.pg2._get_capture(NUM_PKTS)
2493 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002494 self.assertNotEqual(0, len(rx0))
2495 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002496 self.assertEqual(
2497 len(pkts),
2498 len(rx0) + len(rx1),
2499 "Expected all (%s) packets across both ECMP paths. "
2500 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2501 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002502
2503 def test_mpls_v6_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002504 """MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002505
2506 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2507 2) Check EMCP forwarding to these peers
2508 3) withdraw one eBGP path - expect LB across remaining eBGP
2509 """
2510
2511 #
2512 # Lot's of VPN routes. We need more the 64 so VPP will build
2513 # the fast convergence indirection
2514 #
2515 vpn_routes = []
2516 vpn_bindings = []
2517 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002518 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002519 dst = "3000::%d" % ii
2520 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002521 vpn_routes.append(
2522 VppIpRoute(
2523 self,
2524 dst,
2525 128,
2526 [
2527 VppRoutePath(
2528 self.pg2.remote_ip6,
2529 0xFFFFFFFF,
2530 nh_table_id=1,
2531 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2532 ),
2533 VppRoutePath(
2534 self.pg3.remote_ip6,
2535 0xFFFFFFFF,
2536 nh_table_id=1,
2537 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2538 ),
2539 ],
2540 table_id=1,
2541 )
2542 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002543 vpn_routes[ii].add_vpp_config()
2544
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002545 vpn_bindings.append(
2546 VppMplsIpBind(self, local_label, dst, 128, ip_table_id=1)
2547 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002548 vpn_bindings[ii].add_vpp_config()
2549
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002550 pkts.append(
2551 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2552 / MPLS(label=local_label, ttl=64)
2553 / IPv6(src=self.pg0.remote_ip6, dst=dst)
2554 / UDP(sport=1234, dport=1234)
2555 / Raw(b"\xa5" * 100)
2556 )
Neale Ranns097fa662018-05-01 05:17:55 -07002557 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002558
2559 self.pg0.add_stream(pkts)
2560 self.pg_enable_capture(self.pg_interfaces)
2561 self.pg_start()
2562
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002563 rx0 = self.pg2._get_capture(NUM_PKTS)
2564 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002565 self.assertNotEqual(0, len(rx0))
2566 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002567 self.assertEqual(
2568 len(pkts),
2569 len(rx0) + len(rx1),
2570 "Expected all (%s) packets across both ECMP paths. "
2571 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2572 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002573
2574 #
2575 # use a test CLI command to stop the FIB walk process, this
2576 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002577 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002578 #
2579 self.vapi.ppcli("test fib-walk-process disable")
2580
2581 #
2582 # withdraw the connected prefix on the interface.
2583 # and shutdown the interface so the ND cache is flushed.
2584 #
2585 self.pg2.unconfig_ip6()
2586 self.pg2.admin_down()
2587
2588 #
2589 # now all packets should be forwarded through the remaining peer
2590 #
2591 self.pg0.add_stream(pkts)
2592 self.pg_enable_capture(self.pg_interfaces)
2593 self.pg_start()
2594
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002595 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002596 self.assertEqual(
2597 len(pkts),
2598 len(rx0),
2599 "Expected all (%s) packets across single path. "
2600 "rx0: %s." % (len(pkts), len(rx0)),
2601 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002602
2603 #
2604 # enable the FIB walk process to converge the FIB
2605 #
2606 self.vapi.ppcli("test fib-walk-process enable")
2607 self.pg0.add_stream(pkts)
2608 self.pg_enable_capture(self.pg_interfaces)
2609 self.pg_start()
2610
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002611 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002612 self.assertEqual(
2613 len(pkts),
2614 len(rx0),
2615 "Expected all (%s) packets across single path. "
2616 "rx0: %s." % (len(pkts), len(rx0)),
2617 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002618
2619 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002620 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002621 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002622 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002623 self.pg2.admin_up()
2624 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002625 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002626
2627 self.pg0.add_stream(pkts)
2628 self.pg_enable_capture(self.pg_interfaces)
2629 self.pg_start()
2630
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002631 rx0 = self.pg2._get_capture(NUM_PKTS)
2632 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002633 self.assertNotEqual(0, len(rx0))
2634 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002635 self.assertEqual(
2636 len(pkts),
2637 len(rx0) + len(rx1),
2638 "Expected all (%s) packets across both ECMP paths. "
2639 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2640 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002641
2642
Neale Rannsda78f952017-05-24 09:15:43 -07002643class TestMPLSL2(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002644 """MPLS-L2"""
Neale Rannsda78f952017-05-24 09:15:43 -07002645
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002646 @classmethod
2647 def setUpClass(cls):
2648 super(TestMPLSL2, cls).setUpClass()
2649
2650 @classmethod
2651 def tearDownClass(cls):
2652 super(TestMPLSL2, cls).tearDownClass()
2653
Neale Rannsda78f952017-05-24 09:15:43 -07002654 def setUp(self):
2655 super(TestMPLSL2, self).setUp()
2656
2657 # create 2 pg interfaces
2658 self.create_pg_interfaces(range(2))
2659
Neale Ranns15002542017-09-10 04:39:11 -07002660 # create the default MPLS table
2661 self.tables = []
2662 tbl = VppMplsTable(self, 0)
2663 tbl.add_vpp_config()
2664 self.tables.append(tbl)
2665
Neale Ranns1976f362019-11-06 13:13:01 +00002666 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002667 self.pg0.admin_up()
2668 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002669 self.pg0.enable_mpls()
2670
Neale Ranns15002542017-09-10 04:39:11 -07002671 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002672 for i in self.pg_interfaces[1:]:
2673 i.admin_up()
2674
2675 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002676 for i in self.pg_interfaces[1:]:
2677 i.admin_down()
2678
2679 self.pg0.disable_mpls()
2680 self.pg0.unconfig_ip4()
2681 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002682 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002683
Neale Ranns31ed7442018-02-23 05:29:09 -08002684 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002685 capture = verify_filter(capture, sent)
2686
2687 self.assertEqual(len(capture), len(sent))
2688
2689 for i in range(len(capture)):
2690 tx = sent[i]
2691 rx = capture[i]
2692
2693 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002694 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002695
2696 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002697 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002698
2699 self.assertEqual(rx_eth.src, tx_eth.src)
2700 self.assertEqual(rx_eth.dst, tx_eth.dst)
2701
Neale Ranns1976f362019-11-06 13:13:01 +00002702 def verify_arp_req(self, rx, smac, sip, dip):
2703 ether = rx[Ether]
2704 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2705 self.assertEqual(ether.src, smac)
2706
2707 arp = rx[ARP]
2708 self.assertEqual(arp.hwtype, 1)
2709 self.assertEqual(arp.ptype, 0x800)
2710 self.assertEqual(arp.hwlen, 6)
2711 self.assertEqual(arp.plen, 4)
2712 self.assertEqual(arp.op, ARP.who_has)
2713 self.assertEqual(arp.hwsrc, smac)
2714 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2715 self.assertEqual(arp.psrc, sip)
2716 self.assertEqual(arp.pdst, dip)
2717
Neale Rannsda78f952017-05-24 09:15:43 -07002718 def test_vpws(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002719 """Virtual Private Wire Service"""
Neale Rannsda78f952017-05-24 09:15:43 -07002720
2721 #
2722 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002723 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2724 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002725 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002726 mpls_tun_1 = VppMPLSTunnelInterface(
2727 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002728 [
2729 VppRoutePath(
2730 self.pg0.remote_ip4,
2731 self.pg0.sw_if_index,
2732 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)],
2733 )
2734 ],
2735 is_l2=1,
2736 )
Neale Rannsda78f952017-05-24 09:15:43 -07002737 mpls_tun_1.add_vpp_config()
2738 mpls_tun_1.admin_up()
2739
2740 #
2741 # Create a label entry to for 55 that does L2 input to the tunnel
2742 #
2743 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002744 self,
2745 55,
2746 1,
2747 [
2748 VppRoutePath(
2749 "0.0.0.0",
2750 mpls_tun_1.sw_if_index,
2751 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2752 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2753 )
2754 ],
2755 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2756 )
Neale Rannsda78f952017-05-24 09:15:43 -07002757 route_55_eos.add_vpp_config()
2758
2759 #
2760 # Cross-connect the tunnel with one of the customers L2 interfaces
2761 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002762 self.vapi.sw_interface_set_l2_xconnect(
2763 self.pg1.sw_if_index, mpls_tun_1.sw_if_index, enable=1
2764 )
2765 self.vapi.sw_interface_set_l2_xconnect(
2766 mpls_tun_1.sw_if_index, self.pg1.sw_if_index, enable=1
2767 )
Neale Rannsda78f952017-05-24 09:15:43 -07002768
2769 #
2770 # inject a packet from the core
2771 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002772 pcore = (
2773 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2774 / MPLS(label=55, ttl=64)
2775 / Ether(dst="00:00:de:ad:ba:be", src="00:00:de:ad:be:ef")
2776 / IP(src="10.10.10.10", dst="11.11.11.11")
2777 / UDP(sport=1234, dport=1234)
2778 / Raw(b"\xa5" * 100)
2779 )
Neale Rannsda78f952017-05-24 09:15:43 -07002780
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002781 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002782 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2783 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002784
Neale Ranns31ed7442018-02-23 05:29:09 -08002785 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2786 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002787
2788 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002789 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002790 # there's no resolved ARP entry so the first packet we see should be
2791 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002792 #
Neale Ranns1976f362019-11-06 13:13:01 +00002793 tx1 = pcore[MPLS].payload
2794 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2795
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002796 self.verify_arp_req(
2797 rx1[0], self.pg0.local_mac, self.pg0.local_ip4, self.pg0.remote_ip4
2798 )
Neale Ranns1976f362019-11-06 13:13:01 +00002799
2800 #
2801 # resolve the ARP entries and send again
2802 #
2803 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002804 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002805 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002806
Neale Ranns31ed7442018-02-23 05:29:09 -08002807 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002808
2809 def test_vpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002810 """Virtual Private LAN Service"""
Neale Ranns1976f362019-11-06 13:13:01 +00002811
2812 # we skipped this in the setup
2813 self.pg0.resolve_arp()
2814
Neale Rannsda78f952017-05-24 09:15:43 -07002815 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002816 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002817 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002818 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002819 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002820 [
2821 VppRoutePath(
2822 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(42)]
2823 )
2824 ],
2825 is_l2=1,
2826 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002827 mpls_tun1.add_vpp_config()
2828 mpls_tun1.admin_up()
2829
2830 mpls_tun2 = VppMPLSTunnelInterface(
2831 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002832 [
2833 VppRoutePath(
2834 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(43)]
2835 )
2836 ],
2837 is_l2=1,
2838 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002839 mpls_tun2.add_vpp_config()
2840 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002841
2842 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002843 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2844 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002845 #
2846 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002847 self,
2848 55,
2849 1,
2850 [
2851 VppRoutePath(
2852 "0.0.0.0",
2853 mpls_tun1.sw_if_index,
2854 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2855 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2856 )
2857 ],
2858 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2859 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002860
2861 route_56_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002862 self,
2863 56,
2864 1,
2865 [
2866 VppRoutePath(
2867 "0.0.0.0",
2868 mpls_tun2.sw_if_index,
2869 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2870 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2871 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2872 )
2873 ],
2874 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2875 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002876
2877 # move me
2878 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002879 route_55_eos.add_vpp_config()
2880
Neale Ranns1dbcf302019-07-19 11:44:53 +00002881 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2882
Neale Rannsda78f952017-05-24 09:15:43 -07002883 #
2884 # add to tunnel to the customers bridge-domain
2885 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002886 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002887 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1
2888 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002889 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002890 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1
2891 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002892 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002893 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1
2894 )
Neale Rannsda78f952017-05-24 09:15:43 -07002895
2896 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002897 # Packet from host on the customer interface to each host
2898 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002899 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002900 p_cust1 = (
2901 Ether(dst="00:00:de:ad:ba:b1", src="00:00:de:ad:be:ef")
2902 / IP(src="10.10.10.10", dst="11.11.11.11")
2903 / UDP(sport=1234, dport=1234)
2904 / Raw(b"\xa5" * 100)
2905 )
2906 p_cust2 = (
2907 Ether(dst="00:00:de:ad:ba:b2", src="00:00:de:ad:be:ef")
2908 / IP(src="10.10.10.10", dst="11.11.11.12")
2909 / UDP(sport=1234, dport=1234)
2910 / Raw(b"\xa5" * 100)
2911 )
2912 p_core1 = (
2913 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2914 / MPLS(label=55, ttl=64)
2915 / Ether(src="00:00:de:ad:ba:b1", dst="00:00:de:ad:be:ef")
2916 / IP(dst="10.10.10.10", src="11.11.11.11")
2917 / UDP(sport=1234, dport=1234)
2918 / Raw(b"\xa5" * 100)
2919 )
2920 p_core2 = (
2921 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2922 / MPLS(label=56, ttl=64)
2923 / Raw(b"\x01" * 4)
2924 / Ether(src="00:00:de:ad:ba:b2", dst="00:00:de:ad:be:ef") # PW CW
2925 / IP(dst="10.10.10.10", src="11.11.11.12")
2926 / UDP(sport=1234, dport=1234)
2927 / Raw(b"\xa5" * 100)
2928 )
Neale Rannsda78f952017-05-24 09:15:43 -07002929
2930 #
2931 # The BD is learning, so send in one of each packet to learn
2932 #
Neale Rannsda78f952017-05-24 09:15:43 -07002933
Neale Ranns1dbcf302019-07-19 11:44:53 +00002934 # 2 packets due to BD flooding
2935 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2936 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002937
Neale Ranns1dbcf302019-07-19 11:44:53 +00002938 # we've learnt this so expect it be be forwarded not flooded
2939 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2940 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2941 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002942
Neale Ranns1dbcf302019-07-19 11:44:53 +00002943 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2944 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2945 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002946
2947 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002948 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002949 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002950 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002951 self.verify_capture_tunneled_ethernet(
2952 rx, p_cust1 * NUM_PKTS, [VppMplsLabel(42)]
2953 )
Neale Rannsda78f952017-05-24 09:15:43 -07002954
Neale Ranns1dbcf302019-07-19 11:44:53 +00002955 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002956 self.verify_capture_tunneled_ethernet(
2957 rx, p_cust2 * NUM_PKTS, [VppMplsLabel(43)]
2958 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002959
2960 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2961 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2962
Neale Rannsda78f952017-05-24 09:15:43 -07002963 #
2964 # remove interfaces from customers bridge-domain
2965 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002966 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002967 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0
2968 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002969 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002970 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0
2971 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002972 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002973 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0
2974 )
Neale Rannsda78f952017-05-24 09:15:43 -07002975
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002976
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002977if __name__ == "__main__":
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002978 unittest.main(testRunner=VppTestRunner)