blob: d94676b67da52138dcf2aae04afdbcd21d50ee90 [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
Neale Ranns5a8123b2017-01-26 01:18:23 -08009from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -080010 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Ranns990f6942020-10-20 07:20:17 +000011 VppIpTable, VppMplsTable, \
Neale Ranns097fa662018-05-01 05:17:55 -070012 VppMplsLabel, MplsLspMode, find_mpls_route, \
13 FibPathProto, FibPathType, FibPathFlags, VppMplsLabel, MplsLspMode
Neale Ranns0f26c5a2017-03-01 15:12:11 -080014from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns990f6942020-10-20 07:20:17 +000015from vpp_papi import VppEnum
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070017import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000018from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000019from scapy.layers.l2 import Ether, ARP
Neale Rannscb630ff2016-12-14 13:31:29 +010020from scapy.layers.inet import IP, UDP, ICMP
Neale Rannsec5371e2022-03-04 11:45:41 +000021from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded, ICMPv6EchoRequest, \
22 ICMPv6PacketTooBig
Neale Ranns8fe8cc22016-11-01 10:05:08 +000023from scapy.contrib.mpls import MPLS
24
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040025NUM_PKTS = 67
26
Neale Ranns1976f362019-11-06 13:13:01 +000027# scapy removed these attributes.
28# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
29# semantic names have more meaning than numbers. so here they are.
30ARP.who_has = 1
31ARP.is_at = 2
32
Klement Sekeradab231a2016-12-21 08:50:14 +010033
Neale Rannsda78f952017-05-24 09:15:43 -070034def verify_filter(capture, sent):
35 if not len(capture) == len(sent):
36 # filter out any IPv6 RAs from the capture
37 for p in capture:
38 if p.haslayer(IPv6):
39 capture.remove(p)
40 return capture
41
42
Neale Ranns31ed7442018-02-23 05:29:09 -080043def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070044 # the rx'd packet has the MPLS label popped
45 eth = rx[Ether]
46 tst.assertEqual(eth.type, 0x8847)
47
48 rx_mpls = rx[MPLS]
49
50 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080051 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
52 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
53 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
54
Neale Rannsda78f952017-05-24 09:15:43 -070055 if ii == len(mpls_labels) - 1:
56 tst.assertEqual(rx_mpls.s, 1)
57 else:
58 # not end of stack
59 tst.assertEqual(rx_mpls.s, 0)
60 # pop the label to expose the next
61 rx_mpls = rx_mpls[MPLS].payload
62
63
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000064@tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +000065class TestMPLS(VppTestCase):
66 """ MPLS Test Case """
67
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070068 @classmethod
69 def setUpClass(cls):
70 super(TestMPLS, cls).setUpClass()
71
72 @classmethod
73 def tearDownClass(cls):
74 super(TestMPLS, cls).tearDownClass()
75
Neale Ranns8fe8cc22016-11-01 10:05:08 +000076 def setUp(self):
77 super(TestMPLS, self).setUp()
78
79 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080080 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000081
82 # setup both interfaces
83 # assign them different tables.
84 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070085 self.tables = []
86
87 tbl = VppMplsTable(self, 0)
88 tbl.add_vpp_config()
89 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000090
91 for i in self.pg_interfaces:
92 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070093
94 if table_id != 0:
95 tbl = VppIpTable(self, table_id)
96 tbl.add_vpp_config()
97 self.tables.append(tbl)
98 tbl = VppIpTable(self, table_id, is_ip6=1)
99 tbl.add_vpp_config()
100 self.tables.append(tbl)
101
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000102 i.set_table_ip4(table_id)
103 i.set_table_ip6(table_id)
104 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000105 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000106 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000107 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000108 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000109 table_id += 1
110
111 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800112 for i in self.pg_interfaces:
113 i.unconfig_ip4()
114 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700115 i.set_table_ip4(0)
116 i.set_table_ip6(0)
117 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800118 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700119 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000120
Neale Rannsad422ed2016-11-02 14:20:04 +0000121 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100122 def create_stream_labelled_ip4(
123 self,
124 src_if,
125 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100126 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800127 ip_itf=None,
128 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700129 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800130 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800131 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100132 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000133 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800134 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100135 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000136 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000137 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
138
139 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800140 p = p / MPLS(label=mpls_labels[ii].value,
141 ttl=mpls_labels[ii].ttl,
142 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100143 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800144 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800145 p = (p / IP(src=src_if.local_ip4,
146 dst=src_if.remote_ip4,
147 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800148 UDP(sport=1234, dport=1234) /
149 Raw(payload))
150 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800151 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800152 UDP(sport=1234, dport=1234) /
153 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100154 else:
155 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800156 dst=ip_itf.local_ip4,
157 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100158 ICMP())
159
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700160 if chksum:
161 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000162 info.data = p.copy()
163 pkts.append(p)
164 return pkts
165
Ole Troaneb284a12019-10-09 13:33:19 +0200166 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64,
167 ip_dscp=0, payload_size=None):
Klement Sekeradab231a2016-12-21 08:50:14 +0100168 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000169 pkts = []
170 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100171 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000172 payload = self.info_to_payload(info)
173 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800174 IP(src=src_if.remote_ip4, dst=dst_ip,
175 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000176 UDP(sport=1234, dport=1234) /
177 Raw(payload))
178 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200179 if payload_size:
180 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000181 pkts.append(p)
182 return pkts
183
Neale Ranns31ed7442018-02-23 05:29:09 -0800184 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
185 self.reset_packet_infos()
186 pkts = []
187 for i in range(0, 257):
188 info = self.create_packet_info(src_if, src_if)
189 payload = self.info_to_payload(info)
190 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
191 IPv6(src=src_if.remote_ip6, dst=dst_ip,
192 hlim=ip_ttl, tc=ip_dscp) /
193 UDP(sport=1234, dport=1234) /
194 Raw(payload))
195 info.data = p.copy()
196 pkts.append(p)
197 return pkts
198
199 def create_stream_labelled_ip6(self, src_if, mpls_labels,
Neale Rannsf478f752022-02-17 15:41:32 +0000200 hlim=64, dst_ip=None,
201 ping=0, ip_itf=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700202 if dst_ip is None:
203 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100204 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000205 pkts = []
206 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100207 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000208 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800209 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
210 for l in mpls_labels:
211 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
212
Neale Rannsf478f752022-02-17 15:41:32 +0000213 if ping:
214 p = p / (IPv6(src=ip_itf.remote_ip6,
215 dst=ip_itf.local_ip6) /
216 ICMPv6EchoRequest())
217 else:
218 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
219 UDP(sport=1234, dport=1234) /
220 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000221 info.data = p.copy()
222 pkts.append(p)
223 return pkts
224
Neale Ranns31ed7442018-02-23 05:29:09 -0800225 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
226 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000227 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700228 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000229
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000230 self.assertEqual(len(capture), len(sent))
231
232 for i in range(len(capture)):
233 tx = sent[i]
234 rx = capture[i]
235
236 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000237 eth = rx[Ether]
238 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000239
240 tx_ip = tx[IP]
241 rx_ip = rx[IP]
242
Neale Rannscb630ff2016-12-14 13:31:29 +0100243 if not ping_resp:
244 self.assertEqual(rx_ip.src, tx_ip.src)
245 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800246 self.assertEqual(rx_ip.tos, ip_dscp)
247 if not ip_ttl:
248 # IP processing post pop has decremented the TTL
249 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
250 else:
251 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100252 else:
253 self.assertEqual(rx_ip.src, tx_ip.dst)
254 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000255
256 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000257 raise
258
Neale Rannsad422ed2016-11-02 14:20:04 +0000259 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800260 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000261 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700262 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000263
264 self.assertEqual(len(capture), len(sent))
265
266 for i in range(len(capture)):
267 tx = sent[i]
268 rx = capture[i]
269 tx_ip = tx[IP]
270 rx_ip = rx[IP]
271
Neale Ranns31ed7442018-02-23 05:29:09 -0800272 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000273
274 self.assertEqual(rx_ip.src, tx_ip.src)
275 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800276 if not ip_ttl:
277 # IP processing post pop has decremented the TTL
278 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
279 else:
280 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000281
282 except:
283 raise
284
Neale Ranns31ed7442018-02-23 05:29:09 -0800285 def verify_capture_labelled_ip6(self, src_if, capture, sent,
286 mpls_labels, ip_ttl=None):
287 try:
288 capture = verify_filter(capture, sent)
289
290 self.assertEqual(len(capture), len(sent))
291
292 for i in range(len(capture)):
293 tx = sent[i]
294 rx = capture[i]
295 tx_ip = tx[IPv6]
296 rx_ip = rx[IPv6]
297
298 verify_mpls_stack(self, rx, mpls_labels)
299
300 self.assertEqual(rx_ip.src, tx_ip.src)
301 self.assertEqual(rx_ip.dst, tx_ip.dst)
302 if not ip_ttl:
303 # IP processing post pop has decremented the TTL
304 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
305 else:
306 self.assertEqual(rx_ip.hlim, ip_ttl)
307
308 except:
309 raise
310
311 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000312 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700313 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000314
315 self.assertEqual(len(capture), len(sent))
316
317 for i in range(len(capture)):
318 tx = sent[i]
319 rx = capture[i]
320 tx_ip = tx[IP]
321 rx_ip = rx[IP]
322
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000324
325 self.assertEqual(rx_ip.src, tx_ip.src)
326 self.assertEqual(rx_ip.dst, tx_ip.dst)
327 # IP processing post pop has decremented the TTL
328 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
329
330 except:
331 raise
332
333 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800334 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000335 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700336 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000337
338 self.assertEqual(len(capture), len(sent))
339
340 for i in range(len(capture)):
341 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800342 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000343 except:
344 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000345
Neale Ranns31ed7442018-02-23 05:29:09 -0800346 def verify_capture_ip6(self, src_if, capture, sent,
Neale Rannsf478f752022-02-17 15:41:32 +0000347 ip_hlim=None, ip_dscp=0,
348 ping_resp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000349 try:
350 self.assertEqual(len(capture), len(sent))
351
352 for i in range(len(capture)):
353 tx = sent[i]
354 rx = capture[i]
355
356 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000357 eth = rx[Ether]
358 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000359
360 tx_ip = tx[IPv6]
361 rx_ip = rx[IPv6]
362
Neale Rannsf478f752022-02-17 15:41:32 +0000363 if not ping_resp:
364 self.assertEqual(rx_ip.src, tx_ip.src)
365 self.assertEqual(rx_ip.dst, tx_ip.dst)
366 self.assertEqual(rx_ip.tc, ip_dscp)
367 # IP processing post pop has decremented the TTL
368 if not ip_hlim:
369 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
370 else:
371 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns31ed7442018-02-23 05:29:09 -0800372 else:
Neale Rannsf478f752022-02-17 15:41:32 +0000373 self.assertEqual(rx_ip.src, tx_ip.dst)
374 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000375 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000376 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000377
Neale Ranns62fe07c2017-10-31 12:28:22 -0700378 def verify_capture_ip6_icmp(self, src_if, capture, sent):
379 try:
Neale Ranns5c6dd172022-02-17 09:08:47 +0000380 # rate limited ICMP
381 self.assertTrue(len(capture) <= len(sent))
Neale Ranns62fe07c2017-10-31 12:28:22 -0700382
383 for i in range(len(capture)):
384 tx = sent[i]
385 rx = capture[i]
386
387 # the rx'd packet has the MPLS label popped
388 eth = rx[Ether]
389 self.assertEqual(eth.type, 0x86DD)
390
391 tx_ip = tx[IPv6]
392 rx_ip = rx[IPv6]
393
394 self.assertEqual(rx_ip.dst, tx_ip.src)
395 # ICMP sourced from the interface's address
396 self.assertEqual(rx_ip.src, src_if.local_ip6)
397 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200398 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700399
400 icmp = rx[ICMPv6TimeExceeded]
401
402 except:
403 raise
404
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530405 def verify_capture_fragmented_labelled_ip4(self, src_if, capture, sent,
406 mpls_labels, ip_ttl=None):
407 try:
408 capture = verify_filter(capture, sent)
409
410 for i in range(len(capture)):
411 tx = sent[0]
412 rx = capture[i]
413 tx_ip = tx[IP]
414 rx_ip = rx[IP]
415
416 verify_mpls_stack(self, rx, mpls_labels)
417
418 self.assertEqual(rx_ip.src, tx_ip.src)
419 self.assertEqual(rx_ip.dst, tx_ip.dst)
420 if not ip_ttl:
421 # IP processing post pop has decremented the TTL
422 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
423 else:
424 self.assertEqual(rx_ip.ttl, ip_ttl)
425
426 except:
427 raise
428
Neale Rannsec5371e2022-03-04 11:45:41 +0000429 def verify_capture_fragmented_labelled_ip6(self, src_if, capture, sent,
430 mpls_labels, ip_ttl=None):
431 try:
432 capture = verify_filter(capture, sent)
433
434 for i in range(len(capture)):
435 tx = sent[0]
436 rx = capture[i]
437 tx_ip = tx[IPv6]
438 rx.show()
439 rx_ip = IPv6(rx[MPLS].payload)
440 rx_ip.show()
441
442 verify_mpls_stack(self, rx, mpls_labels)
443
444 self.assertEqual(rx_ip.src, tx_ip.src)
445 self.assertEqual(rx_ip.dst, tx_ip.dst)
446 if not ip_ttl:
447 # IP processing post pop has decremented the hop-limit
448 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
449 else:
450 self.assertEqual(rx_ip.hlim, ip_ttl)
451 except:
452 raise
453
Neale Rannsad422ed2016-11-02 14:20:04 +0000454 def test_swap(self):
455 """ MPLS label swap tests """
456
457 #
458 # A simple MPLS xconnect - eos label in label out
459 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800460 route_32_eos = VppMplsRoute(self, 32, 1,
461 [VppRoutePath(self.pg0.remote_ip4,
462 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800463 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000464 route_32_eos.add_vpp_config()
465
Neale Ranns775f73c2018-12-20 03:01:49 -0800466 self.assertTrue(
467 find_mpls_route(self, 0, 32, 1,
468 [VppRoutePath(self.pg0.remote_ip4,
469 self.pg0.sw_if_index,
470 labels=[VppMplsLabel(33)])]))
471
Neale Rannsad422ed2016-11-02 14:20:04 +0000472 #
473 # a stream that matches the route for 10.0.0.1
474 # PG0 is in the default table
475 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800476 tx = self.create_stream_labelled_ip4(self.pg0,
477 [VppMplsLabel(32, ttl=32, exp=1)])
478 rx = self.send_and_expect(self.pg0, tx, self.pg0)
479 self.verify_capture_labelled(self.pg0, rx, tx,
480 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000481
Neale Ranns008dbe12018-09-07 09:32:36 -0700482 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
483
Neale Rannsad422ed2016-11-02 14:20:04 +0000484 #
485 # A simple MPLS xconnect - non-eos label in label out
486 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800487 route_32_neos = VppMplsRoute(self, 32, 0,
488 [VppRoutePath(self.pg0.remote_ip4,
489 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800490 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000491 route_32_neos.add_vpp_config()
492
493 #
494 # a stream that matches the route for 10.0.0.1
495 # PG0 is in the default table
496 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800497 tx = self.create_stream_labelled_ip4(self.pg0,
498 [VppMplsLabel(32, ttl=21, exp=7),
499 VppMplsLabel(99)])
500 rx = self.send_and_expect(self.pg0, tx, self.pg0)
501 self.verify_capture_labelled(self.pg0, rx, tx,
502 [VppMplsLabel(33, ttl=20, exp=7),
503 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700504 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000505
Neale Ranns31ed7442018-02-23 05:29:09 -0800506 #
507 # A simple MPLS xconnect - non-eos label in label out, uniform mode
508 #
509 route_42_neos = VppMplsRoute(
510 self, 42, 0,
511 [VppRoutePath(self.pg0.remote_ip4,
512 self.pg0.sw_if_index,
513 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
514 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000515
Neale Ranns31ed7442018-02-23 05:29:09 -0800516 tx = self.create_stream_labelled_ip4(self.pg0,
517 [VppMplsLabel(42, ttl=21, exp=7),
518 VppMplsLabel(99)])
519 rx = self.send_and_expect(self.pg0, tx, self.pg0)
520 self.verify_capture_labelled(self.pg0, rx, tx,
521 [VppMplsLabel(43, ttl=20, exp=7),
522 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000523
524 #
525 # An MPLS xconnect - EOS label in IP out
526 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800527 route_33_eos = VppMplsRoute(self, 33, 1,
528 [VppRoutePath(self.pg0.remote_ip4,
529 self.pg0.sw_if_index,
530 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000531 route_33_eos.add_vpp_config()
532
Neale Ranns31ed7442018-02-23 05:29:09 -0800533 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
534 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000535 self.verify_capture_ip4(self.pg0, rx, tx)
536
537 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700538 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700539 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800540 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700541 dst_ip=self.pg0.remote_ip4,
542 n=65,
543 chksum=1)
544 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
545
546 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800547 # An MPLS xconnect - EOS label in IP out, uniform mode
548 #
549 route_3333_eos = VppMplsRoute(
550 self, 3333, 1,
551 [VppRoutePath(self.pg0.remote_ip4,
552 self.pg0.sw_if_index,
553 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
554 route_3333_eos.add_vpp_config()
555
556 tx = self.create_stream_labelled_ip4(
557 self.pg0,
558 [VppMplsLabel(3333, ttl=55, exp=3)])
559 rx = self.send_and_expect(self.pg0, tx, self.pg0)
560 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
561 tx = self.create_stream_labelled_ip4(
562 self.pg0,
563 [VppMplsLabel(3333, ttl=66, exp=4)])
564 rx = self.send_and_expect(self.pg0, tx, self.pg0)
565 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
566
567 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700568 # An MPLS xconnect - EOS label in IPv6 out
569 #
570 route_333_eos = VppMplsRoute(
571 self, 333, 1,
572 [VppRoutePath(self.pg0.remote_ip6,
573 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700574 labels=[])],
575 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700576 route_333_eos.add_vpp_config()
577
Neale Ranns31ed7442018-02-23 05:29:09 -0800578 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
579 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700580 self.verify_capture_ip6(self.pg0, rx, tx)
581
582 #
583 # disposed packets have an TTL expired
584 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800585 tx = self.create_stream_labelled_ip6(self.pg0,
586 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700587 dst_ip=self.pg1.remote_ip6,
588 hlim=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +0000589 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700590 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
591
592 #
593 # An MPLS xconnect - EOS label in IPv6 out w imp-null
594 #
595 route_334_eos = VppMplsRoute(
596 self, 334, 1,
597 [VppRoutePath(self.pg0.remote_ip6,
598 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700599 labels=[VppMplsLabel(3)])],
600 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700601 route_334_eos.add_vpp_config()
602
Neale Ranns31ed7442018-02-23 05:29:09 -0800603 tx = self.create_stream_labelled_ip6(self.pg0,
604 [VppMplsLabel(334, ttl=64)])
605 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700606 self.verify_capture_ip6(self.pg0, rx, tx)
607
608 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800609 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
610 #
611 route_335_eos = VppMplsRoute(
612 self, 335, 1,
613 [VppRoutePath(self.pg0.remote_ip6,
614 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700615 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
616 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800617 route_335_eos.add_vpp_config()
618
619 tx = self.create_stream_labelled_ip6(
620 self.pg0,
621 [VppMplsLabel(335, ttl=27, exp=4)])
622 rx = self.send_and_expect(self.pg0, tx, self.pg0)
623 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
624
625 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700626 # disposed packets have an TTL expired
627 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800628 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700629 dst_ip=self.pg1.remote_ip6,
630 hlim=0)
Neale Ranns5c6dd172022-02-17 09:08:47 +0000631 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700632 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
633
634 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000635 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
636 # so this traffic should be dropped.
637 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800638 route_33_neos = VppMplsRoute(self, 33, 0,
639 [VppRoutePath(self.pg0.remote_ip4,
640 self.pg0.sw_if_index,
641 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000642 route_33_neos.add_vpp_config()
643
Neale Ranns31ed7442018-02-23 05:29:09 -0800644 tx = self.create_stream_labelled_ip4(self.pg0,
645 [VppMplsLabel(33),
646 VppMplsLabel(99)])
647 self.send_and_assert_no_replies(
648 self.pg0, tx,
649 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000650
651 #
652 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800653 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000654 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800655 route_34_eos = VppMplsRoute(self, 34, 1,
656 [VppRoutePath("0.0.0.0",
657 0xffffffff,
658 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800659 labels=[VppMplsLabel(44),
660 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000661 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700662 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000663
Neale Ranns31ed7442018-02-23 05:29:09 -0800664 tx = self.create_stream_labelled_ip4(self.pg0,
665 [VppMplsLabel(34, ttl=3)])
666 rx = self.send_and_expect(self.pg0, tx, self.pg0)
667 self.verify_capture_labelled(self.pg0, rx, tx,
668 [VppMplsLabel(33),
669 VppMplsLabel(44),
670 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000671
Neale Ranns008dbe12018-09-07 09:32:36 -0700672 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
673 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
674
Neale Ranns31ed7442018-02-23 05:29:09 -0800675 #
676 # A recursive EOS x-connect, which resolves through another x-connect
677 # in uniform mode
678 #
679 route_35_eos = VppMplsRoute(
680 self, 35, 1,
681 [VppRoutePath("0.0.0.0",
682 0xffffffff,
683 nh_via_label=42,
684 labels=[VppMplsLabel(44)])])
685 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000686
Neale Ranns31ed7442018-02-23 05:29:09 -0800687 tx = self.create_stream_labelled_ip4(self.pg0,
688 [VppMplsLabel(35, ttl=3)])
689 rx = self.send_and_expect(self.pg0, tx, self.pg0)
690 self.verify_capture_labelled(self.pg0, rx, tx,
691 [VppMplsLabel(43, ttl=2),
692 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000693
694 #
Matej Klottondeb69842016-12-09 15:05:46 +0100695 # A recursive non-EOS x-connect, which resolves through another
696 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000697 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800698 route_34_neos = VppMplsRoute(self, 34, 0,
699 [VppRoutePath("0.0.0.0",
700 0xffffffff,
701 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800702 labels=[VppMplsLabel(44),
703 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000704 route_34_neos.add_vpp_config()
705
Neale Ranns31ed7442018-02-23 05:29:09 -0800706 tx = self.create_stream_labelled_ip4(self.pg0,
707 [VppMplsLabel(34, ttl=45),
708 VppMplsLabel(99)])
709 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100710 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800711 self.verify_capture_labelled(self.pg0, rx, tx,
712 [VppMplsLabel(33),
713 VppMplsLabel(44),
714 VppMplsLabel(46, ttl=44),
715 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000716
717 #
Matej Klottondeb69842016-12-09 15:05:46 +0100718 # an recursive IP route that resolves through the recursive non-eos
719 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000720 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800721 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
722 [VppRoutePath("0.0.0.0",
723 0xffffffff,
724 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800725 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000726 ip_10_0_0_1.add_vpp_config()
727
Neale Rannsad422ed2016-11-02 14:20:04 +0000728 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800729 rx = self.send_and_expect(self.pg0, tx, self.pg0)
730 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
731 [VppMplsLabel(33),
732 VppMplsLabel(44),
733 VppMplsLabel(46),
734 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700735 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000736
737 ip_10_0_0_1.remove_vpp_config()
738 route_34_neos.remove_vpp_config()
739 route_34_eos.remove_vpp_config()
740 route_33_neos.remove_vpp_config()
741 route_33_eos.remove_vpp_config()
742 route_32_neos.remove_vpp_config()
743 route_32_eos.remove_vpp_config()
744
745 def test_bind(self):
746 """ MPLS Local Label Binding test """
747
748 #
749 # Add a non-recursive route with a single out label
750 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800751 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
752 [VppRoutePath(self.pg0.remote_ip4,
753 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800754 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 route_10_0_0_1.add_vpp_config()
756
757 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800758 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000759 binding.add_vpp_config()
760
761 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800762 tx = self.create_stream_labelled_ip4(self.pg0,
763 [VppMplsLabel(44),
764 VppMplsLabel(99)])
765 rx = self.send_and_expect(self.pg0, tx, self.pg0)
766 self.verify_capture_labelled(self.pg0, rx, tx,
767 [VppMplsLabel(45, ttl=63),
768 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000769
770 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800771 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
772 rx = self.send_and_expect(self.pg0, tx, self.pg0)
773 self.verify_capture_labelled(self.pg0, rx, tx,
774 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000775
776 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000777 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800778 rx = self.send_and_expect(self.pg0, tx, self.pg0)
779 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000780
781 #
782 # cleanup
783 #
784 binding.remove_vpp_config()
785 route_10_0_0_1.remove_vpp_config()
786
787 def test_imposition(self):
788 """ MPLS label imposition test """
789
790 #
791 # Add a non-recursive route with a single out label
792 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800793 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
794 [VppRoutePath(self.pg0.remote_ip4,
795 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800796 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000797 route_10_0_0_1.add_vpp_config()
798
799 #
800 # a stream that matches the route for 10.0.0.1
801 # PG0 is in the default table
802 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000803 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800804 rx = self.send_and_expect(self.pg0, tx, self.pg0)
805 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000806
807 #
808 # Add a non-recursive route with a 3 out labels
809 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800810 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
811 [VppRoutePath(self.pg0.remote_ip4,
812 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800813 labels=[VppMplsLabel(32),
814 VppMplsLabel(33),
815 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000816 route_10_0_0_2.add_vpp_config()
817
Neale Ranns31ed7442018-02-23 05:29:09 -0800818 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
819 ip_ttl=44, ip_dscp=0xff)
820 rx = self.send_and_expect(self.pg0, tx, self.pg0)
821 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
822 [VppMplsLabel(32),
823 VppMplsLabel(33),
824 VppMplsLabel(34)],
825 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000826
Neale Ranns31ed7442018-02-23 05:29:09 -0800827 #
828 # Add a non-recursive route with a single out label in uniform mode
829 #
830 route_10_0_0_3 = VppIpRoute(
831 self, "10.0.0.3", 32,
832 [VppRoutePath(self.pg0.remote_ip4,
833 self.pg0.sw_if_index,
834 labels=[VppMplsLabel(32,
835 mode=MplsLspMode.UNIFORM)])])
836 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000837
Neale Ranns31ed7442018-02-23 05:29:09 -0800838 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
839 ip_ttl=54, ip_dscp=0xbe)
840 rx = self.send_and_expect(self.pg0, tx, self.pg0)
841 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
842 [VppMplsLabel(32, ttl=53, exp=5)])
843
844 #
845 # Add a IPv6 non-recursive route with a single out label in
846 # uniform mode
847 #
848 route_2001_3 = VppIpRoute(
849 self, "2001::3", 128,
850 [VppRoutePath(self.pg0.remote_ip6,
851 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800852 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700853 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800854 route_2001_3.add_vpp_config()
855
856 tx = self.create_stream_ip6(self.pg0, "2001::3",
857 ip_ttl=54, ip_dscp=0xbe)
858 rx = self.send_and_expect(self.pg0, tx, self.pg0)
859 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
860 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000861
862 #
Matej Klottondeb69842016-12-09 15:05:46 +0100863 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000864 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800865 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
866 [VppRoutePath("10.0.0.1",
867 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800868 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000869 route_11_0_0_1.add_vpp_config()
870
871 #
872 # a stream that matches the route for 11.0.0.1, should pick up
873 # the label stack for 11.0.0.1 and 10.0.0.1
874 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000875 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800876 rx = self.send_and_expect(self.pg0, tx, self.pg0)
877 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
878 [VppMplsLabel(32),
879 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000880
Neale Ranns008dbe12018-09-07 09:32:36 -0700881 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
882
Neale Rannsad422ed2016-11-02 14:20:04 +0000883 #
884 # add a recursive path, with 2 labels, via the 3 label route
885 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800886 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
887 [VppRoutePath("10.0.0.2",
888 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800889 labels=[VppMplsLabel(44),
890 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000891 route_11_0_0_2.add_vpp_config()
892
893 #
894 # a stream that matches the route for 11.0.0.1, should pick up
895 # the label stack for 11.0.0.1 and 10.0.0.1
896 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000897 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800898 rx = self.send_and_expect(self.pg0, tx, self.pg0)
899 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
900 [VppMplsLabel(32),
901 VppMplsLabel(33),
902 VppMplsLabel(34),
903 VppMplsLabel(44),
904 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000905
Neale Ranns008dbe12018-09-07 09:32:36 -0700906 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
907
908 rx = self.send_and_expect(self.pg0, tx, self.pg0)
909 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
910 [VppMplsLabel(32),
911 VppMplsLabel(33),
912 VppMplsLabel(34),
913 VppMplsLabel(44),
914 VppMplsLabel(45)])
915
916 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
917
Neale Rannsad422ed2016-11-02 14:20:04 +0000918 #
919 # cleanup
920 #
921 route_11_0_0_2.remove_vpp_config()
922 route_11_0_0_1.remove_vpp_config()
923 route_10_0_0_2.remove_vpp_config()
924 route_10_0_0_1.remove_vpp_config()
925
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530926 def test_imposition_fragmentation(self):
927 """ MPLS label imposition fragmentation test """
928
929 #
930 # Add a ipv4 non-recursive route with a single out label
931 #
932 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
933 [VppRoutePath(self.pg0.remote_ip4,
934 self.pg0.sw_if_index,
935 labels=[VppMplsLabel(32)])])
936 route_10_0_0_1.add_vpp_config()
Neale Rannsec5371e2022-03-04 11:45:41 +0000937 route_1000_1 = VppIpRoute(self, "1000::1", 128,
938 [VppRoutePath(self.pg0.remote_ip6,
939 self.pg0.sw_if_index,
940 labels=[VppMplsLabel(32)])])
941 route_1000_1.add_vpp_config()
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530942
943 #
944 # a stream that matches the route for 10.0.0.1
945 # PG0 is in the default table
946 #
947 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
948 for i in range(0, 257):
949 self.extend_packet(tx[i], 10000)
950
951 #
952 # 5 fragments per packet (257*5=1285)
953 #
954 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
955 self.verify_capture_fragmented_labelled_ip4(self.pg0, rx, tx,
956 [VppMplsLabel(32)])
957
Neale Rannsec5371e2022-03-04 11:45:41 +0000958 # packets with DF bit set generate ICMP
959 for t in tx:
960 t[IP].flags = 'DF'
961 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
962
963 for rx in rxs:
964 rx[ICMP].code = "fragmentation-needed"
965
966 self.assertEqual(self.statistics.get_err_counter(
967 "/err/mpls-frag/can't fragment this packet"),
968 len(tx))
969 #
970 # a stream that matches the route for 1000::1/128
971 # PG0 is in the default table
972 #
973 tx = self.create_stream_ip6(self.pg0, "1000::1")
974 for i in range(0, 257):
975 self.extend_packet(tx[i], 10000)
976
977 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
978 for rx in rxs:
979 rx[ICMPv6PacketTooBig].mtu = 9000
980
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530981 #
982 # cleanup
983 #
984 route_10_0_0_1.remove_vpp_config()
985
Neale Ranns31ed7442018-02-23 05:29:09 -0800986 def test_tunnel_pipe(self):
987 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000988
989 #
Ole Troaneb284a12019-10-09 13:33:19 +0200990 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +0000991 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800992 mpls_tun = VppMPLSTunnelInterface(
993 self,
994 [VppRoutePath(self.pg0.remote_ip4,
995 self.pg0.sw_if_index,
996 labels=[VppMplsLabel(44),
997 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800998 mpls_tun.add_vpp_config()
999 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +00001000
1001 #
1002 # add an unlabelled route through the new tunnel
1003 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001004 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1005 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001006 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -08001007 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +00001008
1009 self.vapi.cli("clear trace")
1010 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1011 self.pg0.add_stream(tx)
1012
1013 self.pg_enable_capture(self.pg_interfaces)
1014 self.pg_start()
1015
1016 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -08001017 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1018 [VppMplsLabel(44),
1019 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001020
Neale Ranns8c4611b2017-05-23 03:43:47 -07001021 #
1022 # add a labelled route through the new tunnel
1023 #
1024 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
1025 [VppRoutePath("0.0.0.0",
1026 mpls_tun._sw_if_index,
1027 labels=[33])])
1028 route_10_0_0_4.add_vpp_config()
1029
1030 self.vapi.cli("clear trace")
1031 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1032 self.pg0.add_stream(tx)
1033
1034 self.pg_enable_capture(self.pg_interfaces)
1035 self.pg_start()
1036
1037 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -08001038 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1039 [VppMplsLabel(44),
1040 VppMplsLabel(46),
1041 VppMplsLabel(33, ttl=255)])
1042
Ole Troaneb284a12019-10-09 13:33:19 +02001043 #
1044 # change tunnel's MTU to a low value
1045 #
1046 mpls_tun.set_l3_mtu(1200)
1047
1048 # send IP into the tunnel to be fragmented
1049 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
1050 payload_size=1500)
1051 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
1052
1053 fake_tx = []
1054 for p in tx:
1055 fake_tx.append(p)
1056 fake_tx.append(p)
1057 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1058 [VppMplsLabel(44),
1059 VppMplsLabel(46)])
1060
1061 # send MPLS into the tunnel to be fragmented
1062 tx = self.create_stream_ip4(self.pg0, "10.0.0.4",
1063 payload_size=1500)
1064 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
1065
1066 fake_tx = []
1067 for p in tx:
1068 fake_tx.append(p)
1069 fake_tx.append(p)
1070 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1071 [VppMplsLabel(44),
1072 VppMplsLabel(46),
1073 VppMplsLabel(33, ttl=255)])
1074
Neale Ranns31ed7442018-02-23 05:29:09 -08001075 def test_tunnel_uniform(self):
1076 """ MPLS Tunnel Tests - Uniform """
1077
1078 #
1079 # Create a tunnel with a single out label
1080 # The label stack is specified here from outer to inner
1081 #
1082 mpls_tun = VppMPLSTunnelInterface(
1083 self,
1084 [VppRoutePath(self.pg0.remote_ip4,
1085 self.pg0.sw_if_index,
1086 labels=[VppMplsLabel(44, ttl=32),
1087 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1088 mpls_tun.add_vpp_config()
1089 mpls_tun.admin_up()
1090
1091 #
1092 # add an unlabelled route through the new tunnel
1093 #
1094 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1095 [VppRoutePath("0.0.0.0",
1096 mpls_tun._sw_if_index)])
1097 route_10_0_0_3.add_vpp_config()
1098
1099 self.vapi.cli("clear trace")
1100 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1101 self.pg0.add_stream(tx)
1102
1103 self.pg_enable_capture(self.pg_interfaces)
1104 self.pg_start()
1105
1106 rx = self.pg0.get_capture()
1107 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1108 [VppMplsLabel(44, ttl=32),
1109 VppMplsLabel(46, ttl=23)])
1110
1111 #
1112 # add a labelled route through the new tunnel
1113 #
1114 route_10_0_0_4 = VppIpRoute(
1115 self, "10.0.0.4", 32,
1116 [VppRoutePath("0.0.0.0",
1117 mpls_tun._sw_if_index,
1118 labels=[VppMplsLabel(33, ttl=47)])])
1119 route_10_0_0_4.add_vpp_config()
1120
1121 self.vapi.cli("clear trace")
1122 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1123 self.pg0.add_stream(tx)
1124
1125 self.pg_enable_capture(self.pg_interfaces)
1126 self.pg_start()
1127
1128 rx = self.pg0.get_capture()
1129 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1130 [VppMplsLabel(44, ttl=32),
1131 VppMplsLabel(46, ttl=47),
1132 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001133
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001134 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001135 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001136
Neale Ranns397228d2021-10-21 12:02:53 +00001137 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001138 mpls_tun = VppMPLSTunnelInterface(
1139 self,
1140 [VppRoutePath(self.pg0.remote_ip4,
1141 self.pg0.sw_if_index,
1142 labels=[VppMplsLabel(44, ttl=32),
1143 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1144 mpls_tun.add_vpp_config()
1145 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001146 for ii in range(100):
1147 mpls_tun = VppMPLSTunnelInterface(
1148 self,
1149 [VppRoutePath(self.pg0.remote_ip4,
1150 self.pg0.sw_if_index,
1151 labels=[VppMplsLabel(44, ttl=32),
1152 VppMplsLabel(46, MplsLspMode.UNIFORM)])],
1153 is_l2=1)
1154 mpls_tun.add_vpp_config()
1155 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001156
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001157 def test_v4_exp_null(self):
1158 """ MPLS V4 Explicit NULL test """
1159
1160 #
1161 # The first test case has an MPLS TTL of 0
1162 # all packet should be dropped
1163 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001164 tx = self.create_stream_labelled_ip4(self.pg0,
1165 [VppMplsLabel(0, ttl=0)])
1166 self.send_and_assert_no_replies(self.pg0, tx,
1167 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001168
1169 #
1170 # a stream with a non-zero MPLS TTL
1171 # PG0 is in the default table
1172 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001173 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1174 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001175 self.verify_capture_ip4(self.pg0, rx, tx)
1176
1177 #
1178 # a stream with a non-zero MPLS TTL
1179 # PG1 is in table 1
1180 # we are ensuring the post-pop lookup occurs in the VRF table
1181 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001182 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1183 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1184 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001185
1186 def test_v6_exp_null(self):
1187 """ MPLS V6 Explicit NULL test """
1188
1189 #
1190 # a stream with a non-zero MPLS TTL
1191 # PG0 is in the default table
1192 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001193 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1194 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001195 self.verify_capture_ip6(self.pg0, rx, tx)
1196
1197 #
1198 # a stream with a non-zero MPLS TTL
1199 # PG1 is in table 1
1200 # we are ensuring the post-pop lookup occurs in the VRF table
1201 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001202 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1203 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001204 self.verify_capture_ip6(self.pg0, rx, tx)
1205
Neale Rannscb630ff2016-12-14 13:31:29 +01001206 def test_deag(self):
1207 """ MPLS Deagg """
1208
1209 #
1210 # A de-agg route - next-hop lookup in default table
1211 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001212 route_34_eos = VppMplsRoute(self, 34, 1,
1213 [VppRoutePath("0.0.0.0",
1214 0xffffffff,
1215 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001216 route_34_eos.add_vpp_config()
1217
1218 #
1219 # ping an interface in the default table
1220 # PG0 is in the default table
1221 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001222 tx = self.create_stream_labelled_ip4(self.pg0,
1223 [VppMplsLabel(34)],
1224 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001225 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001226 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001227 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1228
1229 #
1230 # A de-agg route - next-hop lookup in non-default table
1231 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001232 route_35_eos = VppMplsRoute(self, 35, 1,
1233 [VppRoutePath("0.0.0.0",
1234 0xffffffff,
1235 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001236 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001237 route_356_eos = VppMplsRoute(
1238 self, 356, 1,
1239 [VppRoutePath("0::0",
1240 0xffffffff,
1241 nh_table_id=1)],
1242 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
1243 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001244
1245 #
1246 # ping an interface in the non-default table
1247 # PG0 is in the default table. packet arrive labelled in the
1248 # default table and egress unlabelled in the non-default
1249 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001250 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001251 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1252 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001253 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001254 tx = self.create_stream_labelled_ip6(
1255 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1)
1256 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1257 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001258
Neale Ranns6af1c042017-05-26 03:48:53 -07001259 #
1260 # Double pop
1261 #
1262 route_36_neos = VppMplsRoute(self, 36, 0,
1263 [VppRoutePath("0.0.0.0",
1264 0xffffffff)])
1265 route_36_neos.add_vpp_config()
1266
Neale Ranns31ed7442018-02-23 05:29:09 -08001267 tx = self.create_stream_labelled_ip4(self.pg0,
1268 [VppMplsLabel(36),
1269 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001270 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001271 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001272 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1273
1274 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001275 route_35_eos.remove_vpp_config()
1276 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001277
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001278 def test_interface_rx(self):
1279 """ MPLS Interface Receive """
1280
1281 #
1282 # Add a non-recursive route that will forward the traffic
1283 # post-interface-rx
1284 #
1285 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1286 table_id=1,
1287 paths=[VppRoutePath(self.pg1.remote_ip4,
1288 self.pg1.sw_if_index)])
1289 route_10_0_0_1.add_vpp_config()
1290
1291 #
1292 # An interface receive label that maps traffic to RX on interface
1293 # pg1
1294 # by injecting the packet in on pg0, which is in table 0
1295 # doing an interface-rx on pg1 and matching a route in table 1
1296 # if the packet egresses, then we must have swapped to pg1
1297 # so as to have matched the route in table 1
1298 #
Neale Ranns097fa662018-05-01 05:17:55 -07001299 route_34_eos = VppMplsRoute(
1300 self, 34, 1,
1301 [VppRoutePath("0.0.0.0",
1302 self.pg1.sw_if_index,
1303 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001304 route_34_eos.add_vpp_config()
1305
1306 #
1307 # ping an interface in the default table
1308 # PG0 is in the default table
1309 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001310 tx = self.create_stream_labelled_ip4(self.pg0,
1311 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001312 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001313 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001314 self.verify_capture_ip4(self.pg1, rx, tx)
1315
1316 def test_mcast_mid_point(self):
1317 """ MPLS Multicast Mid Point """
1318
1319 #
1320 # Add a non-recursive route that will forward the traffic
1321 # post-interface-rx
1322 #
1323 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1324 table_id=1,
1325 paths=[VppRoutePath(self.pg1.remote_ip4,
1326 self.pg1.sw_if_index)])
1327 route_10_0_0_1.add_vpp_config()
1328
1329 #
1330 # Add a mcast entry that replicate to pg2 and pg3
1331 # and replicate to a interface-rx (like a bud node would)
1332 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001333 route_3400_eos = VppMplsRoute(
1334 self, 3400, 1,
1335 [VppRoutePath(self.pg2.remote_ip4,
1336 self.pg2.sw_if_index,
1337 labels=[VppMplsLabel(3401)]),
1338 VppRoutePath(self.pg3.remote_ip4,
1339 self.pg3.sw_if_index,
1340 labels=[VppMplsLabel(3402)]),
1341 VppRoutePath("0.0.0.0",
1342 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001343 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001344 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001345 route_3400_eos.add_vpp_config()
1346
1347 #
1348 # ping an interface in the default table
1349 # PG0 is in the default table
1350 #
1351 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001352 tx = self.create_stream_labelled_ip4(self.pg0,
1353 [VppMplsLabel(3400, ttl=64)],
1354 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001355 dst_ip="10.0.0.1")
1356 self.pg0.add_stream(tx)
1357
1358 self.pg_enable_capture(self.pg_interfaces)
1359 self.pg_start()
1360
1361 rx = self.pg1.get_capture(257)
1362 self.verify_capture_ip4(self.pg1, rx, tx)
1363
1364 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001365 self.verify_capture_labelled(self.pg2, rx, tx,
1366 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001367 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001368 self.verify_capture_labelled(self.pg3, rx, tx,
1369 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001370
1371 def test_mcast_head(self):
1372 """ MPLS Multicast Head-end """
1373
Neale Ranns990f6942020-10-20 07:20:17 +00001374 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1375 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1376
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001377 #
1378 # Create a multicast tunnel with two replications
1379 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001380 mpls_tun = VppMPLSTunnelInterface(
1381 self,
1382 [VppRoutePath(self.pg2.remote_ip4,
1383 self.pg2.sw_if_index,
1384 labels=[VppMplsLabel(42)]),
1385 VppRoutePath(self.pg3.remote_ip4,
1386 self.pg3.sw_if_index,
1387 labels=[VppMplsLabel(43)])],
1388 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001389 mpls_tun.add_vpp_config()
1390 mpls_tun.admin_up()
1391
1392 #
1393 # add an unlabelled route through the new tunnel
1394 #
1395 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1396 [VppRoutePath("0.0.0.0",
1397 mpls_tun._sw_if_index)])
1398 route_10_0_0_3.add_vpp_config()
1399
1400 self.vapi.cli("clear trace")
1401 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1402 self.pg0.add_stream(tx)
1403
1404 self.pg_enable_capture(self.pg_interfaces)
1405 self.pg_start()
1406
1407 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001408 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001409 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001410 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001411
1412 #
1413 # An an IP multicast route via the tunnel
1414 # A (*,G).
1415 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1416 #
1417 route_232_1_1_1 = VppIpMRoute(
1418 self,
1419 "0.0.0.0",
1420 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001421 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001422 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001423 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001424 VppMRoutePath(mpls_tun._sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001425 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001426 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001427 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001428
1429 self.vapi.cli("clear trace")
1430 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1431 self.pg0.add_stream(tx)
1432
1433 self.pg_enable_capture(self.pg_interfaces)
1434 self.pg_start()
1435
1436 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001437 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001438 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001439 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001440
Neale Ranns31426c62017-05-24 10:32:58 -07001441 def test_mcast_ip4_tail(self):
1442 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001443
Neale Ranns990f6942020-10-20 07:20:17 +00001444 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1445 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1446
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001447 #
1448 # Add a multicast route that will forward the traffic
1449 # post-disposition
1450 #
1451 route_232_1_1_1 = VppIpMRoute(
1452 self,
1453 "0.0.0.0",
1454 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001455 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001456 table_id=1,
1457 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001458 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001459 route_232_1_1_1.add_vpp_config()
1460
1461 #
1462 # An interface receive label that maps traffic to RX on interface
1463 # pg1
1464 # by injecting the packet in on pg0, which is in table 0
1465 # doing an rpf-id and matching a route in table 1
1466 # if the packet egresses, then we must have matched the route in
1467 # table 1
1468 #
Neale Ranns097fa662018-05-01 05:17:55 -07001469 route_34_eos = VppMplsRoute(
1470 self, 34, 1,
1471 [VppRoutePath("0.0.0.0",
1472 0xffffffff,
1473 nh_table_id=1,
1474 rpf_id=55)],
1475 is_multicast=1,
1476 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001477
1478 route_34_eos.add_vpp_config()
1479
1480 #
1481 # Drop due to interface lookup miss
1482 #
1483 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001484 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001485 dst_ip="232.1.1.1", n=1)
1486 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1487
1488 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001489 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001490 #
1491 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001492 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001493
Neale Ranns31ed7442018-02-23 05:29:09 -08001494 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1495 dst_ip="232.1.1.1")
1496 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001497 self.verify_capture_ip4(self.pg1, rx, tx)
1498
1499 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001500 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001501 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001502 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001503 dst_ip="232.1.1.1", n=65,
1504 chksum=1)
1505 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1506
1507 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001508 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001509 #
1510 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001511 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001512 dst_ip="232.1.1.1")
1513 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1514
Neale Ranns31426c62017-05-24 10:32:58 -07001515 def test_mcast_ip6_tail(self):
1516 """ MPLS IPv6 Multicast Tail """
1517
Neale Ranns990f6942020-10-20 07:20:17 +00001518 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1519 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1520
Neale Ranns31426c62017-05-24 10:32:58 -07001521 #
1522 # Add a multicast route that will forward the traffic
1523 # post-disposition
1524 #
1525 route_ff = VppIpMRoute(
1526 self,
1527 "::",
1528 "ff01::1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001529 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001530 table_id=1,
1531 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001532 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001533 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001534 route_ff.add_vpp_config()
1535
1536 #
1537 # An interface receive label that maps traffic to RX on interface
1538 # pg1
1539 # by injecting the packet in on pg0, which is in table 0
1540 # doing an rpf-id and matching a route in table 1
1541 # if the packet egresses, then we must have matched the route in
1542 # table 1
1543 #
1544 route_34_eos = VppMplsRoute(
1545 self, 34, 1,
1546 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001547 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001548 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001549 rpf_id=55)],
1550 is_multicast=1,
1551 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001552
1553 route_34_eos.add_vpp_config()
1554
1555 #
1556 # Drop due to interface lookup miss
1557 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001558 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001559 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001560 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001561
1562 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001563 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001564 #
1565 route_ff.update_rpf_id(55)
1566
Neale Ranns31ed7442018-02-23 05:29:09 -08001567 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001568 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001569 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001570 self.verify_capture_ip6(self.pg1, rx, tx)
1571
1572 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001573 # disposed packets have hop-limit = 1
1574 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001575 tx = self.create_stream_labelled_ip6(self.pg0,
1576 [VppMplsLabel(34)],
1577 dst_ip="ff01::1",
1578 hlim=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001579 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001580 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001581
1582 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001583 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001584 #
1585 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001586 tx = self.create_stream_labelled_ip6(self.pg0,
1587 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001588 dst_ip="ff01::1")
1589 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1590
Neale Rannsd5d7b962019-08-04 03:30:56 -07001591 def test_6pe(self):
1592 """ MPLS 6PE """
1593
1594 #
1595 # Add a non-recursive route with a single out label
1596 #
1597 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1598 [VppRoutePath(self.pg0.remote_ip4,
1599 self.pg0.sw_if_index,
1600 labels=[VppMplsLabel(45)])])
1601 route_10_0_0_1.add_vpp_config()
1602
1603 # bind a local label to the route
1604 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1605 binding.add_vpp_config()
1606
1607 #
1608 # a labelled v6 route that resolves through the v4
1609 #
1610 route_2001_3 = VppIpRoute(
1611 self, "2001::3", 128,
1612 [VppRoutePath("10.0.0.1",
1613 INVALID_INDEX,
1614 labels=[VppMplsLabel(32)])])
1615 route_2001_3.add_vpp_config()
1616
1617 tx = self.create_stream_ip6(self.pg0, "2001::3")
1618 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1619
1620 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1621 [VppMplsLabel(45),
1622 VppMplsLabel(32)])
1623
1624 #
1625 # and a v4 recursive via the v6
1626 #
1627 route_20_3 = VppIpRoute(
1628 self, "20.0.0.3", 32,
1629 [VppRoutePath("2001::3",
1630 INVALID_INDEX,
1631 labels=[VppMplsLabel(99)])])
1632 route_20_3.add_vpp_config()
1633
1634 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1635 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1636
1637 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1638 [VppMplsLabel(45),
1639 VppMplsLabel(32),
1640 VppMplsLabel(99)])
1641
Neale Ranns53962fb2021-12-20 18:18:42 +00001642 def test_attached(self):
1643 """ Attach Routes with Local Label """
1644
1645 #
1646 # test that if a local label is associated with an attached/connected
1647 # prefix, that we can reach hosts in the prefix.
1648 #
1649 binding = VppMplsIpBind(self, 44,
1650 self.pg0._local_ip4_subnet,
1651 self.pg0.local_ip4_prefix_len)
1652 binding.add_vpp_config()
1653
1654 tx = (Ether(src=self.pg1.remote_mac,
1655 dst=self.pg1.local_mac) /
1656 MPLS(label=44, ttl=64) /
1657 IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
1658 UDP(sport=1234, dport=1234) /
1659 Raw(b'\xa5' * 100))
1660 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
1661 for rx in rxs:
1662 # if there's an ARP then the label is linked to the glean
1663 # which is wrong.
1664 self.assertFalse(rx.haslayer(ARP))
1665 # it should be unicasted to the host
1666 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1667 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
1668
Neale Ranns180279b2017-03-16 15:49:09 -04001669
1670class TestMPLSDisabled(VppTestCase):
1671 """ MPLS disabled """
1672
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001673 @classmethod
1674 def setUpClass(cls):
1675 super(TestMPLSDisabled, cls).setUpClass()
1676
1677 @classmethod
1678 def tearDownClass(cls):
1679 super(TestMPLSDisabled, cls).tearDownClass()
1680
Neale Ranns180279b2017-03-16 15:49:09 -04001681 def setUp(self):
1682 super(TestMPLSDisabled, self).setUp()
1683
1684 # create 2 pg interfaces
1685 self.create_pg_interfaces(range(2))
1686
Neale Ranns15002542017-09-10 04:39:11 -07001687 self.tbl = VppMplsTable(self, 0)
1688 self.tbl.add_vpp_config()
1689
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001690 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001691 self.pg0.admin_up()
1692 self.pg0.config_ip4()
1693 self.pg0.resolve_arp()
1694 self.pg0.enable_mpls()
1695
1696 # PG 1 is not MPLS enabled
1697 self.pg1.admin_up()
1698
1699 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001700 for i in self.pg_interfaces:
1701 i.unconfig_ip4()
1702 i.admin_down()
1703
Neale Ranns15002542017-09-10 04:39:11 -07001704 self.pg0.disable_mpls()
1705 super(TestMPLSDisabled, self).tearDown()
1706
Neale Ranns180279b2017-03-16 15:49:09 -04001707 def test_mpls_disabled(self):
1708 """ MPLS Disabled """
1709
Neale Rannsde0b3b52021-06-15 12:43:12 +00001710 self.logger.info(self.vapi.cli("show mpls interface"))
1711 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1712 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1713
Neale Ranns180279b2017-03-16 15:49:09 -04001714 tx = (Ether(src=self.pg1.remote_mac,
1715 dst=self.pg1.local_mac) /
1716 MPLS(label=32, ttl=64) /
1717 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1718 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001719 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001720
1721 #
1722 # A simple MPLS xconnect - eos label in label out
1723 #
1724 route_32_eos = VppMplsRoute(self, 32, 1,
1725 [VppRoutePath(self.pg0.remote_ip4,
1726 self.pg0.sw_if_index,
1727 labels=[33])])
1728 route_32_eos.add_vpp_config()
1729
1730 #
1731 # PG1 does not forward IP traffic
1732 #
1733 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1734
1735 #
1736 # MPLS enable PG1
1737 #
1738 self.pg1.enable_mpls()
1739
Neale Rannsde0b3b52021-06-15 12:43:12 +00001740 self.logger.info(self.vapi.cli("show mpls interface"))
1741 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1742
Neale Ranns180279b2017-03-16 15:49:09 -04001743 #
1744 # Now we get packets through
1745 #
1746 self.pg1.add_stream(tx)
1747 self.pg_enable_capture(self.pg_interfaces)
1748 self.pg_start()
1749
1750 rx = self.pg0.get_capture(1)
1751
1752 #
1753 # Disable PG1
1754 #
1755 self.pg1.disable_mpls()
1756
1757 #
1758 # PG1 does not forward IP traffic
1759 #
1760 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1761 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1762
1763
Neale Rannsf12a83f2017-04-18 09:09:40 -07001764class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001765 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001766
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001767 @classmethod
1768 def setUpClass(cls):
1769 super(TestMPLSPIC, cls).setUpClass()
1770
1771 @classmethod
1772 def tearDownClass(cls):
1773 super(TestMPLSPIC, cls).tearDownClass()
1774
Neale Rannsf12a83f2017-04-18 09:09:40 -07001775 def setUp(self):
1776 super(TestMPLSPIC, self).setUp()
1777
1778 # create 2 pg interfaces
1779 self.create_pg_interfaces(range(4))
1780
Neale Ranns15002542017-09-10 04:39:11 -07001781 mpls_tbl = VppMplsTable(self, 0)
1782 mpls_tbl.add_vpp_config()
1783 tbl4 = VppIpTable(self, 1)
1784 tbl4.add_vpp_config()
1785 tbl6 = VppIpTable(self, 1, is_ip6=1)
1786 tbl6.add_vpp_config()
1787
Neale Rannsf12a83f2017-04-18 09:09:40 -07001788 # core links
1789 self.pg0.admin_up()
1790 self.pg0.config_ip4()
1791 self.pg0.resolve_arp()
1792 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001793
Neale Rannsf12a83f2017-04-18 09:09:40 -07001794 self.pg1.admin_up()
1795 self.pg1.config_ip4()
1796 self.pg1.resolve_arp()
1797 self.pg1.enable_mpls()
1798
1799 # VRF (customer facing) link
1800 self.pg2.admin_up()
1801 self.pg2.set_table_ip4(1)
1802 self.pg2.config_ip4()
1803 self.pg2.resolve_arp()
1804 self.pg2.set_table_ip6(1)
1805 self.pg2.config_ip6()
1806 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001807
Neale Rannsf12a83f2017-04-18 09:09:40 -07001808 self.pg3.admin_up()
1809 self.pg3.set_table_ip4(1)
1810 self.pg3.config_ip4()
1811 self.pg3.resolve_arp()
1812 self.pg3.set_table_ip6(1)
1813 self.pg3.config_ip6()
1814 self.pg3.resolve_ndp()
1815
1816 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001817 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001818 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001819 for i in self.pg_interfaces:
1820 i.unconfig_ip4()
1821 i.unconfig_ip6()
1822 i.set_table_ip4(0)
1823 i.set_table_ip6(0)
1824 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001825 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001826
1827 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001828 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001829
1830 1) setup many iBGP VPN routes via a pair of iBGP peers.
1831 2) Check EMCP forwarding to these peers
1832 3) withdraw the IGP route to one of these peers.
1833 4) check forwarding continues to the remaining peer
1834 """
1835
1836 #
1837 # IGP+LDP core routes
1838 #
1839 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1840 [VppRoutePath(self.pg0.remote_ip4,
1841 self.pg0.sw_if_index,
1842 labels=[45])])
1843 core_10_0_0_45.add_vpp_config()
1844
1845 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1846 [VppRoutePath(self.pg1.remote_ip4,
1847 self.pg1.sw_if_index,
1848 labels=[46])])
1849 core_10_0_0_46.add_vpp_config()
1850
1851 #
1852 # Lot's of VPN routes. We need more the 64 so VPP will build
1853 # the fast convergence indirection
1854 #
1855 vpn_routes = []
1856 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001857 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001858 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001859 vpn_routes.append(VppIpRoute(
1860 self, dst, 32,
1861 [VppRoutePath(
1862 "10.0.0.45",
1863 0xffffffff,
1864 labels=[145],
1865 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1866 VppRoutePath(
1867 "10.0.0.46",
1868 0xffffffff,
1869 labels=[146],
1870 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1871 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001872 vpn_routes[ii].add_vpp_config()
1873
1874 pkts.append(Ether(dst=self.pg2.local_mac,
1875 src=self.pg2.remote_mac) /
1876 IP(src=self.pg2.remote_ip4, dst=dst) /
1877 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001878 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001879
1880 #
1881 # Send the packet stream (one pkt to each VPN route)
1882 # - expect a 50-50 split of the traffic
1883 #
1884 self.pg2.add_stream(pkts)
1885 self.pg_enable_capture(self.pg_interfaces)
1886 self.pg_start()
1887
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001888 rx0 = self.pg0._get_capture(NUM_PKTS)
1889 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001890
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001891 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001892 # with the split ratio, just as long as neither is 0
1893 self.assertNotEqual(0, len(rx0))
1894 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001895 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1896 "Expected all (%s) packets across both ECMP paths. "
1897 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001898
1899 #
1900 # use a test CLI command to stop the FIB walk process, this
1901 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001902 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001903 #
1904 self.vapi.ppcli("test fib-walk-process disable")
1905
1906 #
1907 # Withdraw one of the IGP routes
1908 #
1909 core_10_0_0_46.remove_vpp_config()
1910
1911 #
1912 # now all packets should be forwarded through the remaining peer
1913 #
1914 self.vapi.ppcli("clear trace")
1915 self.pg2.add_stream(pkts)
1916 self.pg_enable_capture(self.pg_interfaces)
1917 self.pg_start()
1918
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001919 rx0 = self.pg0.get_capture(NUM_PKTS)
1920 self.assertEqual(len(pkts), len(rx0),
1921 "Expected all (%s) packets across single path. "
1922 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001923
1924 #
1925 # enable the FIB walk process to converge the FIB
1926 #
1927 self.vapi.ppcli("test fib-walk-process enable")
1928
1929 #
1930 # packets should still be forwarded through the remaining peer
1931 #
1932 self.pg2.add_stream(pkts)
1933 self.pg_enable_capture(self.pg_interfaces)
1934 self.pg_start()
1935
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001936 rx0 = self.pg0.get_capture(NUM_PKTS)
1937 self.assertEqual(len(pkts), len(rx0),
1938 "Expected all (%s) packets across single path. "
1939 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001940
1941 #
1942 # Add the IGP route back and we return to load-balancing
1943 #
1944 core_10_0_0_46.add_vpp_config()
1945
1946 self.pg2.add_stream(pkts)
1947 self.pg_enable_capture(self.pg_interfaces)
1948 self.pg_start()
1949
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001950 rx0 = self.pg0._get_capture(NUM_PKTS)
1951 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001952 self.assertNotEqual(0, len(rx0))
1953 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001954 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1955 "Expected all (%s) packets across both ECMP paths. "
1956 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001957
1958 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001959 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001960
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001961 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001962 2) Check EMCP forwarding to these peers
1963 3) withdraw one eBGP path - expect LB across remaining eBGP
1964 """
1965
1966 #
1967 # Lot's of VPN routes. We need more the 64 so VPP will build
1968 # the fast convergence indirection
1969 #
1970 vpn_routes = []
1971 vpn_bindings = []
1972 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001973 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001974 dst = "192.168.1.%d" % ii
1975 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001976 vpn_routes.append(VppIpRoute(
1977 self, dst, 32,
1978 [VppRoutePath(
1979 self.pg2.remote_ip4,
1980 0xffffffff,
1981 nh_table_id=1,
1982 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1983 VppRoutePath(
1984 self.pg3.remote_ip4,
1985 0xffffffff,
1986 nh_table_id=1,
1987 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1988 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001989 vpn_routes[ii].add_vpp_config()
1990
1991 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1992 ip_table_id=1))
1993 vpn_bindings[ii].add_vpp_config()
1994
1995 pkts.append(Ether(dst=self.pg0.local_mac,
1996 src=self.pg0.remote_mac) /
1997 MPLS(label=local_label, ttl=64) /
1998 IP(src=self.pg0.remote_ip4, dst=dst) /
1999 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002000 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002001
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002002 #
2003 # Send the packet stream (one pkt to each VPN route)
2004 # - expect a 50-50 split of the traffic
2005 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002006 self.pg0.add_stream(pkts)
2007 self.pg_enable_capture(self.pg_interfaces)
2008 self.pg_start()
2009
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002010 rx0 = self.pg2._get_capture(NUM_PKTS)
2011 rx1 = self.pg3._get_capture(NUM_PKTS)
2012
2013 # not testing the LB hashing algorithm so we're not concerned
2014 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002015 self.assertNotEqual(0, len(rx0))
2016 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002017 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2018 "Expected all (%s) packets across both ECMP paths. "
2019 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002020
2021 #
2022 # use a test CLI command to stop the FIB walk process, this
2023 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002024 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002025 #
2026 self.vapi.ppcli("test fib-walk-process disable")
2027
2028 #
2029 # withdraw the connected prefix on the interface.
2030 #
2031 self.pg2.unconfig_ip4()
2032
2033 #
2034 # now all packets should be forwarded through the remaining peer
2035 #
2036 self.pg0.add_stream(pkts)
2037 self.pg_enable_capture(self.pg_interfaces)
2038 self.pg_start()
2039
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002040 rx0 = self.pg3.get_capture(NUM_PKTS)
2041 self.assertEqual(len(pkts), len(rx0),
2042 "Expected all (%s) packets across single path. "
2043 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002044
2045 #
2046 # enable the FIB walk process to converge the FIB
2047 #
2048 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002049
2050 #
2051 # packets should still be forwarded through the remaining peer
2052 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002053 self.pg0.add_stream(pkts)
2054 self.pg_enable_capture(self.pg_interfaces)
2055 self.pg_start()
2056
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002057 rx0 = self.pg3.get_capture(NUM_PKTS)
2058 self.assertEqual(len(pkts), len(rx0),
2059 "Expected all (%s) packets across single path. "
2060 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002061
2062 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002063 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002064 #
2065 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002066 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002067
2068 self.pg0.add_stream(pkts)
2069 self.pg_enable_capture(self.pg_interfaces)
2070 self.pg_start()
2071
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002072 rx0 = self.pg2._get_capture(NUM_PKTS)
2073 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002074 self.assertNotEqual(0, len(rx0))
2075 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002076 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2077 "Expected all (%s) packets across both ECMP paths. "
2078 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002079
2080 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002081 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002082
2083 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2084 2) Check EMCP forwarding to these peers
2085 3) withdraw one eBGP path - expect LB across remaining eBGP
2086 """
2087
2088 #
2089 # Lot's of VPN routes. We need more the 64 so VPP will build
2090 # the fast convergence indirection
2091 #
2092 vpn_routes = []
2093 vpn_bindings = []
2094 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002095 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002096 dst = "3000::%d" % ii
2097 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07002098 vpn_routes.append(VppIpRoute(
2099 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002100 [VppRoutePath(
2101 self.pg2.remote_ip6,
2102 0xffffffff,
2103 nh_table_id=1,
2104 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
2105 VppRoutePath(
2106 self.pg3.remote_ip6,
2107 0xffffffff,
2108 nh_table_id=1,
2109 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
2110 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002111 vpn_routes[ii].add_vpp_config()
2112
2113 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002114 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002115 vpn_bindings[ii].add_vpp_config()
2116
2117 pkts.append(Ether(dst=self.pg0.local_mac,
2118 src=self.pg0.remote_mac) /
2119 MPLS(label=local_label, ttl=64) /
2120 IPv6(src=self.pg0.remote_ip6, dst=dst) /
2121 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002122 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002123 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002124
2125 self.pg0.add_stream(pkts)
2126 self.pg_enable_capture(self.pg_interfaces)
2127 self.pg_start()
2128
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002129 rx0 = self.pg2._get_capture(NUM_PKTS)
2130 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002131 self.assertNotEqual(0, len(rx0))
2132 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002133 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2134 "Expected all (%s) packets across both ECMP paths. "
2135 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002136
2137 #
2138 # use a test CLI command to stop the FIB walk process, this
2139 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002140 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002141 #
2142 self.vapi.ppcli("test fib-walk-process disable")
2143
2144 #
2145 # withdraw the connected prefix on the interface.
2146 # and shutdown the interface so the ND cache is flushed.
2147 #
2148 self.pg2.unconfig_ip6()
2149 self.pg2.admin_down()
2150
2151 #
2152 # now all packets should be forwarded through the remaining peer
2153 #
2154 self.pg0.add_stream(pkts)
2155 self.pg_enable_capture(self.pg_interfaces)
2156 self.pg_start()
2157
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002158 rx0 = self.pg3.get_capture(NUM_PKTS)
2159 self.assertEqual(len(pkts), len(rx0),
2160 "Expected all (%s) packets across single path. "
2161 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002162
2163 #
2164 # enable the FIB walk process to converge the FIB
2165 #
2166 self.vapi.ppcli("test fib-walk-process enable")
2167 self.pg0.add_stream(pkts)
2168 self.pg_enable_capture(self.pg_interfaces)
2169 self.pg_start()
2170
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002171 rx0 = self.pg3.get_capture(NUM_PKTS)
2172 self.assertEqual(len(pkts), len(rx0),
2173 "Expected all (%s) packets across single path. "
2174 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002175
2176 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002177 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002178 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002179 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002180 self.pg2.admin_up()
2181 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002182 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002183
2184 self.pg0.add_stream(pkts)
2185 self.pg_enable_capture(self.pg_interfaces)
2186 self.pg_start()
2187
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002188 rx0 = self.pg2._get_capture(NUM_PKTS)
2189 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002190 self.assertNotEqual(0, len(rx0))
2191 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002192 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2193 "Expected all (%s) packets across both ECMP paths. "
2194 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002195
2196
Neale Rannsda78f952017-05-24 09:15:43 -07002197class TestMPLSL2(VppTestCase):
2198 """ MPLS-L2 """
2199
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002200 @classmethod
2201 def setUpClass(cls):
2202 super(TestMPLSL2, cls).setUpClass()
2203
2204 @classmethod
2205 def tearDownClass(cls):
2206 super(TestMPLSL2, cls).tearDownClass()
2207
Neale Rannsda78f952017-05-24 09:15:43 -07002208 def setUp(self):
2209 super(TestMPLSL2, self).setUp()
2210
2211 # create 2 pg interfaces
2212 self.create_pg_interfaces(range(2))
2213
Neale Ranns15002542017-09-10 04:39:11 -07002214 # create the default MPLS table
2215 self.tables = []
2216 tbl = VppMplsTable(self, 0)
2217 tbl.add_vpp_config()
2218 self.tables.append(tbl)
2219
Neale Ranns1976f362019-11-06 13:13:01 +00002220 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002221 self.pg0.admin_up()
2222 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002223 self.pg0.enable_mpls()
2224
Neale Ranns15002542017-09-10 04:39:11 -07002225 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002226 for i in self.pg_interfaces[1:]:
2227 i.admin_up()
2228
2229 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002230 for i in self.pg_interfaces[1:]:
2231 i.admin_down()
2232
2233 self.pg0.disable_mpls()
2234 self.pg0.unconfig_ip4()
2235 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002236 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002237
Neale Ranns31ed7442018-02-23 05:29:09 -08002238 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002239 capture = verify_filter(capture, sent)
2240
2241 self.assertEqual(len(capture), len(sent))
2242
2243 for i in range(len(capture)):
2244 tx = sent[i]
2245 rx = capture[i]
2246
2247 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002248 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002249
2250 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002251 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002252
2253 self.assertEqual(rx_eth.src, tx_eth.src)
2254 self.assertEqual(rx_eth.dst, tx_eth.dst)
2255
Neale Ranns1976f362019-11-06 13:13:01 +00002256 def verify_arp_req(self, rx, smac, sip, dip):
2257 ether = rx[Ether]
2258 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2259 self.assertEqual(ether.src, smac)
2260
2261 arp = rx[ARP]
2262 self.assertEqual(arp.hwtype, 1)
2263 self.assertEqual(arp.ptype, 0x800)
2264 self.assertEqual(arp.hwlen, 6)
2265 self.assertEqual(arp.plen, 4)
2266 self.assertEqual(arp.op, ARP.who_has)
2267 self.assertEqual(arp.hwsrc, smac)
2268 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2269 self.assertEqual(arp.psrc, sip)
2270 self.assertEqual(arp.pdst, dip)
2271
Neale Rannsda78f952017-05-24 09:15:43 -07002272 def test_vpws(self):
2273 """ Virtual Private Wire Service """
2274
2275 #
2276 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002277 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2278 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002279 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002280 mpls_tun_1 = VppMPLSTunnelInterface(
2281 self,
2282 [VppRoutePath(self.pg0.remote_ip4,
2283 self.pg0.sw_if_index,
2284 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2285 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002286 mpls_tun_1.add_vpp_config()
2287 mpls_tun_1.admin_up()
2288
2289 #
2290 # Create a label entry to for 55 that does L2 input to the tunnel
2291 #
2292 route_55_eos = VppMplsRoute(
2293 self, 55, 1,
2294 [VppRoutePath("0.0.0.0",
2295 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002296 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2297 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2298 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002299 route_55_eos.add_vpp_config()
2300
2301 #
2302 # Cross-connect the tunnel with one of the customers L2 interfaces
2303 #
2304 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2305 mpls_tun_1.sw_if_index,
2306 enable=1)
2307 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2308 self.pg1.sw_if_index,
2309 enable=1)
2310
2311 #
2312 # inject a packet from the core
2313 #
2314 pcore = (Ether(dst=self.pg0.local_mac,
2315 src=self.pg0.remote_mac) /
2316 MPLS(label=55, ttl=64) /
2317 Ether(dst="00:00:de:ad:ba:be",
2318 src="00:00:de:ad:be:ef") /
2319 IP(src="10.10.10.10", dst="11.11.11.11") /
2320 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002321 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002322
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002323 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002324 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2325 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002326
Neale Ranns31ed7442018-02-23 05:29:09 -08002327 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2328 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002329
2330 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002331 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002332 # there's no resolved ARP entry so the first packet we see should be
2333 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002334 #
Neale Ranns1976f362019-11-06 13:13:01 +00002335 tx1 = pcore[MPLS].payload
2336 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2337
2338 self.verify_arp_req(rx1[0],
2339 self.pg0.local_mac,
2340 self.pg0.local_ip4,
2341 self.pg0.remote_ip4)
2342
2343 #
2344 # resolve the ARP entries and send again
2345 #
2346 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002347 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002348 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002349
Neale Ranns31ed7442018-02-23 05:29:09 -08002350 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002351
2352 def test_vpls(self):
2353 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002354
2355 # we skipped this in the setup
2356 self.pg0.resolve_arp()
2357
Neale Rannsda78f952017-05-24 09:15:43 -07002358 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002359 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002360 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002361 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002362 self,
2363 [VppRoutePath(self.pg0.remote_ip4,
2364 self.pg0.sw_if_index,
2365 labels=[VppMplsLabel(42)])],
2366 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002367 mpls_tun1.add_vpp_config()
2368 mpls_tun1.admin_up()
2369
2370 mpls_tun2 = VppMPLSTunnelInterface(
2371 self,
2372 [VppRoutePath(self.pg0.remote_ip4,
2373 self.pg0.sw_if_index,
2374 labels=[VppMplsLabel(43)])],
2375 is_l2=1)
2376 mpls_tun2.add_vpp_config()
2377 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002378
2379 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002380 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2381 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002382 #
2383 route_55_eos = VppMplsRoute(
2384 self, 55, 1,
2385 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002386 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002387 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2388 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2389 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002390
2391 route_56_eos = VppMplsRoute(
2392 self, 56, 1,
2393 [VppRoutePath("0.0.0.0",
2394 mpls_tun2.sw_if_index,
2395 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2396 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2397 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2398 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2399
2400 # move me
2401 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002402 route_55_eos.add_vpp_config()
2403
Neale Ranns1dbcf302019-07-19 11:44:53 +00002404 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2405
Neale Rannsda78f952017-05-24 09:15:43 -07002406 #
2407 # add to tunnel to the customers bridge-domain
2408 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002409 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002410 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2411 self.vapi.sw_interface_set_l2_bridge(
2412 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002413 self.vapi.sw_interface_set_l2_bridge(
2414 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002415
2416 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002417 # Packet from host on the customer interface to each host
2418 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002419 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002420 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2421 src="00:00:de:ad:be:ef") /
2422 IP(src="10.10.10.10", dst="11.11.11.11") /
2423 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002424 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002425 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2426 src="00:00:de:ad:be:ef") /
2427 IP(src="10.10.10.10", dst="11.11.11.12") /
2428 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002429 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002430 p_core1 = (Ether(dst=self.pg0.local_mac,
2431 src=self.pg0.remote_mac) /
2432 MPLS(label=55, ttl=64) /
2433 Ether(src="00:00:de:ad:ba:b1",
2434 dst="00:00:de:ad:be:ef") /
2435 IP(dst="10.10.10.10", src="11.11.11.11") /
2436 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002437 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002438 p_core2 = (Ether(dst=self.pg0.local_mac,
2439 src=self.pg0.remote_mac) /
2440 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002441 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002442 Ether(src="00:00:de:ad:ba:b2",
2443 dst="00:00:de:ad:be:ef") /
2444 IP(dst="10.10.10.10", src="11.11.11.12") /
2445 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002446 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002447
2448 #
2449 # The BD is learning, so send in one of each packet to learn
2450 #
Neale Rannsda78f952017-05-24 09:15:43 -07002451
Neale Ranns1dbcf302019-07-19 11:44:53 +00002452 # 2 packets due to BD flooding
2453 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2454 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002455
Neale Ranns1dbcf302019-07-19 11:44:53 +00002456 # we've learnt this so expect it be be forwarded not flooded
2457 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2458 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2459 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002460
Neale Ranns1dbcf302019-07-19 11:44:53 +00002461 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2462 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2463 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002464
2465 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002466 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002467 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002468 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2469 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002470 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002471
Neale Ranns1dbcf302019-07-19 11:44:53 +00002472 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2473 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2474 [VppMplsLabel(43)])
2475
2476 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2477 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2478
Neale Rannsda78f952017-05-24 09:15:43 -07002479 #
2480 # remove interfaces from customers bridge-domain
2481 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002482 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002483 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2484 self.vapi.sw_interface_set_l2_bridge(
2485 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002486 self.vapi.sw_interface_set_l2_bridge(
2487 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002488
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002489
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002490if __name__ == '__main__':
2491 unittest.main(testRunner=VppTestRunner)