blob: 846179765dc7babe7c18e148c58231ea3a1ffb4f [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002
3import unittest
Gabriel Gannea9b2d582016-12-06 10:25:34 +01004import socket
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00006from framework import tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +00007from framework import VppTestCase, VppTestRunner
Neale Rannsd5d7b962019-08-04 03:30:56 -07008from vpp_ip import DpoProto, INVALID_INDEX
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02009from vpp_ip_route import (
10 VppIpRoute,
11 VppRoutePath,
12 VppMplsRoute,
13 VppMplsIpBind,
14 VppIpMRoute,
15 VppMRoutePath,
16 VppIpTable,
17 VppMplsTable,
18 VppMplsLabel,
19 MplsLspMode,
20 find_mpls_route,
21 FibPathProto,
22 FibPathType,
23 FibPathFlags,
24 VppMplsLabel,
25 MplsLspMode,
26)
Neale Ranns0f26c5a2017-03-01 15:12:11 -080027from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns990f6942020-10-20 07:20:17 +000028from vpp_papi import VppEnum
Neale Ranns8fe8cc22016-11-01 10:05:08 +000029
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070030import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000031from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000032from scapy.layers.l2 import Ether, ARP
Neale Rannsfbc633f2022-03-18 13:05:09 +000033from scapy.layers.inet import IP, UDP, ICMP, icmptypes, icmpcodes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034from scapy.layers.inet6 import (
35 IPv6,
36 ICMPv6TimeExceeded,
37 ICMPv6EchoRequest,
38 ICMPv6PacketTooBig,
39)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000040from scapy.contrib.mpls import MPLS
41
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040042NUM_PKTS = 67
43
Neale Ranns1976f362019-11-06 13:13:01 +000044# scapy removed these attributes.
45# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
46# semantic names have more meaning than numbers. so here they are.
47ARP.who_has = 1
48ARP.is_at = 2
49
Klement Sekeradab231a2016-12-21 08:50:14 +010050
Neale Rannsda78f952017-05-24 09:15:43 -070051def verify_filter(capture, sent):
52 if not len(capture) == len(sent):
53 # filter out any IPv6 RAs from the capture
54 for p in capture:
55 if p.haslayer(IPv6):
56 capture.remove(p)
57 return capture
58
59
Neale Ranns31ed7442018-02-23 05:29:09 -080060def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070061 # the rx'd packet has the MPLS label popped
62 eth = rx[Ether]
63 tst.assertEqual(eth.type, 0x8847)
64
65 rx_mpls = rx[MPLS]
66
67 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080068 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
69 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
70 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
71
Neale Rannsda78f952017-05-24 09:15:43 -070072 if ii == len(mpls_labels) - 1:
73 tst.assertEqual(rx_mpls.s, 1)
74 else:
75 # not end of stack
76 tst.assertEqual(rx_mpls.s, 0)
77 # pop the label to expose the next
78 rx_mpls = rx_mpls[MPLS].payload
79
80
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000081@tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +000082class TestMPLS(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020083 """MPLS Test Case"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +000084
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070085 @classmethod
86 def setUpClass(cls):
87 super(TestMPLS, cls).setUpClass()
88
89 @classmethod
90 def tearDownClass(cls):
91 super(TestMPLS, cls).tearDownClass()
92
Neale Ranns8fe8cc22016-11-01 10:05:08 +000093 def setUp(self):
94 super(TestMPLS, self).setUp()
95
96 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080097 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000098
99 # setup both interfaces
100 # assign them different tables.
101 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -0700102 self.tables = []
103
104 tbl = VppMplsTable(self, 0)
105 tbl.add_vpp_config()
106 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000107
108 for i in self.pg_interfaces:
109 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -0700110
111 if table_id != 0:
112 tbl = VppIpTable(self, table_id)
113 tbl.add_vpp_config()
114 self.tables.append(tbl)
115 tbl = VppIpTable(self, table_id, is_ip6=1)
116 tbl.add_vpp_config()
117 self.tables.append(tbl)
118
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000119 i.set_table_ip4(table_id)
120 i.set_table_ip6(table_id)
121 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000122 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000123 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000124 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000125 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000126 table_id += 1
127
128 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800129 for i in self.pg_interfaces:
130 i.unconfig_ip4()
131 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700132 i.set_table_ip4(0)
133 i.set_table_ip6(0)
134 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800135 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700136 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000137
Neale Rannsad422ed2016-11-02 14:20:04 +0000138 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100139 def create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200140 self,
141 src_if,
142 mpls_labels,
143 ping=0,
144 ip_itf=None,
145 dst_ip=None,
146 chksum=None,
147 ip_ttl=64,
148 n=257,
149 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100150 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000151 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800152 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100153 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000154 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000155 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
156
157 for ii in range(len(mpls_labels)):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200158 p = p / MPLS(
159 label=mpls_labels[ii].value,
160 ttl=mpls_labels[ii].ttl,
161 cos=mpls_labels[ii].exp,
162 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100163 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800164 if not dst_ip:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 p = (
166 p
167 / IP(src=src_if.local_ip4, dst=src_if.remote_ip4, ttl=ip_ttl)
168 / UDP(sport=1234, dport=1234)
169 / Raw(payload)
170 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800171 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200172 p = (
173 p
174 / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl)
175 / UDP(sport=1234, dport=1234)
176 / Raw(payload)
177 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100178 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200179 p = (
180 p
181 / IP(src=ip_itf.remote_ip4, dst=ip_itf.local_ip4, ttl=ip_ttl)
182 / ICMP()
183 )
Neale Rannscb630ff2016-12-14 13:31:29 +0100184
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700185 if chksum:
186 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000187 info.data = p.copy()
188 pkts.append(p)
189 return pkts
190
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200191 def create_stream_ip4(
192 self, src_if, dst_ip, ip_ttl=64, ip_dscp=0, payload_size=None
193 ):
Klement Sekeradab231a2016-12-21 08:50:14 +0100194 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000195 pkts = []
196 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100197 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000198 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199 p = (
200 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
201 / IP(src=src_if.remote_ip4, dst=dst_ip, ttl=ip_ttl, tos=ip_dscp)
202 / UDP(sport=1234, dport=1234)
203 / Raw(payload)
204 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000205 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200206 if payload_size:
207 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000208 pkts.append(p)
209 return pkts
210
Neale Ranns31ed7442018-02-23 05:29:09 -0800211 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
212 self.reset_packet_infos()
213 pkts = []
214 for i in range(0, 257):
215 info = self.create_packet_info(src_if, src_if)
216 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 p = (
218 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
219 / IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=ip_ttl, tc=ip_dscp)
220 / UDP(sport=1234, dport=1234)
221 / Raw(payload)
222 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800223 info.data = p.copy()
224 pkts.append(p)
225 return pkts
226
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200227 def create_stream_labelled_ip6(
228 self, src_if, mpls_labels, hlim=64, dst_ip=None, ping=0, ip_itf=None
229 ):
Neale Ranns31426c62017-05-24 10:32:58 -0700230 if dst_ip is None:
231 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100232 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000233 pkts = []
234 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100235 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000236 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800237 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
238 for l in mpls_labels:
239 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
240
Neale Rannsf478f752022-02-17 15:41:32 +0000241 if ping:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 p = p / (
243 IPv6(src=ip_itf.remote_ip6, dst=ip_itf.local_ip6)
244 / ICMPv6EchoRequest()
245 )
Neale Rannsf478f752022-02-17 15:41:32 +0000246 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200247 p = p / (
248 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim)
249 / UDP(sport=1234, dport=1234)
250 / Raw(payload)
251 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000252 info.data = p.copy()
253 pkts.append(p)
254 return pkts
255
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 def verify_capture_ip4(
257 self, src_if, capture, sent, ping_resp=0, ip_ttl=None, ip_dscp=0
258 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000259 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700260 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000261
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000262 self.assertEqual(len(capture), len(sent))
263
264 for i in range(len(capture)):
265 tx = sent[i]
266 rx = capture[i]
267
268 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000269 eth = rx[Ether]
270 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000271
272 tx_ip = tx[IP]
273 rx_ip = rx[IP]
274
Neale Rannscb630ff2016-12-14 13:31:29 +0100275 if not ping_resp:
276 self.assertEqual(rx_ip.src, tx_ip.src)
277 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800278 self.assertEqual(rx_ip.tos, ip_dscp)
279 if not ip_ttl:
280 # IP processing post pop has decremented the TTL
281 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
282 else:
283 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100284 else:
285 self.assertEqual(rx_ip.src, tx_ip.dst)
286 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000287
288 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000289 raise
290
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200291 def verify_capture_labelled_ip4(
292 self, src_if, capture, sent, mpls_labels, ip_ttl=None
293 ):
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700295 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000296
297 self.assertEqual(len(capture), len(sent))
298
299 for i in range(len(capture)):
300 tx = sent[i]
301 rx = capture[i]
302 tx_ip = tx[IP]
303 rx_ip = rx[IP]
304
Neale Ranns31ed7442018-02-23 05:29:09 -0800305 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000306
307 self.assertEqual(rx_ip.src, tx_ip.src)
308 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800309 if not ip_ttl:
310 # IP processing post pop has decremented the TTL
311 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
312 else:
313 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000314
315 except:
316 raise
317
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 def verify_capture_labelled_ip6(
319 self, src_if, capture, sent, mpls_labels, ip_ttl=None
320 ):
Neale Ranns31ed7442018-02-23 05:29:09 -0800321 try:
322 capture = verify_filter(capture, sent)
323
324 self.assertEqual(len(capture), len(sent))
325
326 for i in range(len(capture)):
327 tx = sent[i]
328 rx = capture[i]
329 tx_ip = tx[IPv6]
330 rx_ip = rx[IPv6]
331
332 verify_mpls_stack(self, rx, mpls_labels)
333
334 self.assertEqual(rx_ip.src, tx_ip.src)
335 self.assertEqual(rx_ip.dst, tx_ip.dst)
336 if not ip_ttl:
337 # IP processing post pop has decremented the TTL
338 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
339 else:
340 self.assertEqual(rx_ip.hlim, ip_ttl)
341
342 except:
343 raise
344
345 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000346 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700347 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000348
349 self.assertEqual(len(capture), len(sent))
350
351 for i in range(len(capture)):
352 tx = sent[i]
353 rx = capture[i]
354 tx_ip = tx[IP]
355 rx_ip = rx[IP]
356
Neale Ranns31ed7442018-02-23 05:29:09 -0800357 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000358
359 self.assertEqual(rx_ip.src, tx_ip.src)
360 self.assertEqual(rx_ip.dst, tx_ip.dst)
361 # IP processing post pop has decremented the TTL
362 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
363
364 except:
365 raise
366
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 def verify_capture_labelled(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000368 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700369 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000370
371 self.assertEqual(len(capture), len(sent))
372
373 for i in range(len(capture)):
374 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800375 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000376 except:
377 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000378
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 def verify_capture_ip6(
380 self, src_if, capture, sent, ip_hlim=None, ip_dscp=0, ping_resp=0
381 ):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000382 try:
383 self.assertEqual(len(capture), len(sent))
384
385 for i in range(len(capture)):
386 tx = sent[i]
387 rx = capture[i]
388
389 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000390 eth = rx[Ether]
391 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000392
393 tx_ip = tx[IPv6]
394 rx_ip = rx[IPv6]
395
Neale Rannsf478f752022-02-17 15:41:32 +0000396 if not ping_resp:
397 self.assertEqual(rx_ip.src, tx_ip.src)
398 self.assertEqual(rx_ip.dst, tx_ip.dst)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Rannsf478f752022-02-17 15:41:32 +0000400 # IP processing post pop has decremented the TTL
401 if not ip_hlim:
402 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
403 else:
404 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns31ed7442018-02-23 05:29:09 -0800405 else:
Neale Rannsf478f752022-02-17 15:41:32 +0000406 self.assertEqual(rx_ip.src, tx_ip.dst)
407 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000408 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000409 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000410
Neale Ranns62fe07c2017-10-31 12:28:22 -0700411 def verify_capture_ip6_icmp(self, src_if, capture, sent):
412 try:
Neale Ranns5c6dd172022-02-17 09:08:47 +0000413 # rate limited ICMP
414 self.assertTrue(len(capture) <= len(sent))
Neale Ranns62fe07c2017-10-31 12:28:22 -0700415
416 for i in range(len(capture)):
417 tx = sent[i]
418 rx = capture[i]
419
420 # the rx'd packet has the MPLS label popped
421 eth = rx[Ether]
422 self.assertEqual(eth.type, 0x86DD)
423
424 tx_ip = tx[IPv6]
425 rx_ip = rx[IPv6]
426
427 self.assertEqual(rx_ip.dst, tx_ip.src)
428 # ICMP sourced from the interface's address
429 self.assertEqual(rx_ip.src, src_if.local_ip6)
430 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200431 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700432
433 icmp = rx[ICMPv6TimeExceeded]
434
435 except:
436 raise
437
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200438 def verify_capture_fragmented_labelled_ip4(
439 self, src_if, capture, sent, mpls_labels, ip_ttl=None
440 ):
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530441 try:
442 capture = verify_filter(capture, sent)
443
444 for i in range(len(capture)):
445 tx = sent[0]
446 rx = capture[i]
447 tx_ip = tx[IP]
448 rx_ip = rx[IP]
449
450 verify_mpls_stack(self, rx, mpls_labels)
451
452 self.assertEqual(rx_ip.src, tx_ip.src)
453 self.assertEqual(rx_ip.dst, tx_ip.dst)
454 if not ip_ttl:
455 # IP processing post pop has decremented the TTL
456 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
457 else:
458 self.assertEqual(rx_ip.ttl, ip_ttl)
459
460 except:
461 raise
462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200463 def verify_capture_fragmented_labelled_ip6(
464 self, src_if, capture, sent, mpls_labels, ip_ttl=None
465 ):
Neale Rannsec5371e2022-03-04 11:45:41 +0000466 try:
467 capture = verify_filter(capture, sent)
468
469 for i in range(len(capture)):
470 tx = sent[0]
471 rx = capture[i]
472 tx_ip = tx[IPv6]
473 rx.show()
474 rx_ip = IPv6(rx[MPLS].payload)
475 rx_ip.show()
476
477 verify_mpls_stack(self, rx, mpls_labels)
478
479 self.assertEqual(rx_ip.src, tx_ip.src)
480 self.assertEqual(rx_ip.dst, tx_ip.dst)
481 if not ip_ttl:
482 # IP processing post pop has decremented the hop-limit
483 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
484 else:
485 self.assertEqual(rx_ip.hlim, ip_ttl)
486 except:
487 raise
488
Neale Rannsad422ed2016-11-02 14:20:04 +0000489 def test_swap(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 """MPLS label swap tests"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000491
492 #
493 # A simple MPLS xconnect - eos label in label out
494 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200495 route_32_eos = VppMplsRoute(
496 self,
497 32,
498 1,
499 [
500 VppRoutePath(
501 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
502 )
503 ],
504 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000505 route_32_eos.add_vpp_config()
506
Neale Ranns775f73c2018-12-20 03:01:49 -0800507 self.assertTrue(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 find_mpls_route(
509 self,
510 0,
511 32,
512 1,
513 [
514 VppRoutePath(
515 self.pg0.remote_ip4,
516 self.pg0.sw_if_index,
517 labels=[VppMplsLabel(33)],
518 )
519 ],
520 )
521 )
Neale Ranns775f73c2018-12-20 03:01:49 -0800522
Neale Rannsad422ed2016-11-02 14:20:04 +0000523 #
524 # a stream that matches the route for 10.0.0.1
525 # PG0 is in the default table
526 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200527 tx = self.create_stream_labelled_ip4(
528 self.pg0, [VppMplsLabel(32, ttl=32, exp=1)]
529 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800530 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 self.verify_capture_labelled(
532 self.pg0, rx, tx, [VppMplsLabel(33, ttl=31, exp=1)]
533 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000534
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200535 self.assertEqual(route_32_eos.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700536
Neale Rannsad422ed2016-11-02 14:20:04 +0000537 #
538 # A simple MPLS xconnect - non-eos label in label out
539 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200540 route_32_neos = VppMplsRoute(
541 self,
542 32,
543 0,
544 [
545 VppRoutePath(
546 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(33)]
547 )
548 ],
549 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000550 route_32_neos.add_vpp_config()
551
552 #
553 # a stream that matches the route for 10.0.0.1
554 # PG0 is in the default table
555 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200556 tx = self.create_stream_labelled_ip4(
557 self.pg0, [VppMplsLabel(32, ttl=21, exp=7), VppMplsLabel(99)]
558 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800559 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200560 self.verify_capture_labelled(
561 self.pg0, rx, tx, [VppMplsLabel(33, ttl=20, exp=7), VppMplsLabel(99)]
562 )
563 self.assertEqual(route_32_neos.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000564
Neale Ranns31ed7442018-02-23 05:29:09 -0800565 #
566 # A simple MPLS xconnect - non-eos label in label out, uniform mode
567 #
568 route_42_neos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200569 self,
570 42,
571 0,
572 [
573 VppRoutePath(
574 self.pg0.remote_ip4,
575 self.pg0.sw_if_index,
576 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)],
577 )
578 ],
579 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000581
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200582 tx = self.create_stream_labelled_ip4(
583 self.pg0, [VppMplsLabel(42, ttl=21, exp=7), VppMplsLabel(99)]
584 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800585 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 self.verify_capture_labelled(
587 self.pg0, rx, tx, [VppMplsLabel(43, ttl=20, exp=7), VppMplsLabel(99)]
588 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000589
590 #
591 # An MPLS xconnect - EOS label in IP out
592 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200593 route_33_eos = VppMplsRoute(
594 self,
595 33,
596 1,
597 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
598 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000599 route_33_eos.add_vpp_config()
600
Neale Ranns31ed7442018-02-23 05:29:09 -0800601 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
602 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000603 self.verify_capture_ip4(self.pg0, rx, tx)
604
605 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700606 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700607 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200608 tx = self.create_stream_labelled_ip4(
609 self.pg0, [VppMplsLabel(33)], dst_ip=self.pg0.remote_ip4, n=65, chksum=1
610 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700611 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
612
613 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800614 # An MPLS xconnect - EOS label in IP out, uniform mode
615 #
616 route_3333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200617 self,
618 3333,
619 1,
620 [
621 VppRoutePath(
622 self.pg0.remote_ip4,
623 self.pg0.sw_if_index,
624 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
625 )
626 ],
627 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800628 route_3333_eos.add_vpp_config()
629
630 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200631 self.pg0, [VppMplsLabel(3333, ttl=55, exp=3)]
632 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800633 rx = self.send_and_expect(self.pg0, tx, self.pg0)
634 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
635 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200636 self.pg0, [VppMplsLabel(3333, ttl=66, exp=4)]
637 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800638 rx = self.send_and_expect(self.pg0, tx, self.pg0)
639 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
640
641 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700642 # An MPLS xconnect - EOS label in IPv6 out
643 #
644 route_333_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200645 self,
646 333,
647 1,
648 [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[])],
649 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
650 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700651 route_333_eos.add_vpp_config()
652
Neale Ranns31ed7442018-02-23 05:29:09 -0800653 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
654 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700655 self.verify_capture_ip6(self.pg0, rx, tx)
656
657 #
658 # disposed packets have an TTL expired
659 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200660 tx = self.create_stream_labelled_ip6(
661 self.pg0, [VppMplsLabel(333, ttl=64)], dst_ip=self.pg1.remote_ip6, hlim=1
662 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000663 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700664 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
665
666 #
667 # An MPLS xconnect - EOS label in IPv6 out w imp-null
668 #
669 route_334_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200670 self,
671 334,
672 1,
673 [
674 VppRoutePath(
675 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(3)]
676 )
677 ],
678 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
679 )
Neale Ranns62fe07c2017-10-31 12:28:22 -0700680 route_334_eos.add_vpp_config()
681
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200682 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334, ttl=64)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800683 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700684 self.verify_capture_ip6(self.pg0, rx, tx)
685
686 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800687 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
688 #
689 route_335_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200690 self,
691 335,
692 1,
693 [
694 VppRoutePath(
695 self.pg0.remote_ip6,
696 self.pg0.sw_if_index,
697 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
698 )
699 ],
700 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
701 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800702 route_335_eos.add_vpp_config()
703
704 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 self.pg0, [VppMplsLabel(335, ttl=27, exp=4)]
706 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800707 rx = self.send_and_expect(self.pg0, tx, self.pg0)
708 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
709
710 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700711 # disposed packets have an TTL expired
712 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200713 tx = self.create_stream_labelled_ip6(
714 self.pg0, [VppMplsLabel(334)], dst_ip=self.pg1.remote_ip6, hlim=0
715 )
Neale Ranns5c6dd172022-02-17 09:08:47 +0000716 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700717 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
718
719 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000720 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
721 # so this traffic should be dropped.
722 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200723 route_33_neos = VppMplsRoute(
724 self,
725 33,
726 0,
727 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[])],
728 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000729 route_33_neos.add_vpp_config()
730
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200731 tx = self.create_stream_labelled_ip4(
732 self.pg0, [VppMplsLabel(33), VppMplsLabel(99)]
733 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800734 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200735 self.pg0, tx, "MPLS non-EOS packets popped and forwarded"
736 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000737
738 #
739 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800740 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000741 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200742 route_34_eos = VppMplsRoute(
743 self,
744 34,
745 1,
746 [
747 VppRoutePath(
748 "0.0.0.0",
749 0xFFFFFFFF,
750 nh_via_label=32,
751 labels=[VppMplsLabel(44), VppMplsLabel(45)],
752 )
753 ],
754 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700756 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000757
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200758 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800759 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200760 self.verify_capture_labelled(
761 self.pg0,
762 rx,
763 tx,
764 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(45, ttl=2)],
765 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000766
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200767 self.assertEqual(route_34_eos.get_stats_to()["packets"], 257)
768 self.assertEqual(route_32_neos.get_stats_via()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -0700769
Neale Ranns31ed7442018-02-23 05:29:09 -0800770 #
771 # A recursive EOS x-connect, which resolves through another x-connect
772 # in uniform mode
773 #
774 route_35_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 self,
776 35,
777 1,
778 [
779 VppRoutePath(
780 "0.0.0.0", 0xFFFFFFFF, nh_via_label=42, labels=[VppMplsLabel(44)]
781 )
782 ],
783 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800784 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000785
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200786 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(35, ttl=3)])
Neale Ranns31ed7442018-02-23 05:29:09 -0800787 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200788 self.verify_capture_labelled(
789 self.pg0, rx, tx, [VppMplsLabel(43, ttl=2), VppMplsLabel(44, ttl=2)]
790 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000791
792 #
Matej Klottondeb69842016-12-09 15:05:46 +0100793 # A recursive non-EOS x-connect, which resolves through another
794 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000795 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200796 route_34_neos = VppMplsRoute(
797 self,
798 34,
799 0,
800 [
801 VppRoutePath(
802 "0.0.0.0",
803 0xFFFFFFFF,
804 nh_via_label=32,
805 labels=[VppMplsLabel(44), VppMplsLabel(46)],
806 )
807 ],
808 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000809 route_34_neos.add_vpp_config()
810
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200811 tx = self.create_stream_labelled_ip4(
812 self.pg0, [VppMplsLabel(34, ttl=45), VppMplsLabel(99)]
813 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800814 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100815 # it's the 2nd (counting from 0) label in the stack that is swapped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200816 self.verify_capture_labelled(
817 self.pg0,
818 rx,
819 tx,
820 [
821 VppMplsLabel(33),
822 VppMplsLabel(44),
823 VppMplsLabel(46, ttl=44),
824 VppMplsLabel(99),
825 ],
826 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000827
828 #
Matej Klottondeb69842016-12-09 15:05:46 +0100829 # an recursive IP route that resolves through the recursive non-eos
830 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000831 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200832 ip_10_0_0_1 = VppIpRoute(
833 self,
834 "10.0.0.1",
835 32,
836 [
837 VppRoutePath(
838 "0.0.0.0", 0xFFFFFFFF, nh_via_label=34, labels=[VppMplsLabel(55)]
839 )
840 ],
841 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000842 ip_10_0_0_1.add_vpp_config()
843
Neale Rannsad422ed2016-11-02 14:20:04 +0000844 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800845 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200846 self.verify_capture_labelled_ip4(
847 self.pg0,
848 rx,
849 tx,
850 [VppMplsLabel(33), VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(55)],
851 )
852 self.assertEqual(ip_10_0_0_1.get_stats_to()["packets"], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000853
854 ip_10_0_0_1.remove_vpp_config()
855 route_34_neos.remove_vpp_config()
856 route_34_eos.remove_vpp_config()
857 route_33_neos.remove_vpp_config()
858 route_33_eos.remove_vpp_config()
859 route_32_neos.remove_vpp_config()
860 route_32_eos.remove_vpp_config()
861
862 def test_bind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 """MPLS Local Label Binding test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000864
865 #
866 # Add a non-recursive route with a single out label
867 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200868 route_10_0_0_1 = VppIpRoute(
869 self,
870 "10.0.0.1",
871 32,
872 [
873 VppRoutePath(
874 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
875 )
876 ],
877 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000878 route_10_0_0_1.add_vpp_config()
879
880 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800881 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000882 binding.add_vpp_config()
883
884 # non-EOS stream
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200885 tx = self.create_stream_labelled_ip4(
886 self.pg0, [VppMplsLabel(44), VppMplsLabel(99)]
887 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800888 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200889 self.verify_capture_labelled(
890 self.pg0, rx, tx, [VppMplsLabel(45, ttl=63), VppMplsLabel(99)]
891 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000892
893 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800894 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
895 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200896 self.verify_capture_labelled(self.pg0, rx, tx, [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000897
898 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000899 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800900 rx = self.send_and_expect(self.pg0, tx, self.pg0)
901 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000902
903 #
904 # cleanup
905 #
906 binding.remove_vpp_config()
907 route_10_0_0_1.remove_vpp_config()
908
909 def test_imposition(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200910 """MPLS label imposition test"""
Neale Rannsad422ed2016-11-02 14:20:04 +0000911
912 #
913 # Add a non-recursive route with a single out label
914 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200915 route_10_0_0_1 = VppIpRoute(
916 self,
917 "10.0.0.1",
918 32,
919 [
920 VppRoutePath(
921 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
922 )
923 ],
924 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000925 route_10_0_0_1.add_vpp_config()
926
927 #
928 # a stream that matches the route for 10.0.0.1
929 # PG0 is in the default table
930 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000931 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800932 rx = self.send_and_expect(self.pg0, tx, self.pg0)
933 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000934
935 #
936 # Add a non-recursive route with a 3 out labels
937 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200938 route_10_0_0_2 = VppIpRoute(
939 self,
940 "10.0.0.2",
941 32,
942 [
943 VppRoutePath(
944 self.pg0.remote_ip4,
945 self.pg0.sw_if_index,
946 labels=[VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
947 )
948 ],
949 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000950 route_10_0_0_2.add_vpp_config()
951
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200952 tx = self.create_stream_ip4(self.pg0, "10.0.0.2", ip_ttl=44, ip_dscp=0xFF)
Neale Ranns31ed7442018-02-23 05:29:09 -0800953 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200954 self.verify_capture_labelled_ip4(
955 self.pg0,
956 rx,
957 tx,
958 [VppMplsLabel(32), VppMplsLabel(33), VppMplsLabel(34)],
959 ip_ttl=43,
960 )
Neale Rannsad422ed2016-11-02 14:20:04 +0000961
Neale Ranns31ed7442018-02-23 05:29:09 -0800962 #
963 # Add a non-recursive route with a single out label in uniform mode
964 #
965 route_10_0_0_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200966 self,
967 "10.0.0.3",
968 32,
969 [
970 VppRoutePath(
971 self.pg0.remote_ip4,
972 self.pg0.sw_if_index,
973 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
974 )
975 ],
976 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800977 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000978
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200979 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -0800980 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200981 self.verify_capture_labelled_ip4(
982 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
983 )
Neale Ranns31ed7442018-02-23 05:29:09 -0800984
985 #
986 # Add a IPv6 non-recursive route with a single out label in
987 # uniform mode
988 #
989 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200990 self,
991 "2001::3",
992 128,
993 [
994 VppRoutePath(
995 self.pg0.remote_ip6,
996 self.pg0.sw_if_index,
997 labels=[VppMplsLabel(32, mode=MplsLspMode.UNIFORM)],
998 )
999 ],
1000 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001001 route_2001_3.add_vpp_config()
1002
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001003 tx = self.create_stream_ip6(self.pg0, "2001::3", ip_ttl=54, ip_dscp=0xBE)
Neale Ranns31ed7442018-02-23 05:29:09 -08001004 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001005 self.verify_capture_labelled_ip6(
1006 self.pg0, rx, tx, [VppMplsLabel(32, ttl=53, exp=5)]
1007 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001008
1009 #
Matej Klottondeb69842016-12-09 15:05:46 +01001010 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +00001011 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 route_11_0_0_1 = VppIpRoute(
1013 self,
1014 "11.0.0.1",
1015 32,
1016 [VppRoutePath("10.0.0.1", 0xFFFFFFFF, labels=[VppMplsLabel(44)])],
1017 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001018 route_11_0_0_1.add_vpp_config()
1019
1020 #
1021 # a stream that matches the route for 11.0.0.1, should pick up
1022 # the label stack for 11.0.0.1 and 10.0.0.1
1023 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001024 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001025 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001026 self.verify_capture_labelled_ip4(
1027 self.pg0, rx, tx, [VppMplsLabel(32), VppMplsLabel(44)]
1028 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001030 self.assertEqual(route_11_0_0_1.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001031
Neale Rannsad422ed2016-11-02 14:20:04 +00001032 #
1033 # add a recursive path, with 2 labels, via the 3 label route
1034 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001035 route_11_0_0_2 = VppIpRoute(
1036 self,
1037 "11.0.0.2",
1038 32,
1039 [
1040 VppRoutePath(
1041 "10.0.0.2", 0xFFFFFFFF, labels=[VppMplsLabel(44), VppMplsLabel(45)]
1042 )
1043 ],
1044 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001045 route_11_0_0_2.add_vpp_config()
1046
1047 #
1048 # a stream that matches the route for 11.0.0.1, should pick up
1049 # the label stack for 11.0.0.1 and 10.0.0.1
1050 #
Neale Rannsad422ed2016-11-02 14:20:04 +00001051 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -08001052 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001053 self.verify_capture_labelled_ip4(
1054 self.pg0,
1055 rx,
1056 tx,
1057 [
1058 VppMplsLabel(32),
1059 VppMplsLabel(33),
1060 VppMplsLabel(34),
1061 VppMplsLabel(44),
1062 VppMplsLabel(45),
1063 ],
1064 )
Neale Rannsad422ed2016-11-02 14:20:04 +00001065
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001066 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 257)
Neale Ranns008dbe12018-09-07 09:32:36 -07001067
1068 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 self.verify_capture_labelled_ip4(
1070 self.pg0,
1071 rx,
1072 tx,
1073 [
1074 VppMplsLabel(32),
1075 VppMplsLabel(33),
1076 VppMplsLabel(34),
1077 VppMplsLabel(44),
1078 VppMplsLabel(45),
1079 ],
1080 )
Neale Ranns008dbe12018-09-07 09:32:36 -07001081
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 self.assertEqual(route_11_0_0_2.get_stats_to()["packets"], 514)
Neale Ranns008dbe12018-09-07 09:32:36 -07001083
Neale Rannsad422ed2016-11-02 14:20:04 +00001084 #
1085 # cleanup
1086 #
1087 route_11_0_0_2.remove_vpp_config()
1088 route_11_0_0_1.remove_vpp_config()
1089 route_10_0_0_2.remove_vpp_config()
1090 route_10_0_0_1.remove_vpp_config()
1091
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301092 def test_imposition_fragmentation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001093 """MPLS label imposition fragmentation test"""
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301094
1095 #
1096 # Add a ipv4 non-recursive route with a single out label
1097 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001098 route_10_0_0_1 = VppIpRoute(
1099 self,
1100 "10.0.0.1",
1101 32,
1102 [
1103 VppRoutePath(
1104 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1105 )
1106 ],
1107 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301108 route_10_0_0_1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 route_1000_1 = VppIpRoute(
1110 self,
1111 "1000::1",
1112 128,
1113 [
1114 VppRoutePath(
1115 self.pg0.remote_ip6, self.pg0.sw_if_index, labels=[VppMplsLabel(32)]
1116 )
1117 ],
1118 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001119 route_1000_1.add_vpp_config()
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301120
1121 #
1122 # a stream that matches the route for 10.0.0.1
1123 # PG0 is in the default table
1124 #
1125 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
1126 for i in range(0, 257):
1127 self.extend_packet(tx[i], 10000)
1128
1129 #
1130 # 5 fragments per packet (257*5=1285)
1131 #
1132 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001133 self.verify_capture_fragmented_labelled_ip4(
1134 self.pg0, rx, tx, [VppMplsLabel(32)]
1135 )
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301136
Neale Rannsec5371e2022-03-04 11:45:41 +00001137 # packets with DF bit set generate ICMP
1138 for t in tx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001139 t[IP].flags = "DF"
Neale Rannsec5371e2022-03-04 11:45:41 +00001140 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1141
1142 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001143 self.assertEqual(icmptypes[rx[ICMP].type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001144 self.assertEqual(
1145 icmpcodes[rx[ICMP].type][rx[ICMP].code], "fragmentation-needed"
1146 )
Neale Rannsfbc633f2022-03-18 13:05:09 +00001147 # the link MTU is 9000, the MPLS over head is 4 bytes
1148 self.assertEqual(rx[ICMP].nexthopmtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001149
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001150 self.assertEqual(
Neale Rannse22a7042022-08-09 03:03:29 +00001151 self.statistics.get_err_counter("/err/mpls-frag/dont_fragment_set"),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001152 len(tx),
1153 )
Neale Rannsec5371e2022-03-04 11:45:41 +00001154 #
1155 # a stream that matches the route for 1000::1/128
1156 # PG0 is in the default table
1157 #
1158 tx = self.create_stream_ip6(self.pg0, "1000::1")
1159 for i in range(0, 257):
1160 self.extend_packet(tx[i], 10000)
1161
1162 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
1163 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +00001164 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +00001165
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +05301166 #
1167 # cleanup
1168 #
1169 route_10_0_0_1.remove_vpp_config()
1170
Neale Ranns31ed7442018-02-23 05:29:09 -08001171 def test_tunnel_pipe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001172 """MPLS Tunnel Tests - Pipe"""
Neale Rannsad422ed2016-11-02 14:20:04 +00001173
1174 #
Ole Troaneb284a12019-10-09 13:33:19 +02001175 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +00001176 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001177 mpls_tun = VppMPLSTunnelInterface(
1178 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001179 [
1180 VppRoutePath(
1181 self.pg0.remote_ip4,
1182 self.pg0.sw_if_index,
1183 labels=[VppMplsLabel(44), VppMplsLabel(46)],
1184 )
1185 ],
1186 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001187 mpls_tun.add_vpp_config()
1188 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +00001189
1190 #
1191 # add an unlabelled route through the new tunnel
1192 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001193 route_10_0_0_3 = VppIpRoute(
1194 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1195 )
Neale Ranns5a8123b2017-01-26 01:18:23 -08001196 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +00001197
1198 self.vapi.cli("clear trace")
1199 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1200 self.pg0.add_stream(tx)
1201
1202 self.pg_enable_capture(self.pg_interfaces)
1203 self.pg_start()
1204
1205 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001206 self.verify_capture_tunneled_ip4(
1207 self.pg0, rx, tx, [VppMplsLabel(44), VppMplsLabel(46)]
1208 )
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001209
Neale Ranns8c4611b2017-05-23 03:43:47 -07001210 #
1211 # add a labelled route through the new tunnel
1212 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001213 route_10_0_0_4 = VppIpRoute(
1214 self,
1215 "10.0.0.4",
1216 32,
1217 [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index, labels=[33])],
1218 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001219 route_10_0_0_4.add_vpp_config()
1220
1221 self.vapi.cli("clear trace")
1222 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1223 self.pg0.add_stream(tx)
1224
1225 self.pg_enable_capture(self.pg_interfaces)
1226 self.pg_start()
1227
1228 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001229 self.verify_capture_tunneled_ip4(
1230 self.pg0,
1231 rx,
1232 tx,
1233 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1234 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001235
Ole Troaneb284a12019-10-09 13:33:19 +02001236 #
1237 # change tunnel's MTU to a low value
1238 #
1239 mpls_tun.set_l3_mtu(1200)
1240
1241 # send IP into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001242 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", payload_size=1500)
1243 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001244
1245 fake_tx = []
1246 for p in tx:
1247 fake_tx.append(p)
1248 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001249 self.verify_capture_tunneled_ip4(
1250 self.pg0, rx, fake_tx, [VppMplsLabel(44), VppMplsLabel(46)]
1251 )
Ole Troaneb284a12019-10-09 13:33:19 +02001252
1253 # send MPLS into the tunnel to be fragmented
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001254 tx = self.create_stream_ip4(self.pg0, "10.0.0.4", payload_size=1500)
1255 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx) * 2)
Ole Troaneb284a12019-10-09 13:33:19 +02001256
1257 fake_tx = []
1258 for p in tx:
1259 fake_tx.append(p)
1260 fake_tx.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001261 self.verify_capture_tunneled_ip4(
1262 self.pg0,
1263 rx,
1264 fake_tx,
1265 [VppMplsLabel(44), VppMplsLabel(46), VppMplsLabel(33, ttl=255)],
1266 )
Ole Troaneb284a12019-10-09 13:33:19 +02001267
Neale Ranns31ed7442018-02-23 05:29:09 -08001268 def test_tunnel_uniform(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001269 """MPLS Tunnel Tests - Uniform"""
Neale Ranns31ed7442018-02-23 05:29:09 -08001270
1271 #
1272 # Create a tunnel with a single out label
1273 # The label stack is specified here from outer to inner
1274 #
1275 mpls_tun = VppMPLSTunnelInterface(
1276 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001277 [
1278 VppRoutePath(
1279 self.pg0.remote_ip4,
1280 self.pg0.sw_if_index,
1281 labels=[
1282 VppMplsLabel(44, ttl=32),
1283 VppMplsLabel(46, MplsLspMode.UNIFORM),
1284 ],
1285 )
1286 ],
1287 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001288 mpls_tun.add_vpp_config()
1289 mpls_tun.admin_up()
1290
1291 #
1292 # add an unlabelled route through the new tunnel
1293 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001294 route_10_0_0_3 = VppIpRoute(
1295 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1296 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001297 route_10_0_0_3.add_vpp_config()
1298
1299 self.vapi.cli("clear trace")
1300 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1301 self.pg0.add_stream(tx)
1302
1303 self.pg_enable_capture(self.pg_interfaces)
1304 self.pg_start()
1305
1306 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001307 self.verify_capture_tunneled_ip4(
1308 self.pg0, rx, tx, [VppMplsLabel(44, ttl=32), VppMplsLabel(46, ttl=23)]
1309 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001310
1311 #
1312 # add a labelled route through the new tunnel
1313 #
1314 route_10_0_0_4 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001315 self,
1316 "10.0.0.4",
1317 32,
1318 [
1319 VppRoutePath(
1320 "0.0.0.0", mpls_tun._sw_if_index, labels=[VppMplsLabel(33, ttl=47)]
1321 )
1322 ],
1323 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001324 route_10_0_0_4.add_vpp_config()
1325
1326 self.vapi.cli("clear trace")
1327 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1328 self.pg0.add_stream(tx)
1329
1330 self.pg_enable_capture(self.pg_interfaces)
1331 self.pg_start()
1332
1333 rx = self.pg0.get_capture()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001334 self.verify_capture_tunneled_ip4(
1335 self.pg0,
1336 rx,
1337 tx,
1338 [
1339 VppMplsLabel(44, ttl=32),
1340 VppMplsLabel(46, ttl=47),
1341 VppMplsLabel(33, ttl=47),
1342 ],
1343 )
Neale Ranns8c4611b2017-05-23 03:43:47 -07001344
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001345 def test_mpls_tunnel_many(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001346 """MPLS Multiple Tunnels"""
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001347
Neale Ranns397228d2021-10-21 12:02:53 +00001348 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001349 mpls_tun = VppMPLSTunnelInterface(
1350 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001351 [
1352 VppRoutePath(
1353 self.pg0.remote_ip4,
1354 self.pg0.sw_if_index,
1355 labels=[
1356 VppMplsLabel(44, ttl=32),
1357 VppMplsLabel(46, MplsLspMode.UNIFORM),
1358 ],
1359 )
1360 ],
1361 )
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001362 mpls_tun.add_vpp_config()
1363 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001364 for ii in range(100):
1365 mpls_tun = VppMPLSTunnelInterface(
1366 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001367 [
1368 VppRoutePath(
1369 self.pg0.remote_ip4,
1370 self.pg0.sw_if_index,
1371 labels=[
1372 VppMplsLabel(44, ttl=32),
1373 VppMplsLabel(46, MplsLspMode.UNIFORM),
1374 ],
1375 )
1376 ],
1377 is_l2=1,
1378 )
Neale Ranns397228d2021-10-21 12:02:53 +00001379 mpls_tun.add_vpp_config()
1380 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001381
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001382 def test_v4_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001383 """MPLS V4 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001384
1385 #
1386 # The first test case has an MPLS TTL of 0
1387 # all packet should be dropped
1388 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001389 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0, ttl=0)])
1390 self.send_and_assert_no_replies(self.pg0, tx, "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001391
1392 #
1393 # a stream with a non-zero MPLS TTL
1394 # PG0 is in the default table
1395 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001396 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1397 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001398 self.verify_capture_ip4(self.pg0, rx, tx)
1399
1400 #
1401 # a stream with a non-zero MPLS TTL
1402 # PG1 is in table 1
1403 # we are ensuring the post-pop lookup occurs in the VRF table
1404 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001405 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1406 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1407 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001408
1409 def test_v6_exp_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001410 """MPLS V6 Explicit NULL test"""
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001411
1412 #
1413 # a stream with a non-zero MPLS TTL
1414 # PG0 is in the default table
1415 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001416 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1417 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001418 self.verify_capture_ip6(self.pg0, rx, tx)
1419
1420 #
1421 # a stream with a non-zero MPLS TTL
1422 # PG1 is in table 1
1423 # we are ensuring the post-pop lookup occurs in the VRF table
1424 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001425 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1426 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001427 self.verify_capture_ip6(self.pg0, rx, tx)
1428
Neale Rannscb630ff2016-12-14 13:31:29 +01001429 def test_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001430 """MPLS Deagg"""
Neale Rannscb630ff2016-12-14 13:31:29 +01001431
1432 #
1433 # A de-agg route - next-hop lookup in default table
1434 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001435 route_34_eos = VppMplsRoute(
1436 self, 34, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
1437 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001438 route_34_eos.add_vpp_config()
1439
1440 #
1441 # ping an interface in the default table
1442 # PG0 is in the default table
1443 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001444 tx = self.create_stream_labelled_ip4(
1445 self.pg0, [VppMplsLabel(34)], ping=1, ip_itf=self.pg0
1446 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001447 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001448 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1449
1450 #
1451 # A de-agg route - next-hop lookup in non-default table
1452 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001453 route_35_eos = VppMplsRoute(
1454 self, 35, 1, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
1455 )
Neale Rannscb630ff2016-12-14 13:31:29 +01001456 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001457 route_356_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001458 self,
1459 356,
1460 1,
1461 [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=1)],
1462 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1463 )
Neale Rannsf478f752022-02-17 15:41:32 +00001464 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001465
1466 #
1467 # ping an interface in the non-default table
1468 # PG0 is in the default table. packet arrive labelled in the
1469 # default table and egress unlabelled in the non-default
1470 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001471 tx = self.create_stream_labelled_ip4(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001472 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1473 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001474 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001475 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001476 tx = self.create_stream_labelled_ip6(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001477 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1
1478 )
Neale Rannsf478f752022-02-17 15:41:32 +00001479 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1480 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001481
Neale Ranns6af1c042017-05-26 03:48:53 -07001482 #
1483 # Double pop
1484 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001485 route_36_neos = VppMplsRoute(self, 36, 0, [VppRoutePath("0.0.0.0", 0xFFFFFFFF)])
Neale Ranns6af1c042017-05-26 03:48:53 -07001486 route_36_neos.add_vpp_config()
1487
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001488 tx = self.create_stream_labelled_ip4(
1489 self.pg0, [VppMplsLabel(36), VppMplsLabel(35)], ping=1, ip_itf=self.pg1
1490 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001491 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001492 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1493
1494 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001495 route_35_eos.remove_vpp_config()
1496 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001497
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001498 def test_interface_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001499 """MPLS Interface Receive"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001500
1501 #
1502 # Add a non-recursive route that will forward the traffic
1503 # post-interface-rx
1504 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001505 route_10_0_0_1 = VppIpRoute(
1506 self,
1507 "10.0.0.1",
1508 32,
1509 table_id=1,
1510 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1511 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001512 route_10_0_0_1.add_vpp_config()
1513
1514 #
1515 # An interface receive label that maps traffic to RX on interface
1516 # pg1
1517 # by injecting the packet in on pg0, which is in table 0
1518 # doing an interface-rx on pg1 and matching a route in table 1
1519 # if the packet egresses, then we must have swapped to pg1
1520 # so as to have matched the route in table 1
1521 #
Neale Ranns097fa662018-05-01 05:17:55 -07001522 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001523 self,
1524 34,
1525 1,
1526 [
1527 VppRoutePath(
1528 "0.0.0.0",
1529 self.pg1.sw_if_index,
1530 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1531 )
1532 ],
1533 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001534 route_34_eos.add_vpp_config()
1535
1536 #
1537 # ping an interface in the default table
1538 # PG0 is in the default table
1539 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001540 tx = self.create_stream_labelled_ip4(
1541 self.pg0, [VppMplsLabel(34)], dst_ip="10.0.0.1"
1542 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001543 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001544 self.verify_capture_ip4(self.pg1, rx, tx)
1545
1546 def test_mcast_mid_point(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001547 """MPLS Multicast Mid Point"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001548
1549 #
1550 # Add a non-recursive route that will forward the traffic
1551 # post-interface-rx
1552 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001553 route_10_0_0_1 = VppIpRoute(
1554 self,
1555 "10.0.0.1",
1556 32,
1557 table_id=1,
1558 paths=[VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1559 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001560 route_10_0_0_1.add_vpp_config()
1561
1562 #
1563 # Add a mcast entry that replicate to pg2 and pg3
1564 # and replicate to a interface-rx (like a bud node would)
1565 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001566 route_3400_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001567 self,
1568 3400,
1569 1,
1570 [
1571 VppRoutePath(
1572 self.pg2.remote_ip4,
1573 self.pg2.sw_if_index,
1574 labels=[VppMplsLabel(3401)],
1575 ),
1576 VppRoutePath(
1577 self.pg3.remote_ip4,
1578 self.pg3.sw_if_index,
1579 labels=[VppMplsLabel(3402)],
1580 ),
1581 VppRoutePath(
1582 "0.0.0.0",
1583 self.pg1.sw_if_index,
1584 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
1585 ),
1586 ],
1587 is_multicast=1,
1588 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001589 route_3400_eos.add_vpp_config()
1590
1591 #
1592 # ping an interface in the default table
1593 # PG0 is in the default table
1594 #
1595 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001596 tx = self.create_stream_labelled_ip4(
1597 self.pg0, [VppMplsLabel(3400, ttl=64)], n=257, dst_ip="10.0.0.1"
1598 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001599 self.pg0.add_stream(tx)
1600
1601 self.pg_enable_capture(self.pg_interfaces)
1602 self.pg_start()
1603
1604 rx = self.pg1.get_capture(257)
1605 self.verify_capture_ip4(self.pg1, rx, tx)
1606
1607 rx = self.pg2.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001608 self.verify_capture_labelled(self.pg2, rx, tx, [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001609 rx = self.pg3.get_capture(257)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001610 self.verify_capture_labelled(self.pg3, rx, tx, [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001611
1612 def test_mcast_head(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001613 """MPLS Multicast Head-end"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001614
Neale Ranns990f6942020-10-20 07:20:17 +00001615 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1616 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1617
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001618 #
1619 # Create a multicast tunnel with two replications
1620 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001621 mpls_tun = VppMPLSTunnelInterface(
1622 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001623 [
1624 VppRoutePath(
1625 self.pg2.remote_ip4, self.pg2.sw_if_index, labels=[VppMplsLabel(42)]
1626 ),
1627 VppRoutePath(
1628 self.pg3.remote_ip4, self.pg3.sw_if_index, labels=[VppMplsLabel(43)]
1629 ),
1630 ],
1631 is_multicast=1,
1632 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001633 mpls_tun.add_vpp_config()
1634 mpls_tun.admin_up()
1635
1636 #
1637 # add an unlabelled route through the new tunnel
1638 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001639 route_10_0_0_3 = VppIpRoute(
1640 self, "10.0.0.3", 32, [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)]
1641 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001642 route_10_0_0_3.add_vpp_config()
1643
1644 self.vapi.cli("clear trace")
1645 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1646 self.pg0.add_stream(tx)
1647
1648 self.pg_enable_capture(self.pg_interfaces)
1649 self.pg_start()
1650
1651 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001652 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001653 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001654 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001655
1656 #
1657 # An an IP multicast route via the tunnel
1658 # A (*,G).
1659 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1660 #
1661 route_232_1_1_1 = VppIpMRoute(
1662 self,
1663 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001664 "232.1.1.1",
1665 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001666 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001667 [
1668 VppMRoutePath(
1669 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1670 ),
1671 VppMRoutePath(
1672 mpls_tun._sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1673 ),
1674 ],
1675 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001676 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001677 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001678
1679 self.vapi.cli("clear trace")
1680 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1681 self.pg0.add_stream(tx)
1682
1683 self.pg_enable_capture(self.pg_interfaces)
1684 self.pg_start()
1685
1686 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001687 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001688 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001689 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001690
Neale Ranns31426c62017-05-24 10:32:58 -07001691 def test_mcast_ip4_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001692 """MPLS IPv4 Multicast Tail"""
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001693
Neale Ranns990f6942020-10-20 07:20:17 +00001694 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1695 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1696
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001697 #
1698 # Add a multicast route that will forward the traffic
1699 # post-disposition
1700 #
1701 route_232_1_1_1 = VppIpMRoute(
1702 self,
1703 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001704 "232.1.1.1",
1705 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001706 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001707 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001708 paths=[
1709 VppMRoutePath(
1710 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1711 )
1712 ],
1713 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001714 route_232_1_1_1.add_vpp_config()
1715
1716 #
1717 # An interface receive label that maps traffic to RX on interface
1718 # pg1
1719 # by injecting the packet in on pg0, which is in table 0
1720 # doing an rpf-id and matching a route in table 1
1721 # if the packet egresses, then we must have matched the route in
1722 # table 1
1723 #
Neale Ranns097fa662018-05-01 05:17:55 -07001724 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001725 self,
1726 34,
1727 1,
1728 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001729 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001730 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
1731 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001732
1733 route_34_eos.add_vpp_config()
1734
1735 #
1736 # Drop due to interface lookup miss
1737 #
1738 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001739 tx = self.create_stream_labelled_ip4(
1740 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=1
1741 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001742 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1743
1744 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001745 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001746 #
1747 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001748 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001749
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001750 tx = self.create_stream_labelled_ip4(
1751 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1752 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001753 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001754 self.verify_capture_ip4(self.pg1, rx, tx)
1755
1756 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001757 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001758 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001759 tx = self.create_stream_labelled_ip4(
1760 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1", n=65, chksum=1
1761 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001762 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1763
1764 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001765 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001766 #
1767 route_232_1_1_1.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001768 tx = self.create_stream_labelled_ip4(
1769 self.pg0, [VppMplsLabel(34)], dst_ip="232.1.1.1"
1770 )
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001771 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1772
Neale Ranns31426c62017-05-24 10:32:58 -07001773 def test_mcast_ip6_tail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001774 """MPLS IPv6 Multicast Tail"""
Neale Ranns31426c62017-05-24 10:32:58 -07001775
Neale Ranns990f6942020-10-20 07:20:17 +00001776 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1777 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1778
Neale Ranns31426c62017-05-24 10:32:58 -07001779 #
1780 # Add a multicast route that will forward the traffic
1781 # post-disposition
1782 #
1783 route_ff = VppIpMRoute(
1784 self,
1785 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001786 "ff01::1",
1787 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001788 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001789 table_id=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001790 paths=[
1791 VppMRoutePath(
1792 self.pg1.sw_if_index,
1793 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1794 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1795 )
1796 ],
1797 )
Neale Ranns31426c62017-05-24 10:32:58 -07001798 route_ff.add_vpp_config()
1799
1800 #
1801 # An interface receive label that maps traffic to RX on interface
1802 # pg1
1803 # by injecting the packet in on pg0, which is in table 0
1804 # doing an rpf-id and matching a route in table 1
1805 # if the packet egresses, then we must have matched the route in
1806 # table 1
1807 #
1808 route_34_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001809 self,
1810 34,
1811 1,
1812 [VppRoutePath("::", 0xFFFFFFFF, nh_table_id=1, rpf_id=55)],
Neale Ranns097fa662018-05-01 05:17:55 -07001813 is_multicast=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001814 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1815 )
Neale Ranns31426c62017-05-24 10:32:58 -07001816
1817 route_34_eos.add_vpp_config()
1818
1819 #
1820 # Drop due to interface lookup miss
1821 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 tx = self.create_stream_labelled_ip6(
1823 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1824 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001825 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001826
1827 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001828 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001829 #
1830 route_ff.update_rpf_id(55)
1831
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001832 tx = self.create_stream_labelled_ip6(
1833 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1834 )
Neale Ranns31ed7442018-02-23 05:29:09 -08001835 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001836 self.verify_capture_ip6(self.pg1, rx, tx)
1837
1838 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001839 # disposed packets have hop-limit = 1
1840 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001841 tx = self.create_stream_labelled_ip6(
1842 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1", hlim=1
1843 )
Neale Ranns5c6dd172022-02-17 09:08:47 +00001844 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001845 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001846
1847 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001848 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001849 #
1850 route_ff.update_rpf_id(56)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001851 tx = self.create_stream_labelled_ip6(
1852 self.pg0, [VppMplsLabel(34)], dst_ip="ff01::1"
1853 )
Neale Ranns31426c62017-05-24 10:32:58 -07001854 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1855
Neale Rannsd5d7b962019-08-04 03:30:56 -07001856 def test_6pe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001857 """MPLS 6PE"""
Neale Rannsd5d7b962019-08-04 03:30:56 -07001858
1859 #
1860 # Add a non-recursive route with a single out label
1861 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001862 route_10_0_0_1 = VppIpRoute(
1863 self,
1864 "10.0.0.1",
1865 32,
1866 [
1867 VppRoutePath(
1868 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(45)]
1869 )
1870 ],
1871 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001872 route_10_0_0_1.add_vpp_config()
1873
1874 # bind a local label to the route
1875 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1876 binding.add_vpp_config()
1877
1878 #
1879 # a labelled v6 route that resolves through the v4
1880 #
1881 route_2001_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001882 self,
1883 "2001::3",
1884 128,
1885 [VppRoutePath("10.0.0.1", INVALID_INDEX, labels=[VppMplsLabel(32)])],
1886 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001887 route_2001_3.add_vpp_config()
1888
1889 tx = self.create_stream_ip6(self.pg0, "2001::3")
1890 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1891
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001892 self.verify_capture_labelled_ip6(
1893 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32)]
1894 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001895
1896 #
1897 # and a v4 recursive via the v6
1898 #
1899 route_20_3 = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001900 self,
1901 "20.0.0.3",
1902 32,
1903 [VppRoutePath("2001::3", INVALID_INDEX, labels=[VppMplsLabel(99)])],
1904 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001905 route_20_3.add_vpp_config()
1906
1907 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1908 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1909
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001910 self.verify_capture_labelled_ip4(
1911 self.pg0, rx, tx, [VppMplsLabel(45), VppMplsLabel(32), VppMplsLabel(99)]
1912 )
Neale Rannsd5d7b962019-08-04 03:30:56 -07001913
Neale Ranns53962fb2021-12-20 18:18:42 +00001914 def test_attached(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001915 """Attach Routes with Local Label"""
Neale Ranns53962fb2021-12-20 18:18:42 +00001916
1917 #
1918 # test that if a local label is associated with an attached/connected
1919 # prefix, that we can reach hosts in the prefix.
1920 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001921 binding = VppMplsIpBind(
1922 self, 44, self.pg0._local_ip4_subnet, self.pg0.local_ip4_prefix_len
1923 )
Neale Ranns53962fb2021-12-20 18:18:42 +00001924 binding.add_vpp_config()
1925
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001926 tx = (
1927 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1928 / MPLS(label=44, ttl=64)
1929 / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
1930 / UDP(sport=1234, dport=1234)
1931 / Raw(b"\xa5" * 100)
1932 )
Neale Ranns53962fb2021-12-20 18:18:42 +00001933 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
1934 for rx in rxs:
1935 # if there's an ARP then the label is linked to the glean
1936 # which is wrong.
1937 self.assertFalse(rx.haslayer(ARP))
1938 # it should be unicasted to the host
1939 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1940 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
1941
Neale Ranns180279b2017-03-16 15:49:09 -04001942
1943class TestMPLSDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001944 """MPLS disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04001945
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001946 @classmethod
1947 def setUpClass(cls):
1948 super(TestMPLSDisabled, cls).setUpClass()
1949
1950 @classmethod
1951 def tearDownClass(cls):
1952 super(TestMPLSDisabled, cls).tearDownClass()
1953
Neale Ranns180279b2017-03-16 15:49:09 -04001954 def setUp(self):
1955 super(TestMPLSDisabled, self).setUp()
1956
1957 # create 2 pg interfaces
1958 self.create_pg_interfaces(range(2))
1959
Neale Ranns15002542017-09-10 04:39:11 -07001960 self.tbl = VppMplsTable(self, 0)
1961 self.tbl.add_vpp_config()
1962
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001963 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001964 self.pg0.admin_up()
1965 self.pg0.config_ip4()
1966 self.pg0.resolve_arp()
1967 self.pg0.enable_mpls()
1968
1969 # PG 1 is not MPLS enabled
1970 self.pg1.admin_up()
1971
1972 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001973 for i in self.pg_interfaces:
1974 i.unconfig_ip4()
1975 i.admin_down()
1976
Neale Ranns15002542017-09-10 04:39:11 -07001977 self.pg0.disable_mpls()
1978 super(TestMPLSDisabled, self).tearDown()
1979
Neale Ranns180279b2017-03-16 15:49:09 -04001980 def test_mpls_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001981 """MPLS Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04001982
Neale Rannsde0b3b52021-06-15 12:43:12 +00001983 self.logger.info(self.vapi.cli("show mpls interface"))
1984 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1985 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1986
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001987 tx = (
1988 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1989 / MPLS(label=32, ttl=64)
1990 / IPv6(src="2001::1", dst=self.pg0.remote_ip6)
1991 / UDP(sport=1234, dport=1234)
1992 / Raw(b"\xa5" * 100)
1993 )
Neale Ranns180279b2017-03-16 15:49:09 -04001994
1995 #
1996 # A simple MPLS xconnect - eos label in label out
1997 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001998 route_32_eos = VppMplsRoute(
1999 self,
2000 32,
2001 1,
2002 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[33])],
2003 )
Neale Ranns180279b2017-03-16 15:49:09 -04002004 route_32_eos.add_vpp_config()
2005
2006 #
2007 # PG1 does not forward IP traffic
2008 #
2009 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
2010
2011 #
2012 # MPLS enable PG1
2013 #
2014 self.pg1.enable_mpls()
2015
Neale Rannsde0b3b52021-06-15 12:43:12 +00002016 self.logger.info(self.vapi.cli("show mpls interface"))
2017 self.logger.info(self.vapi.cli("show mpls interface pg1"))
2018
Neale Ranns180279b2017-03-16 15:49:09 -04002019 #
2020 # Now we get packets through
2021 #
2022 self.pg1.add_stream(tx)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
2025
2026 rx = self.pg0.get_capture(1)
2027
2028 #
2029 # Disable PG1
2030 #
2031 self.pg1.disable_mpls()
2032
2033 #
2034 # PG1 does not forward IP traffic
2035 #
2036 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2037 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
2038
2039
Neale Rannsf12a83f2017-04-18 09:09:40 -07002040class TestMPLSPIC(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002041 """MPLS Prefix-Independent Convergence (PIC) edge convergence"""
Neale Rannsf12a83f2017-04-18 09:09:40 -07002042
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002043 @classmethod
2044 def setUpClass(cls):
2045 super(TestMPLSPIC, cls).setUpClass()
2046
2047 @classmethod
2048 def tearDownClass(cls):
2049 super(TestMPLSPIC, cls).tearDownClass()
2050
Neale Rannsf12a83f2017-04-18 09:09:40 -07002051 def setUp(self):
2052 super(TestMPLSPIC, self).setUp()
2053
2054 # create 2 pg interfaces
2055 self.create_pg_interfaces(range(4))
2056
Neale Ranns15002542017-09-10 04:39:11 -07002057 mpls_tbl = VppMplsTable(self, 0)
2058 mpls_tbl.add_vpp_config()
2059 tbl4 = VppIpTable(self, 1)
2060 tbl4.add_vpp_config()
2061 tbl6 = VppIpTable(self, 1, is_ip6=1)
2062 tbl6.add_vpp_config()
2063
Neale Rannsf12a83f2017-04-18 09:09:40 -07002064 # core links
2065 self.pg0.admin_up()
2066 self.pg0.config_ip4()
2067 self.pg0.resolve_arp()
2068 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002069
Neale Rannsf12a83f2017-04-18 09:09:40 -07002070 self.pg1.admin_up()
2071 self.pg1.config_ip4()
2072 self.pg1.resolve_arp()
2073 self.pg1.enable_mpls()
2074
2075 # VRF (customer facing) link
2076 self.pg2.admin_up()
2077 self.pg2.set_table_ip4(1)
2078 self.pg2.config_ip4()
2079 self.pg2.resolve_arp()
2080 self.pg2.set_table_ip6(1)
2081 self.pg2.config_ip6()
2082 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002083
Neale Rannsf12a83f2017-04-18 09:09:40 -07002084 self.pg3.admin_up()
2085 self.pg3.set_table_ip4(1)
2086 self.pg3.config_ip4()
2087 self.pg3.resolve_arp()
2088 self.pg3.set_table_ip6(1)
2089 self.pg3.config_ip6()
2090 self.pg3.resolve_ndp()
2091
2092 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002093 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07002094 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002095 for i in self.pg_interfaces:
2096 i.unconfig_ip4()
2097 i.unconfig_ip6()
2098 i.set_table_ip4(0)
2099 i.set_table_ip6(0)
2100 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002101 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002102
2103 def test_mpls_ibgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002104 """MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002105
2106 1) setup many iBGP VPN routes via a pair of iBGP peers.
2107 2) Check EMCP forwarding to these peers
2108 3) withdraw the IGP route to one of these peers.
2109 4) check forwarding continues to the remaining peer
2110 """
2111
2112 #
2113 # IGP+LDP core routes
2114 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002115 core_10_0_0_45 = VppIpRoute(
2116 self,
2117 "10.0.0.45",
2118 32,
2119 [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[45])],
2120 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002121 core_10_0_0_45.add_vpp_config()
2122
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002123 core_10_0_0_46 = VppIpRoute(
2124 self,
2125 "10.0.0.46",
2126 32,
2127 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[46])],
2128 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002129 core_10_0_0_46.add_vpp_config()
2130
2131 #
2132 # Lot's of VPN routes. We need more the 64 so VPP will build
2133 # the fast convergence indirection
2134 #
2135 vpn_routes = []
2136 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002137 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002138 dst = "192.168.1.%d" % ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002139 vpn_routes.append(
2140 VppIpRoute(
2141 self,
2142 dst,
2143 32,
2144 [
2145 VppRoutePath(
2146 "10.0.0.45",
2147 0xFFFFFFFF,
2148 labels=[145],
2149 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2150 ),
2151 VppRoutePath(
2152 "10.0.0.46",
2153 0xFFFFFFFF,
2154 labels=[146],
2155 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST,
2156 ),
2157 ],
2158 table_id=1,
2159 )
2160 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002161 vpn_routes[ii].add_vpp_config()
2162
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002163 pkts.append(
2164 Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac)
2165 / IP(src=self.pg2.remote_ip4, dst=dst)
2166 / UDP(sport=1234, dport=1234)
2167 / Raw(b"\xa5" * 100)
2168 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002169
2170 #
2171 # Send the packet stream (one pkt to each VPN route)
2172 # - expect a 50-50 split of the traffic
2173 #
2174 self.pg2.add_stream(pkts)
2175 self.pg_enable_capture(self.pg_interfaces)
2176 self.pg_start()
2177
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002178 rx0 = self.pg0._get_capture(NUM_PKTS)
2179 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002180
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002181 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07002182 # with the split ratio, just as long as neither is 0
2183 self.assertNotEqual(0, len(rx0))
2184 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002185 self.assertEqual(
2186 len(pkts),
2187 len(rx0) + len(rx1),
2188 "Expected all (%s) packets across both ECMP paths. "
2189 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2190 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002191
2192 #
2193 # use a test CLI command to stop the FIB walk process, this
2194 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002195 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002196 #
2197 self.vapi.ppcli("test fib-walk-process disable")
2198
2199 #
2200 # Withdraw one of the IGP routes
2201 #
2202 core_10_0_0_46.remove_vpp_config()
2203
2204 #
2205 # now all packets should be forwarded through the remaining peer
2206 #
2207 self.vapi.ppcli("clear trace")
2208 self.pg2.add_stream(pkts)
2209 self.pg_enable_capture(self.pg_interfaces)
2210 self.pg_start()
2211
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002212 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002213 self.assertEqual(
2214 len(pkts),
2215 len(rx0),
2216 "Expected all (%s) packets across single path. "
2217 "rx0: %s." % (len(pkts), len(rx0)),
2218 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002219
2220 #
2221 # enable the FIB walk process to converge the FIB
2222 #
2223 self.vapi.ppcli("test fib-walk-process enable")
2224
2225 #
2226 # packets should still be forwarded through the remaining peer
2227 #
2228 self.pg2.add_stream(pkts)
2229 self.pg_enable_capture(self.pg_interfaces)
2230 self.pg_start()
2231
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002232 rx0 = self.pg0.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002233 self.assertEqual(
2234 len(pkts),
2235 len(rx0),
2236 "Expected all (%s) packets across single path. "
2237 "rx0: %s." % (len(pkts), len(rx0)),
2238 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002239
2240 #
2241 # Add the IGP route back and we return to load-balancing
2242 #
2243 core_10_0_0_46.add_vpp_config()
2244
2245 self.pg2.add_stream(pkts)
2246 self.pg_enable_capture(self.pg_interfaces)
2247 self.pg_start()
2248
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002249 rx0 = self.pg0._get_capture(NUM_PKTS)
2250 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002251 self.assertNotEqual(0, len(rx0))
2252 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002253 self.assertEqual(
2254 len(pkts),
2255 len(rx0) + len(rx1),
2256 "Expected all (%s) packets across both ECMP paths. "
2257 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2258 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002259
2260 def test_mpls_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002261 """MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002262
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002263 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07002264 2) Check EMCP forwarding to these peers
2265 3) withdraw one eBGP path - expect LB across remaining eBGP
2266 """
2267
2268 #
2269 # Lot's of VPN routes. We need more the 64 so VPP will build
2270 # the fast convergence indirection
2271 #
2272 vpn_routes = []
2273 vpn_bindings = []
2274 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002275 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002276 dst = "192.168.1.%d" % ii
2277 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002278 vpn_routes.append(
2279 VppIpRoute(
2280 self,
2281 dst,
2282 32,
2283 [
2284 VppRoutePath(
2285 self.pg2.remote_ip4,
2286 0xFFFFFFFF,
2287 nh_table_id=1,
2288 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2289 ),
2290 VppRoutePath(
2291 self.pg3.remote_ip4,
2292 0xFFFFFFFF,
2293 nh_table_id=1,
2294 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2295 ),
2296 ],
2297 table_id=1,
2298 )
2299 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002300 vpn_routes[ii].add_vpp_config()
2301
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002302 vpn_bindings.append(
2303 VppMplsIpBind(self, local_label, dst, 32, ip_table_id=1)
2304 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002305 vpn_bindings[ii].add_vpp_config()
2306
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002307 pkts.append(
2308 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2309 / MPLS(label=local_label, ttl=64)
2310 / IP(src=self.pg0.remote_ip4, dst=dst)
2311 / UDP(sport=1234, dport=1234)
2312 / Raw(b"\xa5" * 100)
2313 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002314
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002315 #
2316 # Send the packet stream (one pkt to each VPN route)
2317 # - expect a 50-50 split of the traffic
2318 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002319 self.pg0.add_stream(pkts)
2320 self.pg_enable_capture(self.pg_interfaces)
2321 self.pg_start()
2322
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002323 rx0 = self.pg2._get_capture(NUM_PKTS)
2324 rx1 = self.pg3._get_capture(NUM_PKTS)
2325
2326 # not testing the LB hashing algorithm so we're not concerned
2327 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002328 self.assertNotEqual(0, len(rx0))
2329 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002330 self.assertEqual(
2331 len(pkts),
2332 len(rx0) + len(rx1),
2333 "Expected all (%s) packets across both ECMP paths. "
2334 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2335 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002336
2337 #
2338 # use a test CLI command to stop the FIB walk process, this
2339 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002340 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002341 #
2342 self.vapi.ppcli("test fib-walk-process disable")
2343
2344 #
2345 # withdraw the connected prefix on the interface.
2346 #
2347 self.pg2.unconfig_ip4()
2348
2349 #
2350 # now all packets should be forwarded through the remaining peer
2351 #
2352 self.pg0.add_stream(pkts)
2353 self.pg_enable_capture(self.pg_interfaces)
2354 self.pg_start()
2355
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002356 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002357 self.assertEqual(
2358 len(pkts),
2359 len(rx0),
2360 "Expected all (%s) packets across single path. "
2361 "rx0: %s." % (len(pkts), len(rx0)),
2362 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002363
2364 #
2365 # enable the FIB walk process to converge the FIB
2366 #
2367 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002368
2369 #
2370 # packets should still be forwarded through the remaining peer
2371 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002372 self.pg0.add_stream(pkts)
2373 self.pg_enable_capture(self.pg_interfaces)
2374 self.pg_start()
2375
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002376 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002377 self.assertEqual(
2378 len(pkts),
2379 len(rx0),
2380 "Expected all (%s) packets across single path. "
2381 "rx0: %s." % (len(pkts), len(rx0)),
2382 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002383
2384 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002385 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002386 #
2387 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002388 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002389
2390 self.pg0.add_stream(pkts)
2391 self.pg_enable_capture(self.pg_interfaces)
2392 self.pg_start()
2393
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002394 rx0 = self.pg2._get_capture(NUM_PKTS)
2395 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002396 self.assertNotEqual(0, len(rx0))
2397 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002398 self.assertEqual(
2399 len(pkts),
2400 len(rx0) + len(rx1),
2401 "Expected all (%s) packets across both ECMP paths. "
2402 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2403 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002404
2405 def test_mpls_v6_ebgp_pic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002406 """MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002407
2408 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2409 2) Check EMCP forwarding to these peers
2410 3) withdraw one eBGP path - expect LB across remaining eBGP
2411 """
2412
2413 #
2414 # Lot's of VPN routes. We need more the 64 so VPP will build
2415 # the fast convergence indirection
2416 #
2417 vpn_routes = []
2418 vpn_bindings = []
2419 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002420 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002421 dst = "3000::%d" % ii
2422 local_label = 1600 + ii
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002423 vpn_routes.append(
2424 VppIpRoute(
2425 self,
2426 dst,
2427 128,
2428 [
2429 VppRoutePath(
2430 self.pg2.remote_ip6,
2431 0xFFFFFFFF,
2432 nh_table_id=1,
2433 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2434 ),
2435 VppRoutePath(
2436 self.pg3.remote_ip6,
2437 0xFFFFFFFF,
2438 nh_table_id=1,
2439 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED,
2440 ),
2441 ],
2442 table_id=1,
2443 )
2444 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002445 vpn_routes[ii].add_vpp_config()
2446
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002447 vpn_bindings.append(
2448 VppMplsIpBind(self, local_label, dst, 128, ip_table_id=1)
2449 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002450 vpn_bindings[ii].add_vpp_config()
2451
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002452 pkts.append(
2453 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2454 / MPLS(label=local_label, ttl=64)
2455 / IPv6(src=self.pg0.remote_ip6, dst=dst)
2456 / UDP(sport=1234, dport=1234)
2457 / Raw(b"\xa5" * 100)
2458 )
Neale Ranns097fa662018-05-01 05:17:55 -07002459 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002460
2461 self.pg0.add_stream(pkts)
2462 self.pg_enable_capture(self.pg_interfaces)
2463 self.pg_start()
2464
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002465 rx0 = self.pg2._get_capture(NUM_PKTS)
2466 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002467 self.assertNotEqual(0, len(rx0))
2468 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002469 self.assertEqual(
2470 len(pkts),
2471 len(rx0) + len(rx1),
2472 "Expected all (%s) packets across both ECMP paths. "
2473 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2474 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002475
2476 #
2477 # use a test CLI command to stop the FIB walk process, this
2478 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002479 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002480 #
2481 self.vapi.ppcli("test fib-walk-process disable")
2482
2483 #
2484 # withdraw the connected prefix on the interface.
2485 # and shutdown the interface so the ND cache is flushed.
2486 #
2487 self.pg2.unconfig_ip6()
2488 self.pg2.admin_down()
2489
2490 #
2491 # now all packets should be forwarded through the remaining peer
2492 #
2493 self.pg0.add_stream(pkts)
2494 self.pg_enable_capture(self.pg_interfaces)
2495 self.pg_start()
2496
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002497 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002498 self.assertEqual(
2499 len(pkts),
2500 len(rx0),
2501 "Expected all (%s) packets across single path. "
2502 "rx0: %s." % (len(pkts), len(rx0)),
2503 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002504
2505 #
2506 # enable the FIB walk process to converge the FIB
2507 #
2508 self.vapi.ppcli("test fib-walk-process enable")
2509 self.pg0.add_stream(pkts)
2510 self.pg_enable_capture(self.pg_interfaces)
2511 self.pg_start()
2512
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002513 rx0 = self.pg3.get_capture(NUM_PKTS)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002514 self.assertEqual(
2515 len(pkts),
2516 len(rx0),
2517 "Expected all (%s) packets across single path. "
2518 "rx0: %s." % (len(pkts), len(rx0)),
2519 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002520
2521 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002522 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002523 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002524 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002525 self.pg2.admin_up()
2526 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002527 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002528
2529 self.pg0.add_stream(pkts)
2530 self.pg_enable_capture(self.pg_interfaces)
2531 self.pg_start()
2532
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002533 rx0 = self.pg2._get_capture(NUM_PKTS)
2534 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002535 self.assertNotEqual(0, len(rx0))
2536 self.assertNotEqual(0, len(rx1))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002537 self.assertEqual(
2538 len(pkts),
2539 len(rx0) + len(rx1),
2540 "Expected all (%s) packets across both ECMP paths. "
2541 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)),
2542 )
Neale Rannsf12a83f2017-04-18 09:09:40 -07002543
2544
Neale Rannsda78f952017-05-24 09:15:43 -07002545class TestMPLSL2(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 """MPLS-L2"""
Neale Rannsda78f952017-05-24 09:15:43 -07002547
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002548 @classmethod
2549 def setUpClass(cls):
2550 super(TestMPLSL2, cls).setUpClass()
2551
2552 @classmethod
2553 def tearDownClass(cls):
2554 super(TestMPLSL2, cls).tearDownClass()
2555
Neale Rannsda78f952017-05-24 09:15:43 -07002556 def setUp(self):
2557 super(TestMPLSL2, self).setUp()
2558
2559 # create 2 pg interfaces
2560 self.create_pg_interfaces(range(2))
2561
Neale Ranns15002542017-09-10 04:39:11 -07002562 # create the default MPLS table
2563 self.tables = []
2564 tbl = VppMplsTable(self, 0)
2565 tbl.add_vpp_config()
2566 self.tables.append(tbl)
2567
Neale Ranns1976f362019-11-06 13:13:01 +00002568 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002569 self.pg0.admin_up()
2570 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002571 self.pg0.enable_mpls()
2572
Neale Ranns15002542017-09-10 04:39:11 -07002573 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002574 for i in self.pg_interfaces[1:]:
2575 i.admin_up()
2576
2577 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002578 for i in self.pg_interfaces[1:]:
2579 i.admin_down()
2580
2581 self.pg0.disable_mpls()
2582 self.pg0.unconfig_ip4()
2583 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002584 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002585
Neale Ranns31ed7442018-02-23 05:29:09 -08002586 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002587 capture = verify_filter(capture, sent)
2588
2589 self.assertEqual(len(capture), len(sent))
2590
2591 for i in range(len(capture)):
2592 tx = sent[i]
2593 rx = capture[i]
2594
2595 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002596 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002597
2598 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002599 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002600
2601 self.assertEqual(rx_eth.src, tx_eth.src)
2602 self.assertEqual(rx_eth.dst, tx_eth.dst)
2603
Neale Ranns1976f362019-11-06 13:13:01 +00002604 def verify_arp_req(self, rx, smac, sip, dip):
2605 ether = rx[Ether]
2606 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2607 self.assertEqual(ether.src, smac)
2608
2609 arp = rx[ARP]
2610 self.assertEqual(arp.hwtype, 1)
2611 self.assertEqual(arp.ptype, 0x800)
2612 self.assertEqual(arp.hwlen, 6)
2613 self.assertEqual(arp.plen, 4)
2614 self.assertEqual(arp.op, ARP.who_has)
2615 self.assertEqual(arp.hwsrc, smac)
2616 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2617 self.assertEqual(arp.psrc, sip)
2618 self.assertEqual(arp.pdst, dip)
2619
Neale Rannsda78f952017-05-24 09:15:43 -07002620 def test_vpws(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002621 """Virtual Private Wire Service"""
Neale Rannsda78f952017-05-24 09:15:43 -07002622
2623 #
2624 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002625 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2626 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002627 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002628 mpls_tun_1 = VppMPLSTunnelInterface(
2629 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002630 [
2631 VppRoutePath(
2632 self.pg0.remote_ip4,
2633 self.pg0.sw_if_index,
2634 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)],
2635 )
2636 ],
2637 is_l2=1,
2638 )
Neale Rannsda78f952017-05-24 09:15:43 -07002639 mpls_tun_1.add_vpp_config()
2640 mpls_tun_1.admin_up()
2641
2642 #
2643 # Create a label entry to for 55 that does L2 input to the tunnel
2644 #
2645 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002646 self,
2647 55,
2648 1,
2649 [
2650 VppRoutePath(
2651 "0.0.0.0",
2652 mpls_tun_1.sw_if_index,
2653 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2654 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2655 )
2656 ],
2657 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2658 )
Neale Rannsda78f952017-05-24 09:15:43 -07002659 route_55_eos.add_vpp_config()
2660
2661 #
2662 # Cross-connect the tunnel with one of the customers L2 interfaces
2663 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002664 self.vapi.sw_interface_set_l2_xconnect(
2665 self.pg1.sw_if_index, mpls_tun_1.sw_if_index, enable=1
2666 )
2667 self.vapi.sw_interface_set_l2_xconnect(
2668 mpls_tun_1.sw_if_index, self.pg1.sw_if_index, enable=1
2669 )
Neale Rannsda78f952017-05-24 09:15:43 -07002670
2671 #
2672 # inject a packet from the core
2673 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002674 pcore = (
2675 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2676 / MPLS(label=55, ttl=64)
2677 / Ether(dst="00:00:de:ad:ba:be", src="00:00:de:ad:be:ef")
2678 / IP(src="10.10.10.10", dst="11.11.11.11")
2679 / UDP(sport=1234, dport=1234)
2680 / Raw(b"\xa5" * 100)
2681 )
Neale Rannsda78f952017-05-24 09:15:43 -07002682
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002683 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002684 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2685 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002686
Neale Ranns31ed7442018-02-23 05:29:09 -08002687 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2688 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002689
2690 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002691 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002692 # there's no resolved ARP entry so the first packet we see should be
2693 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002694 #
Neale Ranns1976f362019-11-06 13:13:01 +00002695 tx1 = pcore[MPLS].payload
2696 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2697
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002698 self.verify_arp_req(
2699 rx1[0], self.pg0.local_mac, self.pg0.local_ip4, self.pg0.remote_ip4
2700 )
Neale Ranns1976f362019-11-06 13:13:01 +00002701
2702 #
2703 # resolve the ARP entries and send again
2704 #
2705 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002706 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002707 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002708
Neale Ranns31ed7442018-02-23 05:29:09 -08002709 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002710
2711 def test_vpls(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002712 """Virtual Private LAN Service"""
Neale Ranns1976f362019-11-06 13:13:01 +00002713
2714 # we skipped this in the setup
2715 self.pg0.resolve_arp()
2716
Neale Rannsda78f952017-05-24 09:15:43 -07002717 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002718 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002719 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002720 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002721 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002722 [
2723 VppRoutePath(
2724 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(42)]
2725 )
2726 ],
2727 is_l2=1,
2728 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002729 mpls_tun1.add_vpp_config()
2730 mpls_tun1.admin_up()
2731
2732 mpls_tun2 = VppMPLSTunnelInterface(
2733 self,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002734 [
2735 VppRoutePath(
2736 self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[VppMplsLabel(43)]
2737 )
2738 ],
2739 is_l2=1,
2740 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002741 mpls_tun2.add_vpp_config()
2742 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002743
2744 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002745 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2746 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002747 #
2748 route_55_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002749 self,
2750 55,
2751 1,
2752 [
2753 VppRoutePath(
2754 "0.0.0.0",
2755 mpls_tun1.sw_if_index,
2756 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2757 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2758 )
2759 ],
2760 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2761 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002762
2763 route_56_eos = VppMplsRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002764 self,
2765 56,
2766 1,
2767 [
2768 VppRoutePath(
2769 "0.0.0.0",
2770 mpls_tun2.sw_if_index,
2771 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2772 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2773 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2774 )
2775 ],
2776 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET,
2777 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002778
2779 # move me
2780 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002781 route_55_eos.add_vpp_config()
2782
Neale Ranns1dbcf302019-07-19 11:44:53 +00002783 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2784
Neale Rannsda78f952017-05-24 09:15:43 -07002785 #
2786 # add to tunnel to the customers bridge-domain
2787 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002788 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002789 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1
2790 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002791 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002792 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1
2793 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002794 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002795 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1
2796 )
Neale Rannsda78f952017-05-24 09:15:43 -07002797
2798 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002799 # Packet from host on the customer interface to each host
2800 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002801 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002802 p_cust1 = (
2803 Ether(dst="00:00:de:ad:ba:b1", src="00:00:de:ad:be:ef")
2804 / IP(src="10.10.10.10", dst="11.11.11.11")
2805 / UDP(sport=1234, dport=1234)
2806 / Raw(b"\xa5" * 100)
2807 )
2808 p_cust2 = (
2809 Ether(dst="00:00:de:ad:ba:b2", src="00:00:de:ad:be:ef")
2810 / IP(src="10.10.10.10", dst="11.11.11.12")
2811 / UDP(sport=1234, dport=1234)
2812 / Raw(b"\xa5" * 100)
2813 )
2814 p_core1 = (
2815 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2816 / MPLS(label=55, ttl=64)
2817 / Ether(src="00:00:de:ad:ba:b1", dst="00:00:de:ad:be:ef")
2818 / IP(dst="10.10.10.10", src="11.11.11.11")
2819 / UDP(sport=1234, dport=1234)
2820 / Raw(b"\xa5" * 100)
2821 )
2822 p_core2 = (
2823 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2824 / MPLS(label=56, ttl=64)
2825 / Raw(b"\x01" * 4)
2826 / Ether(src="00:00:de:ad:ba:b2", dst="00:00:de:ad:be:ef") # PW CW
2827 / IP(dst="10.10.10.10", src="11.11.11.12")
2828 / UDP(sport=1234, dport=1234)
2829 / Raw(b"\xa5" * 100)
2830 )
Neale Rannsda78f952017-05-24 09:15:43 -07002831
2832 #
2833 # The BD is learning, so send in one of each packet to learn
2834 #
Neale Rannsda78f952017-05-24 09:15:43 -07002835
Neale Ranns1dbcf302019-07-19 11:44:53 +00002836 # 2 packets due to BD flooding
2837 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2838 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002839
Neale Ranns1dbcf302019-07-19 11:44:53 +00002840 # we've learnt this so expect it be be forwarded not flooded
2841 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2842 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2843 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002844
Neale Ranns1dbcf302019-07-19 11:44:53 +00002845 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2846 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2847 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002848
2849 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002850 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002851 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002852 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002853 self.verify_capture_tunneled_ethernet(
2854 rx, p_cust1 * NUM_PKTS, [VppMplsLabel(42)]
2855 )
Neale Rannsda78f952017-05-24 09:15:43 -07002856
Neale Ranns1dbcf302019-07-19 11:44:53 +00002857 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002858 self.verify_capture_tunneled_ethernet(
2859 rx, p_cust2 * NUM_PKTS, [VppMplsLabel(43)]
2860 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002861
2862 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2863 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2864
Neale Rannsda78f952017-05-24 09:15:43 -07002865 #
2866 # remove interfaces from customers bridge-domain
2867 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002868 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002869 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0
2870 )
Neale Ranns1dbcf302019-07-19 11:44:53 +00002871 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002872 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0
2873 )
Ole Troana5b2eec2019-03-11 19:23:25 +01002874 self.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002875 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0
2876 )
Neale Rannsda78f952017-05-24 09:15:43 -07002877
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002878
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002879if __name__ == "__main__":
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002880 unittest.main(testRunner=VppTestRunner)