blob: 0e747ec7cd0151a7d634273c16576e850363eedc [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
Neale Ranns8fe8cc22016-11-01 10:05:08 +000028
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070029import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000030from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000031from scapy.layers.l2 import Ether, ARP
Neale Rannsfbc633f2022-03-18 13:05:09 +000032from scapy.layers.inet import IP, UDP, ICMP, icmptypes, icmpcodes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020033from scapy.layers.inet6 import (
34 IPv6,
35 ICMPv6TimeExceeded,
36 ICMPv6EchoRequest,
37 ICMPv6PacketTooBig,
38)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000039from scapy.contrib.mpls import MPLS
40
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040041NUM_PKTS = 67
42
Neale Ranns1976f362019-11-06 13:13:01 +000043# scapy removed these attributes.
44# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
45# semantic names have more meaning than numbers. so here they are.
46ARP.who_has = 1
47ARP.is_at = 2
48
Klement Sekeradab231a2016-12-21 08:50:14 +010049
Neale Rannsda78f952017-05-24 09:15:43 -070050def verify_filter(capture, sent):
51 if not len(capture) == len(sent):
52 # filter out any IPv6 RAs from the capture
53 for p in capture:
54 if p.haslayer(IPv6):
55 capture.remove(p)
56 return capture
57
58
Neale Ranns31ed7442018-02-23 05:29:09 -080059def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070060 # the rx'd packet has the MPLS label popped
61 eth = rx[Ether]
62 tst.assertEqual(eth.type, 0x8847)
63
64 rx_mpls = rx[MPLS]
65
66 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080067 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
68 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
69 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
70
Neale Rannsda78f952017-05-24 09:15:43 -070071 if ii == len(mpls_labels) - 1:
72 tst.assertEqual(rx_mpls.s, 1)
73 else:
74 # not end of stack
75 tst.assertEqual(rx_mpls.s, 0)
76 # pop the label to expose the next
77 rx_mpls = rx_mpls[MPLS].payload
78
79
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000080@tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +000081class TestMPLS(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020082 """MPLS Test Case"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +000083
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070084 @classmethod
85 def setUpClass(cls):
86 super(TestMPLS, cls).setUpClass()
87
88 @classmethod
89 def tearDownClass(cls):
90 super(TestMPLS, cls).tearDownClass()
91
Neale Ranns8fe8cc22016-11-01 10:05:08 +000092 def setUp(self):
93 super(TestMPLS, self).setUp()
94
95 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080096 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000097
98 # setup both interfaces
99 # assign them different tables.
100 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -0700101 self.tables = []
102
103 tbl = VppMplsTable(self, 0)
104 tbl.add_vpp_config()
105 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000106
107 for i in self.pg_interfaces:
108 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -0700109
110 if table_id != 0:
111 tbl = VppIpTable(self, table_id)
112 tbl.add_vpp_config()
113 self.tables.append(tbl)
114 tbl = VppIpTable(self, table_id, is_ip6=1)
115 tbl.add_vpp_config()
116 self.tables.append(tbl)
117
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000118 i.set_table_ip4(table_id)
119 i.set_table_ip6(table_id)
120 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000121 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000122 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000123 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000124 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000125 table_id += 1
126
127 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800128 for i in self.pg_interfaces:
129 i.unconfig_ip4()
130 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700131 i.set_table_ip4(0)
132 i.set_table_ip6(0)
133 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800134 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700135 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000136
Neale Rannsad422ed2016-11-02 14:20:04 +0000137 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100138 def create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200139 self,
140 src_if,
141 mpls_labels,
142 ping=0,
143 ip_itf=None,
144 dst_ip=None,
145 chksum=None,
146 ip_ttl=64,
147 n=257,
148 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100149 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000150 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800151 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100152 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000153 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000154 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
155
156 for ii in range(len(mpls_labels)):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200157 p = p / MPLS(
158 label=mpls_labels[ii].value,
159 ttl=mpls_labels[ii].ttl,
160 cos=mpls_labels[ii].exp,
161 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100162 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800163 if not dst_ip:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200164 p = (
165 p
166 / IP(src=src_if.local_ip4, dst=src_if.remote_ip4, ttl=ip_ttl)
167 / UDP(sport=1234, dport=1234)
168 / Raw(payload)
169 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800170 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 p = (
172 p
173 / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl)
174 / UDP(sport=1234, dport=1234)
175 / Raw(payload)
176 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100177 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 p = (
179 p
180 / IP(src=ip_itf.remote_ip4, dst=ip_itf.local_ip4, ttl=ip_ttl)
181 / ICMP()
182 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100183
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700184 if chksum:
185 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000186 info.data = p.copy()
187 pkts.append(p)
188 return pkts
189
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200190 def create_stream_ip4(
Vladislav Grishenko302db472024-01-24 16:17:23 +0500191 self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, payload_size=None, n=257
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200192 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100193 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000194 pkts = []
Vladislav Grishenko302db472024-01-24 16:17:23 +0500195 for i in range(0, n):
196 dst = dst_ip[i % len(dst_ip)] if isinstance(dst_ip, list) else dst_ip
Klement Sekeradab231a2016-12-21 08:50:14 +0100197 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000198 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199 p = (
200 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
Vladislav Grishenko302db472024-01-24 16:17:23 +0500201 / IP(src=src_if.remote_ip4, dst=dst, ttl=ip_ttl, tos=ip_dscp)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 / UDP(sport=1234, dport=1234)
203 / Raw(payload)
204 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000205 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200206 if payload_size:
207 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000208 pkts.append(p)
209 return pkts
210
Vladislav Grishenko302db472024-01-24 16:17:23 +0500211 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, n=257):
Neale Ranns31ed7442018-02-23 05:29:09 -0800212 self.reset_packet_infos()
213 pkts = []
Vladislav Grishenko302db472024-01-24 16:17:23 +0500214 for i in range(0, n):
215 dst = dst_ip[i % len(dst_ip)] if isinstance(dst_ip, list) else dst_ip
Neale Ranns31ed7442018-02-23 05:29:09 -0800216 info = self.create_packet_info(src_if, src_if)
217 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218 p = (
219 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
Vladislav Grishenko302db472024-01-24 16:17:23 +0500220 / IPv6(src=src_if.remote_ip6, dst=dst, hlim=ip_ttl, tc=ip_dscp)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200221 / UDP(sport=1234, dport=1234)
222 / Raw(payload)
223 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800224 info.data = p.copy()
225 pkts.append(p)
226 return pkts
227
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200228 def create_stream_labelled_ip6(
229 self, src_if, mpls_labels, hlim=64, dst_ip=None, ping=0, ip_itf=None
230 ):
Neale Ranns31426c62017-05-24 10:32:58 -0700231 if dst_ip is None:
232 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100233 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000234 pkts = []
235 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100236 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000237 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800238 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
239 for l in mpls_labels:
240 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
241
Neale Rannsf478f752022-02-17 15:41:32 +0000242 if ping:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 p = p / (
244 IPv6(src=ip_itf.remote_ip6, dst=ip_itf.local_ip6)
245 / ICMPv6EchoRequest()
246 )
Neale Rannsf478f752022-02-17 15:41:32 +0000247 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200248 p = p / (
249 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim)
250 / UDP(sport=1234, dport=1234)
251 / Raw(payload)
252 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000253 info.data = p.copy()
254 pkts.append(p)
255 return pkts
256
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200257 def verify_capture_ip4(
258 self, src_if, capture, sent, ping_resp=0, ip_ttl=None, ip_dscp=0
259 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000260 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700261 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000262
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000263 self.assertEqual(len(capture), len(sent))
264
265 for i in range(len(capture)):
266 tx = sent[i]
267 rx = capture[i]
268
269 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000270 eth = rx[Ether]
271 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000272
273 tx_ip = tx[IP]
274 rx_ip = rx[IP]
275
Neale Rannscb630ff2016-12-14 13:31:29 +0100276 if not ping_resp:
277 self.assertEqual(rx_ip.src, tx_ip.src)
278 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800279 self.assertEqual(rx_ip.tos, ip_dscp)
280 if not ip_ttl:
281 # IP processing post pop has decremented the TTL
282 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
283 else:
284 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100285 else:
286 self.assertEqual(rx_ip.src, tx_ip.dst)
287 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000288
289 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000290 raise
291
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200292 def verify_capture_labelled_ip4(
293 self, src_if, capture, sent, mpls_labels, ip_ttl=None
294 ):
Neale Rannsad422ed2016-11-02 14:20:04 +0000295 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700296 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000297
298 self.assertEqual(len(capture), len(sent))
299
300 for i in range(len(capture)):
301 tx = sent[i]
302 rx = capture[i]
303 tx_ip = tx[IP]
304 rx_ip = rx[IP]
305
Neale Ranns31ed7442018-02-23 05:29:09 -0800306 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000307
308 self.assertEqual(rx_ip.src, tx_ip.src)
309 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800310 if not ip_ttl:
311 # IP processing post pop has decremented the TTL
312 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
313 else:
314 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000315
316 except:
317 raise
318
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200319 def verify_capture_labelled_ip6(
320 self, src_if, capture, sent, mpls_labels, ip_ttl=None
321 ):
Neale Ranns31ed7442018-02-23 05:29:09 -0800322 try:
323 capture = verify_filter(capture, sent)
324
325 self.assertEqual(len(capture), len(sent))
326
327 for i in range(len(capture)):
328 tx = sent[i]
329 rx = capture[i]
330 tx_ip = tx[IPv6]
331 rx_ip = rx[IPv6]
332
333 verify_mpls_stack(self, rx, mpls_labels)
334
335 self.assertEqual(rx_ip.src, tx_ip.src)
336 self.assertEqual(rx_ip.dst, tx_ip.dst)
337 if not ip_ttl:
338 # IP processing post pop has decremented the TTL
339 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
340 else:
341 self.assertEqual(rx_ip.hlim, ip_ttl)
342
343 except:
344 raise
345
346 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000347 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700348 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000349
350 self.assertEqual(len(capture), len(sent))
351
352 for i in range(len(capture)):
353 tx = sent[i]
354 rx = capture[i]
355 tx_ip = tx[IP]
356 rx_ip = rx[IP]
357
Neale Ranns31ed7442018-02-23 05:29:09 -0800358 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000359
360 self.assertEqual(rx_ip.src, tx_ip.src)
361 self.assertEqual(rx_ip.dst, tx_ip.dst)
362 # IP processing post pop has decremented the TTL
363 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
364
365 except:
366 raise
367
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200368 def verify_capture_labelled(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000369 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700370 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000371
372 self.assertEqual(len(capture), len(sent))
373
374 for i in range(len(capture)):
375 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800376 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000377 except:
378 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000379
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200380 def verify_capture_ip6(
381 self, src_if, capture, sent, ip_hlim=None, ip_dscp=0, ping_resp=0
382 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000383 try:
384 self.assertEqual(len(capture), len(sent))
385
386 for i in range(len(capture)):
387 tx = sent[i]
388 rx = capture[i]
389
390 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000391 eth = rx[Ether]
392 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000393
394 tx_ip = tx[IPv6]
395 rx_ip = rx[IPv6]
396
Neale Rannsf478f752022-02-17 15:41:32 +0000397 if not ping_resp:
398 self.assertEqual(rx_ip.src, tx_ip.src)
399 self.assertEqual(rx_ip.dst, tx_ip.dst)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Rannsf478f752022-02-17 15:41:32 +0000401 # IP processing post pop has decremented the TTL
402 if not ip_hlim:
403 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
404 else:
405 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns31ed7442018-02-23 05:29:09 -0800406 else:
Neale Rannsf478f752022-02-17 15:41:32 +0000407 self.assertEqual(rx_ip.src, tx_ip.dst)
408 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000409 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000410 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000411
Neale Ranns62fe07c2017-10-31 12:28:22 -0700412 def verify_capture_ip6_icmp(self, src_if, capture, sent):
413 try:
Neale Ranns5c6dd172022-02-17 09:08:47 +0000414 # rate limited ICMP
415 self.assertTrue(len(capture) <= len(sent))
Neale Ranns62fe07c2017-10-31 12:28:22 -0700416
417 for i in range(len(capture)):
418 tx = sent[i]
419 rx = capture[i]
420
421 # the rx'd packet has the MPLS label popped
422 eth = rx[Ether]
423 self.assertEqual(eth.type, 0x86DD)
424
425 tx_ip = tx[IPv6]
426 rx_ip = rx[IPv6]
427
428 self.assertEqual(rx_ip.dst, tx_ip.src)
429 # ICMP sourced from the interface's address
430 self.assertEqual(rx_ip.src, src_if.local_ip6)
431 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200432 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700433
434 icmp = rx[ICMPv6TimeExceeded]
435
436 except:
437 raise
438
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200439 def verify_capture_fragmented_labelled_ip4(
440 self, src_if, capture, sent, mpls_labels, ip_ttl=None
441 ):
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530442 try:
443 capture = verify_filter(capture, sent)
444
445 for i in range(len(capture)):
446 tx = sent[0]
447 rx = capture[i]
448 tx_ip = tx[IP]
449 rx_ip = rx[IP]
450
451 verify_mpls_stack(self, rx, mpls_labels)
452
453 self.assertEqual(rx_ip.src, tx_ip.src)
454 self.assertEqual(rx_ip.dst, tx_ip.dst)
455 if not ip_ttl:
456 # IP processing post pop has decremented the TTL
457 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
458 else:
459 self.assertEqual(rx_ip.ttl, ip_ttl)
460
461 except:
462 raise
463
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 def verify_capture_fragmented_labelled_ip6(
465 self, src_if, capture, sent, mpls_labels, ip_ttl=None
466 ):
Neale Rannsec5371e2022-03-04 11:45:41 +0000467 try:
468 capture = verify_filter(capture, sent)
469
470 for i in range(len(capture)):
471 tx = sent[0]
472 rx = capture[i]
473 tx_ip = tx[IPv6]
474 rx.show()
475 rx_ip = IPv6(rx[MPLS].payload)
476 rx_ip.show()
477
478 verify_mpls_stack(self, rx, mpls_labels)
479
480 self.assertEqual(rx_ip.src, tx_ip.src)
481 self.assertEqual(rx_ip.dst, tx_ip.dst)
482 if not ip_ttl:
483 # IP processing post pop has decremented the hop-limit
484 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
485 else:
486 self.assertEqual(rx_ip.hlim, ip_ttl)
487 except:
488 raise
489
Neale Rannsad422ed2016-11-02 14:20:04 +0000490 def test_swap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 """MPLS label swap tests"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000492
493 #
494 # A simple MPLS xconnect - eos label in label out
495 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200496 route_32_eos = VppMplsRoute(
497 self,
498 32,
499 1,
500 [
501 VppRoutePath(
502 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
503 )
504 ],
505 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000506 route_32_eos.add_vpp_config()
507
Neale Ranns775f73c2018-12-20 03:01:49 -0800508 self.assertTrue(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200509 find_mpls_route(
510 self,
511 0,
512 32,
513 1,
514 [
515 VppRoutePath(
516 self.pg0.remote_ip4,
517 self.pg0.sw_if_index,
518 labels=[VppMplsLabel(33)],
519 )
520 ],
521 )
522 )
Neale Ranns775f73c2018-12-20 03:01:49 -0800523
Neale Rannsad422ed2016-11-02 14:20:04 +0000524 #
525 # a stream that matches the route for 10.0.0.1
526 # PG0 is in the default table
527 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200528 tx = self.create_stream_labelled_ip4(
529 self.pg0, [VppMplsLabel(32, ttl=32, exp=1)]
530 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800531 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200532 self.verify_capture_labelled(
533 self.pg0, rx, tx, [VppMplsLabel(33, ttl=31, exp=1)]
534 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000535
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200536 self.assertEqual(route_32_eos.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700537
Neale Rannsad422ed2016-11-02 14:20:04 +0000538 #
539 # A simple MPLS xconnect - non-eos label in label out
540 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200541 route_32_neos = VppMplsRoute(
542 self,
543 32,
544 0,
545 [
546 VppRoutePath(
547 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
548 )
549 ],
550 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000551 route_32_neos.add_vpp_config()
552
553 #
554 # a stream that matches the route for 10.0.0.1
555 # PG0 is in the default table
556 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200557 tx = self.create_stream_labelled_ip4(
558 self.pg0, [VppMplsLabel(32, ttl=21, exp=7), VppMplsLabel(99)]
559 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800560 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200561 self.verify_capture_labelled(
562 self.pg0, rx, tx, [VppMplsLabel(33, ttl=20, exp=7), VppMplsLabel(99)]
563 )
564 self.assertEqual(route_32_neos.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000565
Neale Ranns31ed7442018-02-23 05:29:09 -0800566 #
567 # A simple MPLS xconnect - non-eos label in label out, uniform mode
568 #
569 route_42_neos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200570 self,
571 42,
572 0,
573 [
574 VppRoutePath(
575 self.pg0.remote_ip4,
576 self.pg0.sw_if_index,
577 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)],
578 )
579 ],
580 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800581 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000582
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200583 tx = self.create_stream_labelled_ip4(
584 self.pg0, [VppMplsLabel(42, ttl=21, exp=7), VppMplsLabel(99)]
585 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800586 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200587 self.verify_capture_labelled(
588 self.pg0, rx, tx, [VppMplsLabel(43, ttl=20, exp=7), VppMplsLabel(99)]
589 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000590
591 #
592 # An MPLS xconnect - EOS label in IP out
593 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200594 route_33_eos = VppMplsRoute(
595 self,
596 33,
597 1,
598 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
599 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000600 route_33_eos.add_vpp_config()
601
Neale Ranns31ed7442018-02-23 05:29:09 -0800602 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
603 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000604 self.verify_capture_ip4(self.pg0, rx, tx)
605
606 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700607 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700608 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 tx = self.create_stream_labelled_ip4(
610 self.pg0, [VppMplsLabel(33)], dst_ip=self.pg0.remote_ip4, n=65, chksum=1
611 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700612 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
613
614 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800615 # An MPLS xconnect - EOS label in IP out, uniform mode
616 #
617 route_3333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200618 self,
619 3333,
620 1,
621 [
622 VppRoutePath(
623 self.pg0.remote_ip4,
624 self.pg0.sw_if_index,
625 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
626 )
627 ],
628 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800629 route_3333_eos.add_vpp_config()
630
631 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200632 self.pg0, [VppMplsLabel(3333, ttl=55, exp=3)]
633 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800634 rx = self.send_and_expect(self.pg0, tx, self.pg0)
635 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
636 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200637 self.pg0, [VppMplsLabel(3333, ttl=66, exp=4)]
638 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800639 rx = self.send_and_expect(self.pg0, tx, self.pg0)
640 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
641
642 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700643 # An MPLS xconnect - EOS label in IPv6 out
644 #
645 route_333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200646 self,
647 333,
648 1,
649 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[])],
650 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
651 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700652 route_333_eos.add_vpp_config()
653
Neale Ranns31ed7442018-02-23 05:29:09 -0800654 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
655 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700656 self.verify_capture_ip6(self.pg0, rx, tx)
657
658 #
659 # disposed packets have an TTL expired
660 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200661 tx = self.create_stream_labelled_ip6(
662 self.pg0, [VppMplsLabel(333, ttl=64)], dst_ip=self.pg1.remote_ip6, hlim=1
663 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000664 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700665 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
666
667 #
668 # An MPLS xconnect - EOS label in IPv6 out w imp-null
669 #
670 route_334_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200671 self,
672 334,
673 1,
674 [
675 VppRoutePath(
676 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(3)]
677 )
678 ],
679 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
680 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700681 route_334_eos.add_vpp_config()
682
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200683 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334, ttl=64)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800684 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700685 self.verify_capture_ip6(self.pg0, rx, tx)
686
687 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800688 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
689 #
690 route_335_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200691 self,
692 335,
693 1,
694 [
695 VppRoutePath(
696 self.pg0.remote_ip6,
697 self.pg0.sw_if_index,
698 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
699 )
700 ],
701 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
702 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800703 route_335_eos.add_vpp_config()
704
705 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200706 self.pg0, [VppMplsLabel(335, ttl=27, exp=4)]
707 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800708 rx = self.send_and_expect(self.pg0, tx, self.pg0)
709 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
710
711 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700712 # disposed packets have an TTL expired
713 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200714 tx = self.create_stream_labelled_ip6(
715 self.pg0, [VppMplsLabel(334)], dst_ip=self.pg1.remote_ip6, hlim=0
716 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000717 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700718 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
719
720 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000721 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
722 # so this traffic should be dropped.
723 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200724 route_33_neos = VppMplsRoute(
725 self,
726 33,
727 0,
728 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
729 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000730 route_33_neos.add_vpp_config()
731
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200732 tx = self.create_stream_labelled_ip4(
733 self.pg0, [VppMplsLabel(33), VppMplsLabel(99)]
734 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800735 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200736 self.pg0, tx, "MPLS non-EOS packets popped and forwarded"
737 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000738
739 #
740 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800741 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000742 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200743 route_34_eos = VppMplsRoute(
744 self,
745 34,
746 1,
747 [
748 VppRoutePath(
749 "0.0.0.0",
750 0xFFFFFFFF,
751 nh_via_label=32,
752 labels=[VppMplsLabel(44), VppMplsLabel(45)],
753 )
754 ],
755 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000756 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700757 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000758
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200759 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800760 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200761 self.verify_capture_labelled(
762 self.pg0,
763 rx,
764 tx,
765 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(45, ttl=2)],
766 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000767
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200768 self.assertEqual(route_34_eos.get_stats_to()["packets"], 257)
769 self.assertEqual(route_32_neos.get_stats_via()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700770
Neale Ranns31ed7442018-02-23 05:29:09 -0800771 #
772 # A recursive EOS x-connect, which resolves through another x-connect
773 # in uniform mode
774 #
775 route_35_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200776 self,
777 35,
778 1,
779 [
780 VppRoutePath(
781 "0.0.0.0", 0xFFFFFFFF, nh_via_label=42, labels=[VppMplsLabel(44)]
782 )
783 ],
784 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800785 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000786
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200787 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(35, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800788 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200789 self.verify_capture_labelled(
790 self.pg0, rx, tx, [VppMplsLabel(43, ttl=2), VppMplsLabel(44, ttl=2)]
791 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000792
793 #
Matej Klottondeb69842016-12-09 15:05:46 +0100794 # A recursive non-EOS x-connect, which resolves through another
795 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000796 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 route_34_neos = VppMplsRoute(
798 self,
799 34,
800 0,
801 [
802 VppRoutePath(
803 "0.0.0.0",
804 0xFFFFFFFF,
805 nh_via_label=32,
806 labels=[VppMplsLabel(44), VppMplsLabel(46)],
807 )
808 ],
809 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000810 route_34_neos.add_vpp_config()
811
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200812 tx = self.create_stream_labelled_ip4(
813 self.pg0, [VppMplsLabel(34, ttl=45), VppMplsLabel(99)]
814 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800815 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100816 # it's the 2nd (counting from 0) label in the stack that is swapped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200817 self.verify_capture_labelled(
818 self.pg0,
819 rx,
820 tx,
821 [
822 VppMplsLabel(33),
823 VppMplsLabel(44),
824 VppMplsLabel(46, ttl=44),
825 VppMplsLabel(99),
826 ],
827 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000828
829 #
Matej Klottondeb69842016-12-09 15:05:46 +0100830 # an recursive IP route that resolves through the recursive non-eos
831 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000832 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200833 ip_10_0_0_1 = VppIpRoute(
834 self,
835 "10.0.0.1",
836 32,
837 [
838 VppRoutePath(
839 "0.0.0.0", 0xFFFFFFFF, nh_via_label=34, labels=[VppMplsLabel(55)]
840 )
841 ],
842 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000843 ip_10_0_0_1.add_vpp_config()
844
Neale Rannsad422ed2016-11-02 14:20:04 +0000845 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800846 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200847 self.verify_capture_labelled_ip4(
848 self.pg0,
849 rx,
850 tx,
851 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(55)],
852 )
853 self.assertEqual(ip_10_0_0_1.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000854
855 ip_10_0_0_1.remove_vpp_config()
856 route_34_neos.remove_vpp_config()
857 route_34_eos.remove_vpp_config()
858 route_33_neos.remove_vpp_config()
859 route_33_eos.remove_vpp_config()
860 route_32_neos.remove_vpp_config()
861 route_32_eos.remove_vpp_config()
862
863 def test_bind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200864 """MPLS Local Label Binding test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000865
866 #
867 # Add a non-recursive route with a single out label
868 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200869 route_10_0_0_1 = VppIpRoute(
870 self,
871 "10.0.0.1",
872 32,
873 [
874 VppRoutePath(
875 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
876 )
877 ],
878 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000879 route_10_0_0_1.add_vpp_config()
880
881 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800882 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000883 binding.add_vpp_config()
884
885 # non-EOS stream
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200886 tx = self.create_stream_labelled_ip4(
887 self.pg0, [VppMplsLabel(44), VppMplsLabel(99)]
888 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800889 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200890 self.verify_capture_labelled(
891 self.pg0, rx, tx, [VppMplsLabel(45, ttl=63), VppMplsLabel(99)]
892 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000893
894 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800895 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
896 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200897 self.verify_capture_labelled(self.pg0, rx, tx, [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000898
899 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000900 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800901 rx = self.send_and_expect(self.pg0, tx, self.pg0)
902 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000903
904 #
905 # cleanup
906 #
907 binding.remove_vpp_config()
908 route_10_0_0_1.remove_vpp_config()
909
910 def test_imposition(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200911 """MPLS label imposition test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000912
913 #
914 # Add a non-recursive route with a single out label
915 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200916 route_10_0_0_1 = VppIpRoute(
917 self,
918 "10.0.0.1",
919 32,
920 [
921 VppRoutePath(
922 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
923 )
924 ],
925 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000926 route_10_0_0_1.add_vpp_config()
927
928 #
929 # a stream that matches the route for 10.0.0.1
930 # PG0 is in the default table
931 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000932 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800933 rx = self.send_and_expect(self.pg0, tx, self.pg0)
934 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000935
936 #
937 # Add a non-recursive route with a 3 out labels
938 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200939 route_10_0_0_2 = VppIpRoute(
940 self,
941 "10.0.0.2",
942 32,
943 [
944 VppRoutePath(
945 self.pg0.remote_ip4,
946 self.pg0.sw_if_index,
947 labels=[VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
948 )
949 ],
950 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000951 route_10_0_0_2.add_vpp_config()
952
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200953 tx = self.create_stream_ip4(self.pg0, "10.0.0.2", ip_ttl=44, ip_dscp=0xFF)
Neale Ranns31ed7442018-02-23 05:29:09 -0800954 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200955 self.verify_capture_labelled_ip4(
956 self.pg0,
957 rx,
958 tx,
959 [VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
960 ip_ttl=43,
961 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000962
Neale Ranns31ed7442018-02-23 05:29:09 -0800963 #
964 # Add a non-recursive route with a single out label in uniform mode
965 #
966 route_10_0_0_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200967 self,
968 "10.0.0.3",
969 32,
970 [
971 VppRoutePath(
972 self.pg0.remote_ip4,
973 self.pg0.sw_if_index,
974 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
975 )
976 ],
977 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800978 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000979
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200980 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -0800981 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200982 self.verify_capture_labelled_ip4(
983 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
984 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800985
986 #
987 # Add a IPv6 non-recursive route with a single out label in
988 # uniform mode
989 #
990 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200991 self,
992 "2001::3",
993 128,
994 [
995 VppRoutePath(
996 self.pg0.remote_ip6,
997 self.pg0.sw_if_index,
998 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
999 )
1000 ],
1001 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001002 route_2001_3.add_vpp_config()
1003
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001004 tx = self.create_stream_ip6(self.pg0, "2001::3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -08001005 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001006 self.verify_capture_labelled_ip6(
1007 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
1008 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001009
1010 #
Matej Klottondeb69842016-12-09 15:05:46 +01001011 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +00001012 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001013 route_11_0_0_1 = VppIpRoute(
1014 self,
1015 "11.0.0.1",
1016 32,
1017 [VppRoutePath("10.0.0.1", 0xFFFFFFFF, labels=[VppMplsLabel(44)])],
1018 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001019 route_11_0_0_1.add_vpp_config()
1020
1021 #
1022 # a stream that matches the route for 11.0.0.1, should pick up
1023 # the label stack for 11.0.0.1 and 10.0.0.1
1024 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001025 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001026 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 self.verify_capture_labelled_ip4(
1028 self.pg0, rx, tx, [VppMplsLabel(32), VppMplsLabel(44)]
1029 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001030
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 self.assertEqual(route_11_0_0_1.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001032
Neale Rannsad422ed2016-11-02 14:20:04 +00001033 #
1034 # add a recursive path, with 2 labels, via the 3 label route
1035 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 route_11_0_0_2 = VppIpRoute(
1037 self,
1038 "11.0.0.2",
1039 32,
1040 [
1041 VppRoutePath(
1042 "10.0.0.2", 0xFFFFFFFF, labels=[VppMplsLabel(44), VppMplsLabel(45)]
1043 )
1044 ],
1045 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001046 route_11_0_0_2.add_vpp_config()
1047
1048 #
1049 # a stream that matches the route for 11.0.0.1, should pick up
1050 # the label stack for 11.0.0.1 and 10.0.0.1
1051 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001052 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -08001053 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001054 self.verify_capture_labelled_ip4(
1055 self.pg0,
1056 rx,
1057 tx,
1058 [
1059 VppMplsLabel(32),
1060 VppMplsLabel(33),
1061 VppMplsLabel(34),
1062 VppMplsLabel(44),
1063 VppMplsLabel(45),
1064 ],
1065 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001066
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001067 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001068
1069 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001070 self.verify_capture_labelled_ip4(
1071 self.pg0,
1072 rx,
1073 tx,
1074 [
1075 VppMplsLabel(32),
1076 VppMplsLabel(33),
1077 VppMplsLabel(34),
1078 VppMplsLabel(44),
1079 VppMplsLabel(45),
1080 ],
1081 )
Neale Ranns008dbe12018-09-07 09:32:36 -07001082
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001083 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 514)
Neale Ranns008dbe12018-09-07 09:32:36 -07001084
Neale Rannsad422ed2016-11-02 14:20:04 +00001085 #
1086 # cleanup
1087 #
1088 route_11_0_0_2.remove_vpp_config()
1089 route_11_0_0_1.remove_vpp_config()
1090 route_10_0_0_2.remove_vpp_config()
1091 route_10_0_0_1.remove_vpp_config()
1092
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301093 def test_imposition_fragmentation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001094 """MPLS label imposition fragmentation test"""
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301095
1096 #
1097 # Add a ipv4 non-recursive route with a single out label
1098 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001099 route_10_0_0_1 = VppIpRoute(
1100 self,
1101 "10.0.0.1",
1102 32,
1103 [
1104 VppRoutePath(
1105 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1106 )
1107 ],
1108 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301109 route_10_0_0_1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001110 route_1000_1 = VppIpRoute(
1111 self,
1112 "1000::1",
1113 128,
1114 [
1115 VppRoutePath(
1116 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1117 )
1118 ],
1119 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001120 route_1000_1.add_vpp_config()
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301121
1122 #
1123 # a stream that matches the route for 10.0.0.1
1124 # PG0 is in the default table
1125 #
1126 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
1127 for i in range(0, 257):
1128 self.extend_packet(tx[i], 10000)
1129
1130 #
1131 # 5 fragments per packet (257*5=1285)
1132 #
1133 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001134 self.verify_capture_fragmented_labelled_ip4(
1135 self.pg0, rx, tx, [VppMplsLabel(32)]
1136 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301137
Neale Rannsec5371e2022-03-04 11:45:41 +00001138 # packets with DF bit set generate ICMP
1139 for t in tx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001140 t[IP].flags = "DF"
Neale Rannsec5371e2022-03-04 11:45:41 +00001141 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1142
1143 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001144 self.assertEqual(icmptypes[rx[ICMP].type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001145 self.assertEqual(
1146 icmpcodes[rx[ICMP].type][rx[ICMP].code], "fragmentation-needed"
1147 )
Neale Rannsfbc633f2022-03-18 13:05:09 +00001148 # the link MTU is 9000, the MPLS over head is 4 bytes
1149 self.assertEqual(rx[ICMP].nexthopmtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001150
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001151 self.assertEqual(
Neale Rannse22a7042022-08-09 03:03:29 +00001152 self.statistics.get_err_counter("/err/mpls-frag/dont_fragment_set"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001153 len(tx),
1154 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001155 #
1156 # a stream that matches the route for 1000::1/128
1157 # PG0 is in the default table
1158 #
1159 tx = self.create_stream_ip6(self.pg0, "1000::1")
1160 for i in range(0, 257):
1161 self.extend_packet(tx[i], 10000)
1162
1163 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1164 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001165 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001166
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301167 #
1168 # cleanup
1169 #
1170 route_10_0_0_1.remove_vpp_config()
1171
Neale Ranns31ed7442018-02-23 05:29:09 -08001172 def test_tunnel_pipe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001173 """MPLS Tunnel Tests - Pipe"""
Neale Rannsad422ed2016-11-02 14:20:04 +00001174
1175 #
Ole Troaneb284a12019-10-09 13:33:19 +02001176 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +00001177 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001178 mpls_tun = VppMPLSTunnelInterface(
1179 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001180 [
1181 VppRoutePath(
1182 self.pg0.remote_ip4,
1183 self.pg0.sw_if_index,
1184 labels=[VppMplsLabel(44), VppMplsLabel(46)],
1185 )
1186 ],
1187 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001188 mpls_tun.add_vpp_config()
1189 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +00001190
1191 #
1192 # add an unlabelled route through the new tunnel
1193 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001194 route_10_0_0_3 = VppIpRoute(
1195 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1196 )
Neale Ranns5a8123b2017-01-26 01:18:23 -08001197 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +00001198
1199 self.vapi.cli("clear trace")
1200 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1201 self.pg0.add_stream(tx)
1202
1203 self.pg_enable_capture(self.pg_interfaces)
1204 self.pg_start()
1205
1206 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001207 self.verify_capture_tunneled_ip4(
1208 self.pg0, rx, tx, [VppMplsLabel(44), VppMplsLabel(46)]
1209 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001210
Neale Ranns8c4611b2017-05-23 03:43:47 -07001211 #
1212 # add a labelled route through the new tunnel
1213 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001214 route_10_0_0_4 = VppIpRoute(
1215 self,
1216 "10.0.0.4",
1217 32,
1218 [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index, labels=[33])],
1219 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001220 route_10_0_0_4.add_vpp_config()
1221
1222 self.vapi.cli("clear trace")
1223 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1224 self.pg0.add_stream(tx)
1225
1226 self.pg_enable_capture(self.pg_interfaces)
1227 self.pg_start()
1228
1229 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001230 self.verify_capture_tunneled_ip4(
1231 self.pg0,
1232 rx,
1233 tx,
1234 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1235 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001236
Ole Troaneb284a12019-10-09 13:33:19 +02001237 #
1238 # change tunnel's MTU to a low value
1239 #
1240 mpls_tun.set_l3_mtu(1200)
1241
1242 # send IP into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001243 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", payload_size=1500)
1244 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001245
1246 fake_tx = []
1247 for p in tx:
1248 fake_tx.append(p)
1249 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001250 self.verify_capture_tunneled_ip4(
1251 self.pg0, rx, fake_tx, [VppMplsLabel(44), VppMplsLabel(46)]
1252 )
Ole Troaneb284a12019-10-09 13:33:19 +02001253
1254 # send MPLS into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001255 tx = self.create_stream_ip4(self.pg0, "10.0.0.4", payload_size=1500)
1256 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001257
1258 fake_tx = []
1259 for p in tx:
1260 fake_tx.append(p)
1261 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001262 self.verify_capture_tunneled_ip4(
1263 self.pg0,
1264 rx,
1265 fake_tx,
1266 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1267 )
Ole Troaneb284a12019-10-09 13:33:19 +02001268
Neale Ranns31ed7442018-02-23 05:29:09 -08001269 def test_tunnel_uniform(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001270 """MPLS Tunnel Tests - Uniform"""
Neale Ranns31ed7442018-02-23 05:29:09 -08001271
1272 #
1273 # Create a tunnel with a single out label
1274 # The label stack is specified here from outer to inner
1275 #
1276 mpls_tun = VppMPLSTunnelInterface(
1277 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001278 [
1279 VppRoutePath(
1280 self.pg0.remote_ip4,
1281 self.pg0.sw_if_index,
1282 labels=[
1283 VppMplsLabel(44, ttl=32),
1284 VppMplsLabel(46, MplsLspMode.UNIFORM),
1285 ],
1286 )
1287 ],
1288 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001289 mpls_tun.add_vpp_config()
1290 mpls_tun.admin_up()
1291
1292 #
1293 # add an unlabelled route through the new tunnel
1294 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001295 route_10_0_0_3 = VppIpRoute(
1296 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1297 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001298 route_10_0_0_3.add_vpp_config()
1299
1300 self.vapi.cli("clear trace")
1301 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1302 self.pg0.add_stream(tx)
1303
1304 self.pg_enable_capture(self.pg_interfaces)
1305 self.pg_start()
1306
1307 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001308 self.verify_capture_tunneled_ip4(
1309 self.pg0, rx, tx, [VppMplsLabel(44, ttl=32), VppMplsLabel(46, ttl=23)]
1310 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001311
1312 #
1313 # add a labelled route through the new tunnel
1314 #
1315 route_10_0_0_4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001316 self,
1317 "10.0.0.4",
1318 32,
1319 [
1320 VppRoutePath(
1321 "0.0.0.0", mpls_tun._sw_if_index, labels=[VppMplsLabel(33, ttl=47)]
1322 )
1323 ],
1324 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001325 route_10_0_0_4.add_vpp_config()
1326
1327 self.vapi.cli("clear trace")
1328 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1329 self.pg0.add_stream(tx)
1330
1331 self.pg_enable_capture(self.pg_interfaces)
1332 self.pg_start()
1333
1334 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001335 self.verify_capture_tunneled_ip4(
1336 self.pg0,
1337 rx,
1338 tx,
1339 [
1340 VppMplsLabel(44, ttl=32),
1341 VppMplsLabel(46, ttl=47),
1342 VppMplsLabel(33, ttl=47),
1343 ],
1344 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001345
Vladislav Grishenko302db472024-01-24 16:17:23 +05001346 def test_tunnel_ecmp(self):
1347 """MPLS Tunnel Tests - ECMP"""
1348
1349 #
1350 # Create a tunnel with multiple paths and labels
1351 #
1352 self.pg0.generate_remote_hosts(2)
1353 self.pg0.configure_ipv4_neighbors()
1354 mpls_tun = VppMPLSTunnelInterface(
1355 self,
1356 [
1357 VppRoutePath(
1358 self.pg0.remote_hosts[0].ip4,
1359 self.pg0.sw_if_index,
1360 labels=[VppMplsLabel(3)],
1361 ),
1362 VppRoutePath(
1363 self.pg0.remote_hosts[1].ip4,
1364 self.pg0.sw_if_index,
1365 labels=[VppMplsLabel(44)],
1366 ),
1367 ],
1368 )
1369 mpls_tun.add_vpp_config()
1370 mpls_tun.admin_up()
1371
1372 self.vapi.cli("clear trace")
1373 pkts = self.create_stream_ip4(
1374 self.pg0, ["10.0.0.%d" % i for i in range(NUM_PKTS)], n=NUM_PKTS
1375 )
1376
1377 def send_and_expect_mpls_lb(pkts, path_labels, min_ratio):
1378 self.pg0.add_stream(pkts)
1379
1380 self.pg_enable_capture(self.pg_interfaces)
1381 self.pg_start()
1382
1383 rx = self.pg0.get_capture()
1384
1385 paths = {}
1386 for packet in rx:
1387 eth = packet[Ether]
1388 self.assertEqual(eth.type, 0x8847)
1389
1390 mpls = packet[MPLS]
1391 labels = []
1392 while True:
1393 labels.append(mpls.label)
1394 if mpls.s == 1:
1395 break
1396 mpls = mpls[MPLS].payload
1397 self.assertIn(labels, path_labels)
1398
1399 key = "{}-{}".format(eth.dst, "-".join(str(i) for i in labels))
1400 paths[key] = paths.get(key, 0) + 1
1401
1402 #
1403 # Check distribution over multiple mpls paths
1404 #
1405 self.assertEqual(len(paths), len(path_labels))
1406 for n in paths.values():
1407 self.assertGreaterEqual(n, NUM_PKTS / len(paths) * min_ratio)
1408
1409 #
1410 # Add labelled route through the new tunnel,
1411 # traffic should be balanced over all tunnel paths only.
1412 #
1413 route_10_0_0_0 = VppIpRoute(
1414 self,
1415 "10.0.0.0",
1416 16,
1417 [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index, labels=[33])],
1418 )
1419 route_10_0_0_0.add_vpp_config()
1420 send_and_expect_mpls_lb(pkts, [[33], [44, 33]], 0.85)
1421
1422 #
1423 # Add labelled multipath route through the new tunnel,
1424 # traffic should be balanced over both paths first and
1425 # then over all tunnel paths.
1426 #
1427 route_10_0_0_0 = VppIpRoute(
1428 self,
1429 "10.0.0.0",
1430 16,
1431 [
1432 VppRoutePath("0.0.0.1", mpls_tun._sw_if_index, labels=[33]),
1433 VppRoutePath("0.0.0.2", mpls_tun._sw_if_index, labels=[34]),
1434 ],
1435 )
1436 route_10_0_0_0.add_vpp_config()
1437 send_and_expect_mpls_lb(pkts, [[33], [44, 33], [34], [44, 34]], 0.70)
1438
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001439 def test_mpls_tunnel_many(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001440 """MPLS Multiple Tunnels"""
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001441
Neale Ranns397228d2021-10-21 12:02:53 +00001442 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001443 mpls_tun = VppMPLSTunnelInterface(
1444 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001445 [
1446 VppRoutePath(
1447 self.pg0.remote_ip4,
1448 self.pg0.sw_if_index,
1449 labels=[
1450 VppMplsLabel(44, ttl=32),
1451 VppMplsLabel(46, MplsLspMode.UNIFORM),
1452 ],
1453 )
1454 ],
1455 )
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001456 mpls_tun.add_vpp_config()
1457 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001458 for ii in range(100):
1459 mpls_tun = VppMPLSTunnelInterface(
1460 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001461 [
1462 VppRoutePath(
1463 self.pg0.remote_ip4,
1464 self.pg0.sw_if_index,
1465 labels=[
1466 VppMplsLabel(44, ttl=32),
1467 VppMplsLabel(46, MplsLspMode.UNIFORM),
1468 ],
1469 )
1470 ],
1471 is_l2=1,
1472 )
Neale Ranns397228d2021-10-21 12:02:53 +00001473 mpls_tun.add_vpp_config()
1474 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001475
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001476 def test_v4_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001477 """MPLS V4 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001478
1479 #
1480 # The first test case has an MPLS TTL of 0
1481 # all packet should be dropped
1482 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001483 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0, ttl=0)])
1484 self.send_and_assert_no_replies(self.pg0, tx, "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001485
1486 #
1487 # a stream with a non-zero MPLS TTL
1488 # PG0 is in the default table
1489 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001490 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1491 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001492 self.verify_capture_ip4(self.pg0, rx, tx)
1493
1494 #
1495 # a stream with a non-zero MPLS TTL
1496 # PG1 is in table 1
1497 # we are ensuring the post-pop lookup occurs in the VRF table
1498 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001499 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1500 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1501 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001502
1503 def test_v6_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001504 """MPLS V6 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001505
1506 #
1507 # a stream with a non-zero MPLS TTL
1508 # PG0 is in the default table
1509 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001510 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1511 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001512 self.verify_capture_ip6(self.pg0, rx, tx)
1513
1514 #
1515 # a stream with a non-zero MPLS TTL
1516 # PG1 is in table 1
1517 # we are ensuring the post-pop lookup occurs in the VRF table
1518 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001519 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1520 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001521 self.verify_capture_ip6(self.pg0, rx, tx)
1522
Neale Rannscb630ff2016-12-14 13:31:29 +01001523 def test_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001524 """MPLS Deagg"""
Neale Rannscb630ff2016-12-14 13:31:29 +01001525
1526 #
1527 # A de-agg route - next-hop lookup in default table
1528 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001529 route_34_eos = VppMplsRoute(
1530 self, 34, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
1531 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001532 route_34_eos.add_vpp_config()
1533
1534 #
1535 # ping an interface in the default table
1536 # PG0 is in the default table
1537 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001538 tx = self.create_stream_labelled_ip4(
1539 self.pg0, [VppMplsLabel(34)], ping=1, ip_itf=self.pg0
1540 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001541 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001542 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1543
1544 #
1545 # A de-agg route - next-hop lookup in non-default table
1546 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001547 route_35_eos = VppMplsRoute(
1548 self, 35, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
1549 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001550 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001551 route_356_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 self,
1553 356,
1554 1,
1555 [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=1)],
1556 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1557 )
Neale Rannsf478f752022-02-17 15:41:32 +00001558 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001559
1560 #
1561 # ping an interface in the non-default table
1562 # PG0 is in the default table. packet arrive labelled in the
1563 # default table and egress unlabelled in the non-default
1564 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001565 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001566 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1567 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001568 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001569 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001570 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001571 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1
1572 )
Neale Rannsf478f752022-02-17 15:41:32 +00001573 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1574 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001575
Neale Ranns6af1c042017-05-26 03:48:53 -07001576 #
1577 # Double pop
1578 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001579 route_36_neos = VppMplsRoute(self, 36, 0, [VppRoutePath("0.0.0.0", 0xFFFFFFFF)])
Neale Ranns6af1c042017-05-26 03:48:53 -07001580 route_36_neos.add_vpp_config()
1581
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001582 tx = self.create_stream_labelled_ip4(
1583 self.pg0, [VppMplsLabel(36), VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1584 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001585 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001586 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1587
1588 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001589 route_35_eos.remove_vpp_config()
1590 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001591
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001592 def test_interface_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001593 """MPLS Interface Receive"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001594
1595 #
1596 # Add a non-recursive route that will forward the traffic
1597 # post-interface-rx
1598 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001599 route_10_0_0_1 = VppIpRoute(
1600 self,
1601 "10.0.0.1",
1602 32,
1603 table_id=1,
1604 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1605 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001606 route_10_0_0_1.add_vpp_config()
1607
1608 #
1609 # An interface receive label that maps traffic to RX on interface
1610 # pg1
1611 # by injecting the packet in on pg0, which is in table 0
1612 # doing an interface-rx on pg1 and matching a route in table 1
1613 # if the packet egresses, then we must have swapped to pg1
1614 # so as to have matched the route in table 1
1615 #
Neale Ranns097fa662018-05-01 05:17:55 -07001616 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001617 self,
1618 34,
1619 1,
1620 [
1621 VppRoutePath(
1622 "0.0.0.0",
1623 self.pg1.sw_if_index,
1624 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1625 )
1626 ],
1627 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001628 route_34_eos.add_vpp_config()
1629
1630 #
1631 # ping an interface in the default table
1632 # PG0 is in the default table
1633 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001634 tx = self.create_stream_labelled_ip4(
1635 self.pg0, [VppMplsLabel(34)], dst_ip="10.0.0.1"
1636 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001637 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001638 self.verify_capture_ip4(self.pg1, rx, tx)
1639
1640 def test_mcast_mid_point(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001641 """MPLS Multicast Mid Point"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001642
1643 #
1644 # Add a non-recursive route that will forward the traffic
1645 # post-interface-rx
1646 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001647 route_10_0_0_1 = VppIpRoute(
1648 self,
1649 "10.0.0.1",
1650 32,
1651 table_id=1,
1652 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1653 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001654 route_10_0_0_1.add_vpp_config()
1655
1656 #
1657 # Add a mcast entry that replicate to pg2 and pg3
1658 # and replicate to a interface-rx (like a bud node would)
1659 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001660 route_3400_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001661 self,
1662 3400,
1663 1,
1664 [
1665 VppRoutePath(
1666 self.pg2.remote_ip4,
1667 self.pg2.sw_if_index,
1668 labels=[VppMplsLabel(3401)],
1669 ),
1670 VppRoutePath(
1671 self.pg3.remote_ip4,
1672 self.pg3.sw_if_index,
1673 labels=[VppMplsLabel(3402)],
1674 ),
1675 VppRoutePath(
1676 "0.0.0.0",
1677 self.pg1.sw_if_index,
1678 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1679 ),
1680 ],
1681 is_multicast=1,
1682 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001683 route_3400_eos.add_vpp_config()
1684
1685 #
1686 # ping an interface in the default table
1687 # PG0 is in the default table
1688 #
1689 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001690 tx = self.create_stream_labelled_ip4(
1691 self.pg0, [VppMplsLabel(3400, ttl=64)], n=257, dst_ip="10.0.0.1"
1692 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001693 self.pg0.add_stream(tx)
1694
1695 self.pg_enable_capture(self.pg_interfaces)
1696 self.pg_start()
1697
1698 rx = self.pg1.get_capture(257)
1699 self.verify_capture_ip4(self.pg1, rx, tx)
1700
1701 rx = self.pg2.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001702 self.verify_capture_labelled(self.pg2, rx, tx, [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001703 rx = self.pg3.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001704 self.verify_capture_labelled(self.pg3, rx, tx, [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001705
1706 def test_mcast_head(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001707 """MPLS Multicast Head-end"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001708
Neale Ranns990f6942020-10-20 07:20:17 +00001709 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1710 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1711
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001712 #
1713 # Create a multicast tunnel with two replications
1714 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001715 mpls_tun = VppMPLSTunnelInterface(
1716 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001717 [
1718 VppRoutePath(
1719 self.pg2.remote_ip4, self.pg2.sw_if_index, labels=[VppMplsLabel(42)]
1720 ),
1721 VppRoutePath(
1722 self.pg3.remote_ip4, self.pg3.sw_if_index, labels=[VppMplsLabel(43)]
1723 ),
1724 ],
1725 is_multicast=1,
1726 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001727 mpls_tun.add_vpp_config()
1728 mpls_tun.admin_up()
1729
1730 #
1731 # add an unlabelled route through the new tunnel
1732 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001733 route_10_0_0_3 = VppIpRoute(
1734 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1735 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001736 route_10_0_0_3.add_vpp_config()
1737
1738 self.vapi.cli("clear trace")
1739 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1740 self.pg0.add_stream(tx)
1741
1742 self.pg_enable_capture(self.pg_interfaces)
1743 self.pg_start()
1744
1745 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001746 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001747 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001748 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001749
1750 #
1751 # An an IP multicast route via the tunnel
1752 # A (*,G).
1753 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1754 #
1755 route_232_1_1_1 = VppIpMRoute(
1756 self,
1757 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001758 "232.1.1.1",
1759 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001760 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001761 [
1762 VppMRoutePath(
1763 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1764 ),
1765 VppMRoutePath(
1766 mpls_tun._sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1767 ),
1768 ],
1769 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001770 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001771 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001772
1773 self.vapi.cli("clear trace")
1774 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1775 self.pg0.add_stream(tx)
1776
1777 self.pg_enable_capture(self.pg_interfaces)
1778 self.pg_start()
1779
1780 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001781 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001782 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001783 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001784
Neale Ranns31426c62017-05-24 10:32:58 -07001785 def test_mcast_ip4_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001786 """MPLS IPv4 Multicast Tail"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001787
Neale Ranns990f6942020-10-20 07:20:17 +00001788 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1789 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1790
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001791 #
1792 # Add a multicast route that will forward the traffic
1793 # post-disposition
1794 #
1795 route_232_1_1_1 = VppIpMRoute(
1796 self,
1797 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001798 "232.1.1.1",
1799 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001800 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001801 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 paths=[
1803 VppMRoutePath(
1804 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1805 )
1806 ],
1807 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001808 route_232_1_1_1.add_vpp_config()
1809
1810 #
1811 # An interface receive label that maps traffic to RX on interface
1812 # pg1
1813 # by injecting the packet in on pg0, which is in table 0
1814 # doing an rpf-id and matching a route in table 1
1815 # if the packet egresses, then we must have matched the route in
1816 # table 1
1817 #
Neale Ranns097fa662018-05-01 05:17:55 -07001818 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001819 self,
1820 34,
1821 1,
1822 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001823 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001824 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1825 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001826
1827 route_34_eos.add_vpp_config()
1828
1829 #
1830 # Drop due to interface lookup miss
1831 #
1832 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001833 tx = self.create_stream_labelled_ip4(
1834 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=1
1835 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001836 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1837
1838 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001839 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001840 #
1841 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001842 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001843
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001844 tx = self.create_stream_labelled_ip4(
1845 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1846 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001847 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001848 self.verify_capture_ip4(self.pg1, rx, tx)
1849
1850 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001851 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001852 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001853 tx = self.create_stream_labelled_ip4(
1854 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=65, chksum=1
1855 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001856 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1857
1858 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001859 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001860 #
1861 route_232_1_1_1.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001862 tx = self.create_stream_labelled_ip4(
1863 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1864 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001865 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1866
Neale Ranns31426c62017-05-24 10:32:58 -07001867 def test_mcast_ip6_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001868 """MPLS IPv6 Multicast Tail"""
Neale Ranns31426c62017-05-24 10:32:58 -07001869
Neale Ranns990f6942020-10-20 07:20:17 +00001870 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1871 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1872
Neale Ranns31426c62017-05-24 10:32:58 -07001873 #
1874 # Add a multicast route that will forward the traffic
1875 # post-disposition
1876 #
1877 route_ff = VppIpMRoute(
1878 self,
1879 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001880 "ff01::1",
1881 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001882 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001883 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001884 paths=[
1885 VppMRoutePath(
1886 self.pg1.sw_if_index,
1887 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1888 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1889 )
1890 ],
1891 )
Neale Ranns31426c62017-05-24 10:32:58 -07001892 route_ff.add_vpp_config()
1893
1894 #
1895 # An interface receive label that maps traffic to RX on interface
1896 # pg1
1897 # by injecting the packet in on pg0, which is in table 0
1898 # doing an rpf-id and matching a route in table 1
1899 # if the packet egresses, then we must have matched the route in
1900 # table 1
1901 #
1902 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001903 self,
1904 34,
1905 1,
1906 [VppRoutePath("::", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001907 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001908 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1909 )
Neale Ranns31426c62017-05-24 10:32:58 -07001910
1911 route_34_eos.add_vpp_config()
1912
1913 #
1914 # Drop due to interface lookup miss
1915 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001916 tx = self.create_stream_labelled_ip6(
1917 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1918 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001919 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001920
1921 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001922 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001923 #
1924 route_ff.update_rpf_id(55)
1925
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001926 tx = self.create_stream_labelled_ip6(
1927 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1928 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001929 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001930 self.verify_capture_ip6(self.pg1, rx, tx)
1931
1932 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001933 # disposed packets have hop-limit = 1
1934 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001935 tx = self.create_stream_labelled_ip6(
1936 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1", hlim=1
1937 )
Neale Ranns5c6dd172022-02-17 09:08:47 +00001938 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001939 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001940
1941 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001942 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001943 #
1944 route_ff.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001945 tx = self.create_stream_labelled_ip6(
1946 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1947 )
Neale Ranns31426c62017-05-24 10:32:58 -07001948 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1949
Neale Rannsd5d7b962019-08-04 03:30:56 -07001950 def test_6pe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001951 """MPLS 6PE"""
Neale Rannsd5d7b962019-08-04 03:30:56 -07001952
1953 #
1954 # Add a non-recursive route with a single out label
1955 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001956 route_10_0_0_1 = VppIpRoute(
1957 self,
1958 "10.0.0.1",
1959 32,
1960 [
1961 VppRoutePath(
1962 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
1963 )
1964 ],
1965 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001966 route_10_0_0_1.add_vpp_config()
1967
1968 # bind a local label to the route
1969 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1970 binding.add_vpp_config()
1971
1972 #
1973 # a labelled v6 route that resolves through the v4
1974 #
1975 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001976 self,
1977 "2001::3",
1978 128,
1979 [VppRoutePath("10.0.0.1", INVALID_INDEX, labels=[VppMplsLabel(32)])],
1980 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001981 route_2001_3.add_vpp_config()
1982
1983 tx = self.create_stream_ip6(self.pg0, "2001::3")
1984 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1985
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001986 self.verify_capture_labelled_ip6(
1987 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32)]
1988 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001989
1990 #
1991 # and a v4 recursive via the v6
1992 #
1993 route_20_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001994 self,
1995 "20.0.0.3",
1996 32,
1997 [VppRoutePath("2001::3", INVALID_INDEX, labels=[VppMplsLabel(99)])],
1998 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001999 route_20_3.add_vpp_config()
2000
2001 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
2002 rx = self.send_and_expect(self.pg0, tx, self.pg0)
2003
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002004 self.verify_capture_labelled_ip4(
2005 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32), VppMplsLabel(99)]
2006 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07002007
Neale Ranns53962fb2021-12-20 18:18:42 +00002008 def test_attached(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002009 """Attach Routes with Local Label"""
Neale Ranns53962fb2021-12-20 18:18:42 +00002010
2011 #
2012 # test that if a local label is associated with an attached/connected
2013 # prefix, that we can reach hosts in the prefix.
2014 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002015 binding = VppMplsIpBind(
2016 self, 44, self.pg0._local_ip4_subnet, self.pg0.local_ip4_prefix_len
2017 )
Neale Ranns53962fb2021-12-20 18:18:42 +00002018 binding.add_vpp_config()
2019
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002020 tx = (
Steven Luonge4238aa2024-04-19 09:49:20 -07002021 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002022 / MPLS(label=44, ttl=64)
2023 / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
2024 / UDP(sport=1234, dport=1234)
2025 / Raw(b"\xa5" * 100)
2026 )
Neale Ranns53962fb2021-12-20 18:18:42 +00002027 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
2028 for rx in rxs:
2029 # if there's an ARP then the label is linked to the glean
2030 # which is wrong.
2031 self.assertFalse(rx.haslayer(ARP))
2032 # it should be unicasted to the host
2033 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
2034 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
2035
Neale Ranns180279b2017-03-16 15:49:09 -04002036
2037class TestMPLSDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002038 """MPLS disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04002039
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002040 @classmethod
2041 def setUpClass(cls):
2042 super(TestMPLSDisabled, cls).setUpClass()
2043
2044 @classmethod
2045 def tearDownClass(cls):
2046 super(TestMPLSDisabled, cls).tearDownClass()
2047
Neale Ranns180279b2017-03-16 15:49:09 -04002048 def setUp(self):
2049 super(TestMPLSDisabled, self).setUp()
2050
2051 # create 2 pg interfaces
2052 self.create_pg_interfaces(range(2))
2053
Neale Ranns15002542017-09-10 04:39:11 -07002054 self.tbl = VppMplsTable(self, 0)
2055 self.tbl.add_vpp_config()
2056
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002057 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04002058 self.pg0.admin_up()
2059 self.pg0.config_ip4()
2060 self.pg0.resolve_arp()
2061 self.pg0.enable_mpls()
2062
2063 # PG 1 is not MPLS enabled
2064 self.pg1.admin_up()
2065
2066 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04002067 for i in self.pg_interfaces:
2068 i.unconfig_ip4()
2069 i.admin_down()
2070
Neale Ranns15002542017-09-10 04:39:11 -07002071 self.pg0.disable_mpls()
2072 super(TestMPLSDisabled, self).tearDown()
2073
Neale Ranns180279b2017-03-16 15:49:09 -04002074 def test_mpls_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002075 """MPLS Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04002076
Neale Rannsde0b3b52021-06-15 12:43:12 +00002077 self.logger.info(self.vapi.cli("show mpls interface"))
2078 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2079 self.logger.info(self.vapi.cli("show mpls interface pg0"))
2080
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002081 tx = (
2082 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2083 / MPLS(label=32, ttl=64)
2084 / IPv6(src="2001::1", dst=self.pg0.remote_ip6)
2085 / UDP(sport=1234, dport=1234)
2086 / Raw(b"\xa5" * 100)
2087 )
Neale Ranns180279b2017-03-16 15:49:09 -04002088
2089 #
2090 # A simple MPLS xconnect - eos label in label out
2091 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002092 route_32_eos = VppMplsRoute(
2093 self,
2094 32,
2095 1,
2096 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[33])],
2097 )
Neale Ranns180279b2017-03-16 15:49:09 -04002098 route_32_eos.add_vpp_config()
2099
2100 #
2101 # PG1 does not forward IP traffic
2102 #
2103 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
2104
2105 #
2106 # MPLS enable PG1
2107 #
2108 self.pg1.enable_mpls()
2109
Neale Rannsde0b3b52021-06-15 12:43:12 +00002110 self.logger.info(self.vapi.cli("show mpls interface"))
2111 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2112
Neale Ranns180279b2017-03-16 15:49:09 -04002113 #
2114 # Now we get packets through
2115 #
2116 self.pg1.add_stream(tx)
2117 self.pg_enable_capture(self.pg_interfaces)
2118 self.pg_start()
2119
2120 rx = self.pg0.get_capture(1)
2121
2122 #
2123 # Disable PG1
2124 #
2125 self.pg1.disable_mpls()
2126
2127 #
2128 # PG1 does not forward IP traffic
2129 #
2130 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2131 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2132
2133
Neale Rannsf12a83f2017-04-18 09:09:40 -07002134class TestMPLSPIC(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002135 """MPLS Prefix-Independent Convergence (PIC) edge convergence"""
Neale Rannsf12a83f2017-04-18 09:09:40 -07002136
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002137 @classmethod
2138 def setUpClass(cls):
2139 super(TestMPLSPIC, cls).setUpClass()
2140
2141 @classmethod
2142 def tearDownClass(cls):
2143 super(TestMPLSPIC, cls).tearDownClass()
2144
Neale Rannsf12a83f2017-04-18 09:09:40 -07002145 def setUp(self):
2146 super(TestMPLSPIC, self).setUp()
2147
2148 # create 2 pg interfaces
2149 self.create_pg_interfaces(range(4))
2150
Neale Ranns15002542017-09-10 04:39:11 -07002151 mpls_tbl = VppMplsTable(self, 0)
2152 mpls_tbl.add_vpp_config()
2153 tbl4 = VppIpTable(self, 1)
2154 tbl4.add_vpp_config()
2155 tbl6 = VppIpTable(self, 1, is_ip6=1)
2156 tbl6.add_vpp_config()
2157
Neale Rannsf12a83f2017-04-18 09:09:40 -07002158 # core links
2159 self.pg0.admin_up()
2160 self.pg0.config_ip4()
2161 self.pg0.resolve_arp()
2162 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002163
Neale Rannsf12a83f2017-04-18 09:09:40 -07002164 self.pg1.admin_up()
2165 self.pg1.config_ip4()
2166 self.pg1.resolve_arp()
2167 self.pg1.enable_mpls()
2168
2169 # VRF (customer facing) link
2170 self.pg2.admin_up()
2171 self.pg2.set_table_ip4(1)
2172 self.pg2.config_ip4()
2173 self.pg2.resolve_arp()
2174 self.pg2.set_table_ip6(1)
2175 self.pg2.config_ip6()
2176 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002177
Neale Rannsf12a83f2017-04-18 09:09:40 -07002178 self.pg3.admin_up()
2179 self.pg3.set_table_ip4(1)
2180 self.pg3.config_ip4()
2181 self.pg3.resolve_arp()
2182 self.pg3.set_table_ip6(1)
2183 self.pg3.config_ip6()
2184 self.pg3.resolve_ndp()
2185
2186 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002187 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07002188 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002189 for i in self.pg_interfaces:
2190 i.unconfig_ip4()
2191 i.unconfig_ip6()
2192 i.set_table_ip4(0)
2193 i.set_table_ip6(0)
2194 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002195 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002196
2197 def test_mpls_ibgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002198 """MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002199
2200 1) setup many iBGP VPN routes via a pair of iBGP peers.
2201 2) Check EMCP forwarding to these peers
2202 3) withdraw the IGP route to one of these peers.
2203 4) check forwarding continues to the remaining peer
2204 """
2205
2206 #
2207 # IGP+LDP core routes
2208 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002209 core_10_0_0_45 = VppIpRoute(
2210 self,
2211 "10.0.0.45",
2212 32,
2213 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[45])],
2214 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002215 core_10_0_0_45.add_vpp_config()
2216
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002217 core_10_0_0_46 = VppIpRoute(
2218 self,
2219 "10.0.0.46",
2220 32,
2221 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[46])],
2222 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002223 core_10_0_0_46.add_vpp_config()
2224
2225 #
2226 # Lot's of VPN routes. We need more the 64 so VPP will build
2227 # the fast convergence indirection
2228 #
2229 vpn_routes = []
2230 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002231 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002232 dst = "192.168.1.%d" % ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002233 vpn_routes.append(
2234 VppIpRoute(
2235 self,
2236 dst,
2237 32,
2238 [
2239 VppRoutePath(
2240 "10.0.0.45",
2241 0xFFFFFFFF,
2242 labels=[145],
2243 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2244 ),
2245 VppRoutePath(
2246 "10.0.0.46",
2247 0xFFFFFFFF,
2248 labels=[146],
2249 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2250 ),
2251 ],
2252 table_id=1,
2253 )
2254 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002255 vpn_routes[ii].add_vpp_config()
2256
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002257 pkts.append(
2258 Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac)
2259 / IP(src=self.pg2.remote_ip4, dst=dst)
2260 / UDP(sport=1234, dport=1234)
2261 / Raw(b"\xa5" * 100)
2262 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002263
2264 #
2265 # Send the packet stream (one pkt to each VPN route)
2266 # - expect a 50-50 split of the traffic
2267 #
2268 self.pg2.add_stream(pkts)
2269 self.pg_enable_capture(self.pg_interfaces)
2270 self.pg_start()
2271
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002272 rx0 = self.pg0._get_capture(NUM_PKTS)
2273 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002274
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002275 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07002276 # with the split ratio, just as long as neither is 0
2277 self.assertNotEqual(0, len(rx0))
2278 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002279 self.assertEqual(
2280 len(pkts),
2281 len(rx0) + len(rx1),
2282 "Expected all (%s) packets across both ECMP paths. "
2283 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2284 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002285
2286 #
2287 # use a test CLI command to stop the FIB walk process, this
2288 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002289 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002290 #
2291 self.vapi.ppcli("test fib-walk-process disable")
2292
2293 #
2294 # Withdraw one of the IGP routes
2295 #
2296 core_10_0_0_46.remove_vpp_config()
2297
2298 #
2299 # now all packets should be forwarded through the remaining peer
2300 #
2301 self.vapi.ppcli("clear trace")
2302 self.pg2.add_stream(pkts)
2303 self.pg_enable_capture(self.pg_interfaces)
2304 self.pg_start()
2305
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002306 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002307 self.assertEqual(
2308 len(pkts),
2309 len(rx0),
2310 "Expected all (%s) packets across single path. "
2311 "rx0: %s." % (len(pkts), len(rx0)),
2312 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002313
2314 #
2315 # enable the FIB walk process to converge the FIB
2316 #
2317 self.vapi.ppcli("test fib-walk-process enable")
2318
2319 #
2320 # packets should still be forwarded through the remaining peer
2321 #
2322 self.pg2.add_stream(pkts)
2323 self.pg_enable_capture(self.pg_interfaces)
2324 self.pg_start()
2325
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002326 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002327 self.assertEqual(
2328 len(pkts),
2329 len(rx0),
2330 "Expected all (%s) packets across single path. "
2331 "rx0: %s." % (len(pkts), len(rx0)),
2332 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002333
2334 #
2335 # Add the IGP route back and we return to load-balancing
2336 #
2337 core_10_0_0_46.add_vpp_config()
2338
2339 self.pg2.add_stream(pkts)
2340 self.pg_enable_capture(self.pg_interfaces)
2341 self.pg_start()
2342
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002343 rx0 = self.pg0._get_capture(NUM_PKTS)
2344 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002345 self.assertNotEqual(0, len(rx0))
2346 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002347 self.assertEqual(
2348 len(pkts),
2349 len(rx0) + len(rx1),
2350 "Expected all (%s) packets across both ECMP paths. "
2351 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2352 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002353
2354 def test_mpls_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002355 """MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002356
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002357 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07002358 2) Check EMCP forwarding to these peers
2359 3) withdraw one eBGP path - expect LB across remaining eBGP
2360 """
2361
2362 #
2363 # Lot's of VPN routes. We need more the 64 so VPP will build
2364 # the fast convergence indirection
2365 #
2366 vpn_routes = []
2367 vpn_bindings = []
2368 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002369 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002370 dst = "192.168.1.%d" % ii
2371 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002372 vpn_routes.append(
2373 VppIpRoute(
2374 self,
2375 dst,
2376 32,
2377 [
2378 VppRoutePath(
2379 self.pg2.remote_ip4,
2380 0xFFFFFFFF,
2381 nh_table_id=1,
2382 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2383 ),
2384 VppRoutePath(
2385 self.pg3.remote_ip4,
2386 0xFFFFFFFF,
2387 nh_table_id=1,
2388 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2389 ),
2390 ],
2391 table_id=1,
2392 )
2393 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002394 vpn_routes[ii].add_vpp_config()
2395
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002396 vpn_bindings.append(
2397 VppMplsIpBind(self, local_label, dst, 32, ip_table_id=1)
2398 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002399 vpn_bindings[ii].add_vpp_config()
2400
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002401 pkts.append(
2402 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2403 / MPLS(label=local_label, ttl=64)
2404 / IP(src=self.pg0.remote_ip4, dst=dst)
2405 / UDP(sport=1234, dport=1234)
2406 / Raw(b"\xa5" * 100)
2407 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002408
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002409 #
2410 # Send the packet stream (one pkt to each VPN route)
2411 # - expect a 50-50 split of the traffic
2412 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002413 self.pg0.add_stream(pkts)
2414 self.pg_enable_capture(self.pg_interfaces)
2415 self.pg_start()
2416
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002417 rx0 = self.pg2._get_capture(NUM_PKTS)
2418 rx1 = self.pg3._get_capture(NUM_PKTS)
2419
2420 # not testing the LB hashing algorithm so we're not concerned
2421 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002422 self.assertNotEqual(0, len(rx0))
2423 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002424 self.assertEqual(
2425 len(pkts),
2426 len(rx0) + len(rx1),
2427 "Expected all (%s) packets across both ECMP paths. "
2428 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2429 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002430
2431 #
2432 # use a test CLI command to stop the FIB walk process, this
2433 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002434 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002435 #
2436 self.vapi.ppcli("test fib-walk-process disable")
2437
2438 #
2439 # withdraw the connected prefix on the interface.
2440 #
2441 self.pg2.unconfig_ip4()
2442
2443 #
2444 # now all packets should be forwarded through the remaining peer
2445 #
2446 self.pg0.add_stream(pkts)
2447 self.pg_enable_capture(self.pg_interfaces)
2448 self.pg_start()
2449
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002450 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002451 self.assertEqual(
2452 len(pkts),
2453 len(rx0),
2454 "Expected all (%s) packets across single path. "
2455 "rx0: %s." % (len(pkts), len(rx0)),
2456 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002457
2458 #
2459 # enable the FIB walk process to converge the FIB
2460 #
2461 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002462
2463 #
2464 # packets should still be forwarded through the remaining peer
2465 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002466 self.pg0.add_stream(pkts)
2467 self.pg_enable_capture(self.pg_interfaces)
2468 self.pg_start()
2469
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002470 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002471 self.assertEqual(
2472 len(pkts),
2473 len(rx0),
2474 "Expected all (%s) packets across single path. "
2475 "rx0: %s." % (len(pkts), len(rx0)),
2476 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002477
2478 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002479 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002480 #
2481 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002482 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002483
2484 self.pg0.add_stream(pkts)
2485 self.pg_enable_capture(self.pg_interfaces)
2486 self.pg_start()
2487
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002488 rx0 = self.pg2._get_capture(NUM_PKTS)
2489 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002490 self.assertNotEqual(0, len(rx0))
2491 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002492 self.assertEqual(
2493 len(pkts),
2494 len(rx0) + len(rx1),
2495 "Expected all (%s) packets across both ECMP paths. "
2496 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2497 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002498
2499 def test_mpls_v6_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002500 """MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002501
2502 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2503 2) Check EMCP forwarding to these peers
2504 3) withdraw one eBGP path - expect LB across remaining eBGP
2505 """
2506
2507 #
2508 # Lot's of VPN routes. We need more the 64 so VPP will build
2509 # the fast convergence indirection
2510 #
2511 vpn_routes = []
2512 vpn_bindings = []
2513 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002514 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002515 dst = "3000::%d" % ii
2516 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002517 vpn_routes.append(
2518 VppIpRoute(
2519 self,
2520 dst,
2521 128,
2522 [
2523 VppRoutePath(
2524 self.pg2.remote_ip6,
2525 0xFFFFFFFF,
2526 nh_table_id=1,
2527 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2528 ),
2529 VppRoutePath(
2530 self.pg3.remote_ip6,
2531 0xFFFFFFFF,
2532 nh_table_id=1,
2533 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2534 ),
2535 ],
2536 table_id=1,
2537 )
2538 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002539 vpn_routes[ii].add_vpp_config()
2540
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002541 vpn_bindings.append(
2542 VppMplsIpBind(self, local_label, dst, 128, ip_table_id=1)
2543 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002544 vpn_bindings[ii].add_vpp_config()
2545
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 pkts.append(
2547 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2548 / MPLS(label=local_label, ttl=64)
2549 / IPv6(src=self.pg0.remote_ip6, dst=dst)
2550 / UDP(sport=1234, dport=1234)
2551 / Raw(b"\xa5" * 100)
2552 )
Neale Ranns097fa662018-05-01 05:17:55 -07002553 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002554
2555 self.pg0.add_stream(pkts)
2556 self.pg_enable_capture(self.pg_interfaces)
2557 self.pg_start()
2558
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002559 rx0 = self.pg2._get_capture(NUM_PKTS)
2560 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002561 self.assertNotEqual(0, len(rx0))
2562 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002563 self.assertEqual(
2564 len(pkts),
2565 len(rx0) + len(rx1),
2566 "Expected all (%s) packets across both ECMP paths. "
2567 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2568 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002569
2570 #
2571 # use a test CLI command to stop the FIB walk process, this
2572 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002573 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002574 #
2575 self.vapi.ppcli("test fib-walk-process disable")
2576
2577 #
2578 # withdraw the connected prefix on the interface.
2579 # and shutdown the interface so the ND cache is flushed.
2580 #
2581 self.pg2.unconfig_ip6()
2582 self.pg2.admin_down()
2583
2584 #
2585 # now all packets should be forwarded through the remaining peer
2586 #
2587 self.pg0.add_stream(pkts)
2588 self.pg_enable_capture(self.pg_interfaces)
2589 self.pg_start()
2590
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002591 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002592 self.assertEqual(
2593 len(pkts),
2594 len(rx0),
2595 "Expected all (%s) packets across single path. "
2596 "rx0: %s." % (len(pkts), len(rx0)),
2597 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002598
2599 #
2600 # enable the FIB walk process to converge the FIB
2601 #
2602 self.vapi.ppcli("test fib-walk-process enable")
2603 self.pg0.add_stream(pkts)
2604 self.pg_enable_capture(self.pg_interfaces)
2605 self.pg_start()
2606
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002607 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002608 self.assertEqual(
2609 len(pkts),
2610 len(rx0),
2611 "Expected all (%s) packets across single path. "
2612 "rx0: %s." % (len(pkts), len(rx0)),
2613 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002614
2615 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002616 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002617 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002618 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002619 self.pg2.admin_up()
2620 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002621 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002622
2623 self.pg0.add_stream(pkts)
2624 self.pg_enable_capture(self.pg_interfaces)
2625 self.pg_start()
2626
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002627 rx0 = self.pg2._get_capture(NUM_PKTS)
2628 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002629 self.assertNotEqual(0, len(rx0))
2630 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002631 self.assertEqual(
2632 len(pkts),
2633 len(rx0) + len(rx1),
2634 "Expected all (%s) packets across both ECMP paths. "
2635 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2636 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002637
2638
Neale Rannsda78f952017-05-24 09:15:43 -07002639class TestMPLSL2(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002640 """MPLS-L2"""
Neale Rannsda78f952017-05-24 09:15:43 -07002641
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002642 @classmethod
2643 def setUpClass(cls):
2644 super(TestMPLSL2, cls).setUpClass()
2645
2646 @classmethod
2647 def tearDownClass(cls):
2648 super(TestMPLSL2, cls).tearDownClass()
2649
Neale Rannsda78f952017-05-24 09:15:43 -07002650 def setUp(self):
2651 super(TestMPLSL2, self).setUp()
2652
2653 # create 2 pg interfaces
2654 self.create_pg_interfaces(range(2))
2655
Neale Ranns15002542017-09-10 04:39:11 -07002656 # create the default MPLS table
2657 self.tables = []
2658 tbl = VppMplsTable(self, 0)
2659 tbl.add_vpp_config()
2660 self.tables.append(tbl)
2661
Neale Ranns1976f362019-11-06 13:13:01 +00002662 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002663 self.pg0.admin_up()
2664 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002665 self.pg0.enable_mpls()
2666
Neale Ranns15002542017-09-10 04:39:11 -07002667 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002668 for i in self.pg_interfaces[1:]:
2669 i.admin_up()
2670
2671 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002672 for i in self.pg_interfaces[1:]:
2673 i.admin_down()
2674
2675 self.pg0.disable_mpls()
2676 self.pg0.unconfig_ip4()
2677 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002678 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002679
Neale Ranns31ed7442018-02-23 05:29:09 -08002680 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002681 capture = verify_filter(capture, sent)
2682
2683 self.assertEqual(len(capture), len(sent))
2684
2685 for i in range(len(capture)):
2686 tx = sent[i]
2687 rx = capture[i]
2688
2689 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002690 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002691
2692 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002693 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002694
2695 self.assertEqual(rx_eth.src, tx_eth.src)
2696 self.assertEqual(rx_eth.dst, tx_eth.dst)
2697
Neale Ranns1976f362019-11-06 13:13:01 +00002698 def verify_arp_req(self, rx, smac, sip, dip):
2699 ether = rx[Ether]
2700 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2701 self.assertEqual(ether.src, smac)
2702
2703 arp = rx[ARP]
2704 self.assertEqual(arp.hwtype, 1)
2705 self.assertEqual(arp.ptype, 0x800)
2706 self.assertEqual(arp.hwlen, 6)
2707 self.assertEqual(arp.plen, 4)
2708 self.assertEqual(arp.op, ARP.who_has)
2709 self.assertEqual(arp.hwsrc, smac)
2710 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2711 self.assertEqual(arp.psrc, sip)
2712 self.assertEqual(arp.pdst, dip)
2713
Neale Rannsda78f952017-05-24 09:15:43 -07002714 def test_vpws(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002715 """Virtual Private Wire Service"""
Neale Rannsda78f952017-05-24 09:15:43 -07002716
2717 #
2718 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002719 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2720 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002721 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002722 mpls_tun_1 = VppMPLSTunnelInterface(
2723 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002724 [
2725 VppRoutePath(
2726 self.pg0.remote_ip4,
2727 self.pg0.sw_if_index,
2728 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)],
2729 )
2730 ],
2731 is_l2=1,
2732 )
Neale Rannsda78f952017-05-24 09:15:43 -07002733 mpls_tun_1.add_vpp_config()
2734 mpls_tun_1.admin_up()
2735
2736 #
2737 # Create a label entry to for 55 that does L2 input to the tunnel
2738 #
2739 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002740 self,
2741 55,
2742 1,
2743 [
2744 VppRoutePath(
2745 "0.0.0.0",
2746 mpls_tun_1.sw_if_index,
2747 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2748 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2749 )
2750 ],
2751 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2752 )
Neale Rannsda78f952017-05-24 09:15:43 -07002753 route_55_eos.add_vpp_config()
2754
2755 #
2756 # Cross-connect the tunnel with one of the customers L2 interfaces
2757 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002758 self.vapi.sw_interface_set_l2_xconnect(
2759 self.pg1.sw_if_index, mpls_tun_1.sw_if_index, enable=1
2760 )
2761 self.vapi.sw_interface_set_l2_xconnect(
2762 mpls_tun_1.sw_if_index, self.pg1.sw_if_index, enable=1
2763 )
Neale Rannsda78f952017-05-24 09:15:43 -07002764
2765 #
2766 # inject a packet from the core
2767 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002768 pcore = (
2769 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2770 / MPLS(label=55, ttl=64)
2771 / Ether(dst="00:00:de:ad:ba:be", src="00:00:de:ad:be:ef")
2772 / IP(src="10.10.10.10", dst="11.11.11.11")
2773 / UDP(sport=1234, dport=1234)
2774 / Raw(b"\xa5" * 100)
2775 )
Neale Rannsda78f952017-05-24 09:15:43 -07002776
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002777 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002778 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2779 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002780
Neale Ranns31ed7442018-02-23 05:29:09 -08002781 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2782 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002783
2784 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002785 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002786 # there's no resolved ARP entry so the first packet we see should be
2787 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002788 #
Neale Ranns1976f362019-11-06 13:13:01 +00002789 tx1 = pcore[MPLS].payload
2790 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2791
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002792 self.verify_arp_req(
2793 rx1[0], self.pg0.local_mac, self.pg0.local_ip4, self.pg0.remote_ip4
2794 )
Neale Ranns1976f362019-11-06 13:13:01 +00002795
2796 #
2797 # resolve the ARP entries and send again
2798 #
2799 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002800 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002801 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002802
Neale Ranns31ed7442018-02-23 05:29:09 -08002803 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002804
2805 def test_vpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002806 """Virtual Private LAN Service"""
Neale Ranns1976f362019-11-06 13:13:01 +00002807
2808 # we skipped this in the setup
2809 self.pg0.resolve_arp()
2810
Neale Rannsda78f952017-05-24 09:15:43 -07002811 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002812 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002813 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002814 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002815 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002816 [
2817 VppRoutePath(
2818 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(42)]
2819 )
2820 ],
2821 is_l2=1,
2822 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002823 mpls_tun1.add_vpp_config()
2824 mpls_tun1.admin_up()
2825
2826 mpls_tun2 = VppMPLSTunnelInterface(
2827 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002828 [
2829 VppRoutePath(
2830 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(43)]
2831 )
2832 ],
2833 is_l2=1,
2834 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002835 mpls_tun2.add_vpp_config()
2836 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002837
2838 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002839 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2840 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002841 #
2842 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002843 self,
2844 55,
2845 1,
2846 [
2847 VppRoutePath(
2848 "0.0.0.0",
2849 mpls_tun1.sw_if_index,
2850 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2851 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2852 )
2853 ],
2854 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2855 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002856
2857 route_56_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002858 self,
2859 56,
2860 1,
2861 [
2862 VppRoutePath(
2863 "0.0.0.0",
2864 mpls_tun2.sw_if_index,
2865 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2866 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2867 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2868 )
2869 ],
2870 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2871 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002872
2873 # move me
2874 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002875 route_55_eos.add_vpp_config()
2876
Neale Ranns1dbcf302019-07-19 11:44:53 +00002877 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2878
Neale Rannsda78f952017-05-24 09:15:43 -07002879 #
2880 # add to tunnel to the customers bridge-domain
2881 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002882 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002883 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1
2884 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002885 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002886 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1
2887 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002888 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002889 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1
2890 )
Neale Rannsda78f952017-05-24 09:15:43 -07002891
2892 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002893 # Packet from host on the customer interface to each host
2894 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002895 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002896 p_cust1 = (
2897 Ether(dst="00:00:de:ad:ba:b1", src="00:00:de:ad:be:ef")
2898 / IP(src="10.10.10.10", dst="11.11.11.11")
2899 / UDP(sport=1234, dport=1234)
2900 / Raw(b"\xa5" * 100)
2901 )
2902 p_cust2 = (
2903 Ether(dst="00:00:de:ad:ba:b2", src="00:00:de:ad:be:ef")
2904 / IP(src="10.10.10.10", dst="11.11.11.12")
2905 / UDP(sport=1234, dport=1234)
2906 / Raw(b"\xa5" * 100)
2907 )
2908 p_core1 = (
2909 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2910 / MPLS(label=55, ttl=64)
2911 / Ether(src="00:00:de:ad:ba:b1", dst="00:00:de:ad:be:ef")
2912 / IP(dst="10.10.10.10", src="11.11.11.11")
2913 / UDP(sport=1234, dport=1234)
2914 / Raw(b"\xa5" * 100)
2915 )
2916 p_core2 = (
2917 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2918 / MPLS(label=56, ttl=64)
2919 / Raw(b"\x01" * 4)
2920 / Ether(src="00:00:de:ad:ba:b2", dst="00:00:de:ad:be:ef") # PW CW
2921 / IP(dst="10.10.10.10", src="11.11.11.12")
2922 / UDP(sport=1234, dport=1234)
2923 / Raw(b"\xa5" * 100)
2924 )
Neale Rannsda78f952017-05-24 09:15:43 -07002925
2926 #
2927 # The BD is learning, so send in one of each packet to learn
2928 #
Neale Rannsda78f952017-05-24 09:15:43 -07002929
Neale Ranns1dbcf302019-07-19 11:44:53 +00002930 # 2 packets due to BD flooding
2931 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2932 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002933
Neale Ranns1dbcf302019-07-19 11:44:53 +00002934 # we've learnt this so expect it be be forwarded not flooded
2935 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2936 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2937 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002938
Neale Ranns1dbcf302019-07-19 11:44:53 +00002939 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2940 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2941 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002942
2943 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002944 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002945 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002946 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002947 self.verify_capture_tunneled_ethernet(
2948 rx, p_cust1 * NUM_PKTS, [VppMplsLabel(42)]
2949 )
Neale Rannsda78f952017-05-24 09:15:43 -07002950
Neale Ranns1dbcf302019-07-19 11:44:53 +00002951 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002952 self.verify_capture_tunneled_ethernet(
2953 rx, p_cust2 * NUM_PKTS, [VppMplsLabel(43)]
2954 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002955
2956 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2957 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2958
Neale Rannsda78f952017-05-24 09:15:43 -07002959 #
2960 # remove interfaces from customers bridge-domain
2961 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002962 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002963 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0
2964 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002965 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002966 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0
2967 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002968 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002969 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0
2970 )
Neale Rannsda78f952017-05-24 09:15:43 -07002971
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002972
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002973if __name__ == "__main__":
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002974 unittest.main(testRunner=VppTestRunner)