blob: a568f849aed7c84710a85fd5ca39f3c934713cc6 [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 Rannsfbc633f2022-03-18 13:05:09 +000020from scapy.layers.inet import IP, UDP, ICMP, icmptypes, icmpcodes
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:
Neale Rannsfbc633f2022-03-18 13:05:09 +0000964 self.assertEqual(icmptypes[rx[ICMP].type], "dest-unreach")
965 self.assertEqual(icmpcodes[rx[ICMP].type][rx[ICMP].code],
966 "fragmentation-needed")
967 # the link MTU is 9000, the MPLS over head is 4 bytes
968 self.assertEqual(rx[ICMP].nexthopmtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +0000969
970 self.assertEqual(self.statistics.get_err_counter(
971 "/err/mpls-frag/can't fragment this packet"),
972 len(tx))
973 #
974 # a stream that matches the route for 1000::1/128
975 # PG0 is in the default table
976 #
977 tx = self.create_stream_ip6(self.pg0, "1000::1")
978 for i in range(0, 257):
979 self.extend_packet(tx[i], 10000)
980
981 rxs = self.send_and_expect_some(self.pg0, tx, self.pg0)
982 for rx in rxs:
Neale Rannsfbc633f2022-03-18 13:05:09 +0000983 self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 9000 - 4)
Neale Rannsec5371e2022-03-04 11:45:41 +0000984
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530985 #
986 # cleanup
987 #
988 route_10_0_0_1.remove_vpp_config()
989
Neale Ranns31ed7442018-02-23 05:29:09 -0800990 def test_tunnel_pipe(self):
991 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000992
993 #
Ole Troaneb284a12019-10-09 13:33:19 +0200994 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +0000995 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800996 mpls_tun = VppMPLSTunnelInterface(
997 self,
998 [VppRoutePath(self.pg0.remote_ip4,
999 self.pg0.sw_if_index,
1000 labels=[VppMplsLabel(44),
1001 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001002 mpls_tun.add_vpp_config()
1003 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +00001004
1005 #
1006 # add an unlabelled route through the new tunnel
1007 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001008 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1009 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001010 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -08001011 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +00001012
1013 self.vapi.cli("clear trace")
1014 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1015 self.pg0.add_stream(tx)
1016
1017 self.pg_enable_capture(self.pg_interfaces)
1018 self.pg_start()
1019
1020 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -08001021 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1022 [VppMplsLabel(44),
1023 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001024
Neale Ranns8c4611b2017-05-23 03:43:47 -07001025 #
1026 # add a labelled route through the new tunnel
1027 #
1028 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
1029 [VppRoutePath("0.0.0.0",
1030 mpls_tun._sw_if_index,
1031 labels=[33])])
1032 route_10_0_0_4.add_vpp_config()
1033
1034 self.vapi.cli("clear trace")
1035 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1036 self.pg0.add_stream(tx)
1037
1038 self.pg_enable_capture(self.pg_interfaces)
1039 self.pg_start()
1040
1041 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -08001042 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1043 [VppMplsLabel(44),
1044 VppMplsLabel(46),
1045 VppMplsLabel(33, ttl=255)])
1046
Ole Troaneb284a12019-10-09 13:33:19 +02001047 #
1048 # change tunnel's MTU to a low value
1049 #
1050 mpls_tun.set_l3_mtu(1200)
1051
1052 # send IP into the tunnel to be fragmented
1053 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
1054 payload_size=1500)
1055 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
1056
1057 fake_tx = []
1058 for p in tx:
1059 fake_tx.append(p)
1060 fake_tx.append(p)
1061 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1062 [VppMplsLabel(44),
1063 VppMplsLabel(46)])
1064
1065 # send MPLS into the tunnel to be fragmented
1066 tx = self.create_stream_ip4(self.pg0, "10.0.0.4",
1067 payload_size=1500)
1068 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
1069
1070 fake_tx = []
1071 for p in tx:
1072 fake_tx.append(p)
1073 fake_tx.append(p)
1074 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1075 [VppMplsLabel(44),
1076 VppMplsLabel(46),
1077 VppMplsLabel(33, ttl=255)])
1078
Neale Ranns31ed7442018-02-23 05:29:09 -08001079 def test_tunnel_uniform(self):
1080 """ MPLS Tunnel Tests - Uniform """
1081
1082 #
1083 # Create a tunnel with a single out label
1084 # The label stack is specified here from outer to inner
1085 #
1086 mpls_tun = VppMPLSTunnelInterface(
1087 self,
1088 [VppRoutePath(self.pg0.remote_ip4,
1089 self.pg0.sw_if_index,
1090 labels=[VppMplsLabel(44, ttl=32),
1091 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1092 mpls_tun.add_vpp_config()
1093 mpls_tun.admin_up()
1094
1095 #
1096 # add an unlabelled route through the new tunnel
1097 #
1098 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1099 [VppRoutePath("0.0.0.0",
1100 mpls_tun._sw_if_index)])
1101 route_10_0_0_3.add_vpp_config()
1102
1103 self.vapi.cli("clear trace")
1104 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1105 self.pg0.add_stream(tx)
1106
1107 self.pg_enable_capture(self.pg_interfaces)
1108 self.pg_start()
1109
1110 rx = self.pg0.get_capture()
1111 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1112 [VppMplsLabel(44, ttl=32),
1113 VppMplsLabel(46, ttl=23)])
1114
1115 #
1116 # add a labelled route through the new tunnel
1117 #
1118 route_10_0_0_4 = VppIpRoute(
1119 self, "10.0.0.4", 32,
1120 [VppRoutePath("0.0.0.0",
1121 mpls_tun._sw_if_index,
1122 labels=[VppMplsLabel(33, ttl=47)])])
1123 route_10_0_0_4.add_vpp_config()
1124
1125 self.vapi.cli("clear trace")
1126 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1127 self.pg0.add_stream(tx)
1128
1129 self.pg_enable_capture(self.pg_interfaces)
1130 self.pg_start()
1131
1132 rx = self.pg0.get_capture()
1133 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1134 [VppMplsLabel(44, ttl=32),
1135 VppMplsLabel(46, ttl=47),
1136 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001137
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001138 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001139 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001140
Neale Ranns397228d2021-10-21 12:02:53 +00001141 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001142 mpls_tun = VppMPLSTunnelInterface(
1143 self,
1144 [VppRoutePath(self.pg0.remote_ip4,
1145 self.pg0.sw_if_index,
1146 labels=[VppMplsLabel(44, ttl=32),
1147 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1148 mpls_tun.add_vpp_config()
1149 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001150 for ii in range(100):
1151 mpls_tun = VppMPLSTunnelInterface(
1152 self,
1153 [VppRoutePath(self.pg0.remote_ip4,
1154 self.pg0.sw_if_index,
1155 labels=[VppMplsLabel(44, ttl=32),
1156 VppMplsLabel(46, MplsLspMode.UNIFORM)])],
1157 is_l2=1)
1158 mpls_tun.add_vpp_config()
1159 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001160
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001161 def test_v4_exp_null(self):
1162 """ MPLS V4 Explicit NULL test """
1163
1164 #
1165 # The first test case has an MPLS TTL of 0
1166 # all packet should be dropped
1167 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001168 tx = self.create_stream_labelled_ip4(self.pg0,
1169 [VppMplsLabel(0, ttl=0)])
1170 self.send_and_assert_no_replies(self.pg0, tx,
1171 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001172
1173 #
1174 # a stream with a non-zero MPLS TTL
1175 # PG0 is in the default table
1176 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001177 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1178 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001179 self.verify_capture_ip4(self.pg0, rx, tx)
1180
1181 #
1182 # a stream with a non-zero MPLS TTL
1183 # PG1 is in table 1
1184 # we are ensuring the post-pop lookup occurs in the VRF table
1185 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001186 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1187 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1188 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001189
1190 def test_v6_exp_null(self):
1191 """ MPLS V6 Explicit NULL test """
1192
1193 #
1194 # a stream with a non-zero MPLS TTL
1195 # PG0 is in the default table
1196 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001197 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1198 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001199 self.verify_capture_ip6(self.pg0, rx, tx)
1200
1201 #
1202 # a stream with a non-zero MPLS TTL
1203 # PG1 is in table 1
1204 # we are ensuring the post-pop lookup occurs in the VRF table
1205 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001206 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1207 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001208 self.verify_capture_ip6(self.pg0, rx, tx)
1209
Neale Rannscb630ff2016-12-14 13:31:29 +01001210 def test_deag(self):
1211 """ MPLS Deagg """
1212
1213 #
1214 # A de-agg route - next-hop lookup in default table
1215 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001216 route_34_eos = VppMplsRoute(self, 34, 1,
1217 [VppRoutePath("0.0.0.0",
1218 0xffffffff,
1219 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001220 route_34_eos.add_vpp_config()
1221
1222 #
1223 # ping an interface in the default table
1224 # PG0 is in the default table
1225 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001226 tx = self.create_stream_labelled_ip4(self.pg0,
1227 [VppMplsLabel(34)],
1228 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001229 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001230 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001231 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1232
1233 #
1234 # A de-agg route - next-hop lookup in non-default table
1235 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001236 route_35_eos = VppMplsRoute(self, 35, 1,
1237 [VppRoutePath("0.0.0.0",
1238 0xffffffff,
1239 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001240 route_35_eos.add_vpp_config()
Neale Rannsf478f752022-02-17 15:41:32 +00001241 route_356_eos = VppMplsRoute(
1242 self, 356, 1,
1243 [VppRoutePath("0::0",
1244 0xffffffff,
1245 nh_table_id=1)],
1246 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
1247 route_356_eos.add_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001248
1249 #
1250 # ping an interface in the non-default table
1251 # PG0 is in the default table. packet arrive labelled in the
1252 # default table and egress unlabelled in the non-default
1253 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001254 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001255 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1256 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001257 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
Neale Rannsf478f752022-02-17 15:41:32 +00001258 tx = self.create_stream_labelled_ip6(
1259 self.pg0, [VppMplsLabel(356)], ping=1, ip_itf=self.pg1)
1260 rx = self.send_and_expect(self.pg0, tx, self.pg1)
1261 self.verify_capture_ip6(self.pg1, rx, tx, ping_resp=1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001262
Neale Ranns6af1c042017-05-26 03:48:53 -07001263 #
1264 # Double pop
1265 #
1266 route_36_neos = VppMplsRoute(self, 36, 0,
1267 [VppRoutePath("0.0.0.0",
1268 0xffffffff)])
1269 route_36_neos.add_vpp_config()
1270
Neale Ranns31ed7442018-02-23 05:29:09 -08001271 tx = self.create_stream_labelled_ip4(self.pg0,
1272 [VppMplsLabel(36),
1273 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001274 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001275 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001276 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1277
1278 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001279 route_35_eos.remove_vpp_config()
1280 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001281
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001282 def test_interface_rx(self):
1283 """ MPLS Interface Receive """
1284
1285 #
1286 # Add a non-recursive route that will forward the traffic
1287 # post-interface-rx
1288 #
1289 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1290 table_id=1,
1291 paths=[VppRoutePath(self.pg1.remote_ip4,
1292 self.pg1.sw_if_index)])
1293 route_10_0_0_1.add_vpp_config()
1294
1295 #
1296 # An interface receive label that maps traffic to RX on interface
1297 # pg1
1298 # by injecting the packet in on pg0, which is in table 0
1299 # doing an interface-rx on pg1 and matching a route in table 1
1300 # if the packet egresses, then we must have swapped to pg1
1301 # so as to have matched the route in table 1
1302 #
Neale Ranns097fa662018-05-01 05:17:55 -07001303 route_34_eos = VppMplsRoute(
1304 self, 34, 1,
1305 [VppRoutePath("0.0.0.0",
1306 self.pg1.sw_if_index,
1307 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001308 route_34_eos.add_vpp_config()
1309
1310 #
1311 # ping an interface in the default table
1312 # PG0 is in the default table
1313 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001314 tx = self.create_stream_labelled_ip4(self.pg0,
1315 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001316 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001317 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001318 self.verify_capture_ip4(self.pg1, rx, tx)
1319
1320 def test_mcast_mid_point(self):
1321 """ MPLS Multicast Mid Point """
1322
1323 #
1324 # Add a non-recursive route that will forward the traffic
1325 # post-interface-rx
1326 #
1327 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1328 table_id=1,
1329 paths=[VppRoutePath(self.pg1.remote_ip4,
1330 self.pg1.sw_if_index)])
1331 route_10_0_0_1.add_vpp_config()
1332
1333 #
1334 # Add a mcast entry that replicate to pg2 and pg3
1335 # and replicate to a interface-rx (like a bud node would)
1336 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001337 route_3400_eos = VppMplsRoute(
1338 self, 3400, 1,
1339 [VppRoutePath(self.pg2.remote_ip4,
1340 self.pg2.sw_if_index,
1341 labels=[VppMplsLabel(3401)]),
1342 VppRoutePath(self.pg3.remote_ip4,
1343 self.pg3.sw_if_index,
1344 labels=[VppMplsLabel(3402)]),
1345 VppRoutePath("0.0.0.0",
1346 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001347 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001348 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001349 route_3400_eos.add_vpp_config()
1350
1351 #
1352 # ping an interface in the default table
1353 # PG0 is in the default table
1354 #
1355 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001356 tx = self.create_stream_labelled_ip4(self.pg0,
1357 [VppMplsLabel(3400, ttl=64)],
1358 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001359 dst_ip="10.0.0.1")
1360 self.pg0.add_stream(tx)
1361
1362 self.pg_enable_capture(self.pg_interfaces)
1363 self.pg_start()
1364
1365 rx = self.pg1.get_capture(257)
1366 self.verify_capture_ip4(self.pg1, rx, tx)
1367
1368 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001369 self.verify_capture_labelled(self.pg2, rx, tx,
1370 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001371 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001372 self.verify_capture_labelled(self.pg3, rx, tx,
1373 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001374
1375 def test_mcast_head(self):
1376 """ MPLS Multicast Head-end """
1377
Neale Ranns990f6942020-10-20 07:20:17 +00001378 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1379 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1380
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001381 #
1382 # Create a multicast tunnel with two replications
1383 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001384 mpls_tun = VppMPLSTunnelInterface(
1385 self,
1386 [VppRoutePath(self.pg2.remote_ip4,
1387 self.pg2.sw_if_index,
1388 labels=[VppMplsLabel(42)]),
1389 VppRoutePath(self.pg3.remote_ip4,
1390 self.pg3.sw_if_index,
1391 labels=[VppMplsLabel(43)])],
1392 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001393 mpls_tun.add_vpp_config()
1394 mpls_tun.admin_up()
1395
1396 #
1397 # add an unlabelled route through the new tunnel
1398 #
1399 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1400 [VppRoutePath("0.0.0.0",
1401 mpls_tun._sw_if_index)])
1402 route_10_0_0_3.add_vpp_config()
1403
1404 self.vapi.cli("clear trace")
1405 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1406 self.pg0.add_stream(tx)
1407
1408 self.pg_enable_capture(self.pg_interfaces)
1409 self.pg_start()
1410
1411 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001412 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001413 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001414 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001415
1416 #
1417 # An an IP multicast route via the tunnel
1418 # A (*,G).
1419 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1420 #
1421 route_232_1_1_1 = VppIpMRoute(
1422 self,
1423 "0.0.0.0",
1424 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001425 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001426 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001427 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001428 VppMRoutePath(mpls_tun._sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001429 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001430 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001431 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001432
1433 self.vapi.cli("clear trace")
1434 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1435 self.pg0.add_stream(tx)
1436
1437 self.pg_enable_capture(self.pg_interfaces)
1438 self.pg_start()
1439
1440 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001441 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001442 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001443 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001444
Neale Ranns31426c62017-05-24 10:32:58 -07001445 def test_mcast_ip4_tail(self):
1446 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001447
Neale Ranns990f6942020-10-20 07:20:17 +00001448 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1449 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1450
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001451 #
1452 # Add a multicast route that will forward the traffic
1453 # post-disposition
1454 #
1455 route_232_1_1_1 = VppIpMRoute(
1456 self,
1457 "0.0.0.0",
1458 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001459 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001460 table_id=1,
1461 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001462 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001463 route_232_1_1_1.add_vpp_config()
1464
1465 #
1466 # An interface receive label that maps traffic to RX on interface
1467 # pg1
1468 # by injecting the packet in on pg0, which is in table 0
1469 # doing an rpf-id and matching a route in table 1
1470 # if the packet egresses, then we must have matched the route in
1471 # table 1
1472 #
Neale Ranns097fa662018-05-01 05:17:55 -07001473 route_34_eos = VppMplsRoute(
1474 self, 34, 1,
1475 [VppRoutePath("0.0.0.0",
1476 0xffffffff,
1477 nh_table_id=1,
1478 rpf_id=55)],
1479 is_multicast=1,
1480 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001481
1482 route_34_eos.add_vpp_config()
1483
1484 #
1485 # Drop due to interface lookup miss
1486 #
1487 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001488 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001489 dst_ip="232.1.1.1", n=1)
1490 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1491
1492 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001493 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001494 #
1495 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001496 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001497
Neale Ranns31ed7442018-02-23 05:29:09 -08001498 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1499 dst_ip="232.1.1.1")
1500 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001501 self.verify_capture_ip4(self.pg1, rx, tx)
1502
1503 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001504 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001505 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001506 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001507 dst_ip="232.1.1.1", n=65,
1508 chksum=1)
1509 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1510
1511 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001512 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001513 #
1514 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001515 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001516 dst_ip="232.1.1.1")
1517 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1518
Neale Ranns31426c62017-05-24 10:32:58 -07001519 def test_mcast_ip6_tail(self):
1520 """ MPLS IPv6 Multicast Tail """
1521
Neale Ranns990f6942020-10-20 07:20:17 +00001522 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1523 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1524
Neale Ranns31426c62017-05-24 10:32:58 -07001525 #
1526 # Add a multicast route that will forward the traffic
1527 # post-disposition
1528 #
1529 route_ff = VppIpMRoute(
1530 self,
1531 "::",
1532 "ff01::1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001533 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001534 table_id=1,
1535 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001536 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001537 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001538 route_ff.add_vpp_config()
1539
1540 #
1541 # An interface receive label that maps traffic to RX on interface
1542 # pg1
1543 # by injecting the packet in on pg0, which is in table 0
1544 # doing an rpf-id and matching a route in table 1
1545 # if the packet egresses, then we must have matched the route in
1546 # table 1
1547 #
1548 route_34_eos = VppMplsRoute(
1549 self, 34, 1,
1550 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001551 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001552 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001553 rpf_id=55)],
1554 is_multicast=1,
1555 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001556
1557 route_34_eos.add_vpp_config()
1558
1559 #
1560 # Drop due to interface lookup miss
1561 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001562 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001563 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001564 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001565
1566 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001567 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001568 #
1569 route_ff.update_rpf_id(55)
1570
Neale Ranns31ed7442018-02-23 05:29:09 -08001571 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001572 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001573 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001574 self.verify_capture_ip6(self.pg1, rx, tx)
1575
1576 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001577 # disposed packets have hop-limit = 1
1578 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001579 tx = self.create_stream_labelled_ip6(self.pg0,
1580 [VppMplsLabel(34)],
1581 dst_ip="ff01::1",
1582 hlim=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001583 rx = self.send_and_expect_some(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001584 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001585
1586 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001587 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001588 #
1589 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001590 tx = self.create_stream_labelled_ip6(self.pg0,
1591 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001592 dst_ip="ff01::1")
1593 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1594
Neale Rannsd5d7b962019-08-04 03:30:56 -07001595 def test_6pe(self):
1596 """ MPLS 6PE """
1597
1598 #
1599 # Add a non-recursive route with a single out label
1600 #
1601 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1602 [VppRoutePath(self.pg0.remote_ip4,
1603 self.pg0.sw_if_index,
1604 labels=[VppMplsLabel(45)])])
1605 route_10_0_0_1.add_vpp_config()
1606
1607 # bind a local label to the route
1608 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1609 binding.add_vpp_config()
1610
1611 #
1612 # a labelled v6 route that resolves through the v4
1613 #
1614 route_2001_3 = VppIpRoute(
1615 self, "2001::3", 128,
1616 [VppRoutePath("10.0.0.1",
1617 INVALID_INDEX,
1618 labels=[VppMplsLabel(32)])])
1619 route_2001_3.add_vpp_config()
1620
1621 tx = self.create_stream_ip6(self.pg0, "2001::3")
1622 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1623
1624 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1625 [VppMplsLabel(45),
1626 VppMplsLabel(32)])
1627
1628 #
1629 # and a v4 recursive via the v6
1630 #
1631 route_20_3 = VppIpRoute(
1632 self, "20.0.0.3", 32,
1633 [VppRoutePath("2001::3",
1634 INVALID_INDEX,
1635 labels=[VppMplsLabel(99)])])
1636 route_20_3.add_vpp_config()
1637
1638 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1639 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1640
1641 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1642 [VppMplsLabel(45),
1643 VppMplsLabel(32),
1644 VppMplsLabel(99)])
1645
Neale Ranns53962fb2021-12-20 18:18:42 +00001646 def test_attached(self):
1647 """ Attach Routes with Local Label """
1648
1649 #
1650 # test that if a local label is associated with an attached/connected
1651 # prefix, that we can reach hosts in the prefix.
1652 #
1653 binding = VppMplsIpBind(self, 44,
1654 self.pg0._local_ip4_subnet,
1655 self.pg0.local_ip4_prefix_len)
1656 binding.add_vpp_config()
1657
1658 tx = (Ether(src=self.pg1.remote_mac,
1659 dst=self.pg1.local_mac) /
1660 MPLS(label=44, ttl=64) /
1661 IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
1662 UDP(sport=1234, dport=1234) /
1663 Raw(b'\xa5' * 100))
1664 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
1665 for rx in rxs:
1666 # if there's an ARP then the label is linked to the glean
1667 # which is wrong.
1668 self.assertFalse(rx.haslayer(ARP))
1669 # it should be unicasted to the host
1670 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1671 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
1672
Neale Ranns180279b2017-03-16 15:49:09 -04001673
1674class TestMPLSDisabled(VppTestCase):
1675 """ MPLS disabled """
1676
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001677 @classmethod
1678 def setUpClass(cls):
1679 super(TestMPLSDisabled, cls).setUpClass()
1680
1681 @classmethod
1682 def tearDownClass(cls):
1683 super(TestMPLSDisabled, cls).tearDownClass()
1684
Neale Ranns180279b2017-03-16 15:49:09 -04001685 def setUp(self):
1686 super(TestMPLSDisabled, self).setUp()
1687
1688 # create 2 pg interfaces
1689 self.create_pg_interfaces(range(2))
1690
Neale Ranns15002542017-09-10 04:39:11 -07001691 self.tbl = VppMplsTable(self, 0)
1692 self.tbl.add_vpp_config()
1693
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001694 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001695 self.pg0.admin_up()
1696 self.pg0.config_ip4()
1697 self.pg0.resolve_arp()
1698 self.pg0.enable_mpls()
1699
1700 # PG 1 is not MPLS enabled
1701 self.pg1.admin_up()
1702
1703 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001704 for i in self.pg_interfaces:
1705 i.unconfig_ip4()
1706 i.admin_down()
1707
Neale Ranns15002542017-09-10 04:39:11 -07001708 self.pg0.disable_mpls()
1709 super(TestMPLSDisabled, self).tearDown()
1710
Neale Ranns180279b2017-03-16 15:49:09 -04001711 def test_mpls_disabled(self):
1712 """ MPLS Disabled """
1713
Neale Rannsde0b3b52021-06-15 12:43:12 +00001714 self.logger.info(self.vapi.cli("show mpls interface"))
1715 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1716 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1717
Neale Ranns180279b2017-03-16 15:49:09 -04001718 tx = (Ether(src=self.pg1.remote_mac,
1719 dst=self.pg1.local_mac) /
1720 MPLS(label=32, ttl=64) /
1721 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1722 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001723 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001724
1725 #
1726 # A simple MPLS xconnect - eos label in label out
1727 #
1728 route_32_eos = VppMplsRoute(self, 32, 1,
1729 [VppRoutePath(self.pg0.remote_ip4,
1730 self.pg0.sw_if_index,
1731 labels=[33])])
1732 route_32_eos.add_vpp_config()
1733
1734 #
1735 # PG1 does not forward IP traffic
1736 #
1737 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1738
1739 #
1740 # MPLS enable PG1
1741 #
1742 self.pg1.enable_mpls()
1743
Neale Rannsde0b3b52021-06-15 12:43:12 +00001744 self.logger.info(self.vapi.cli("show mpls interface"))
1745 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1746
Neale Ranns180279b2017-03-16 15:49:09 -04001747 #
1748 # Now we get packets through
1749 #
1750 self.pg1.add_stream(tx)
1751 self.pg_enable_capture(self.pg_interfaces)
1752 self.pg_start()
1753
1754 rx = self.pg0.get_capture(1)
1755
1756 #
1757 # Disable PG1
1758 #
1759 self.pg1.disable_mpls()
1760
1761 #
1762 # PG1 does not forward IP traffic
1763 #
1764 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1765 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1766
1767
Neale Rannsf12a83f2017-04-18 09:09:40 -07001768class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001769 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001770
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001771 @classmethod
1772 def setUpClass(cls):
1773 super(TestMPLSPIC, cls).setUpClass()
1774
1775 @classmethod
1776 def tearDownClass(cls):
1777 super(TestMPLSPIC, cls).tearDownClass()
1778
Neale Rannsf12a83f2017-04-18 09:09:40 -07001779 def setUp(self):
1780 super(TestMPLSPIC, self).setUp()
1781
1782 # create 2 pg interfaces
1783 self.create_pg_interfaces(range(4))
1784
Neale Ranns15002542017-09-10 04:39:11 -07001785 mpls_tbl = VppMplsTable(self, 0)
1786 mpls_tbl.add_vpp_config()
1787 tbl4 = VppIpTable(self, 1)
1788 tbl4.add_vpp_config()
1789 tbl6 = VppIpTable(self, 1, is_ip6=1)
1790 tbl6.add_vpp_config()
1791
Neale Rannsf12a83f2017-04-18 09:09:40 -07001792 # core links
1793 self.pg0.admin_up()
1794 self.pg0.config_ip4()
1795 self.pg0.resolve_arp()
1796 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001797
Neale Rannsf12a83f2017-04-18 09:09:40 -07001798 self.pg1.admin_up()
1799 self.pg1.config_ip4()
1800 self.pg1.resolve_arp()
1801 self.pg1.enable_mpls()
1802
1803 # VRF (customer facing) link
1804 self.pg2.admin_up()
1805 self.pg2.set_table_ip4(1)
1806 self.pg2.config_ip4()
1807 self.pg2.resolve_arp()
1808 self.pg2.set_table_ip6(1)
1809 self.pg2.config_ip6()
1810 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001811
Neale Rannsf12a83f2017-04-18 09:09:40 -07001812 self.pg3.admin_up()
1813 self.pg3.set_table_ip4(1)
1814 self.pg3.config_ip4()
1815 self.pg3.resolve_arp()
1816 self.pg3.set_table_ip6(1)
1817 self.pg3.config_ip6()
1818 self.pg3.resolve_ndp()
1819
1820 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001821 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001822 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001823 for i in self.pg_interfaces:
1824 i.unconfig_ip4()
1825 i.unconfig_ip6()
1826 i.set_table_ip4(0)
1827 i.set_table_ip6(0)
1828 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001829 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001830
1831 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001832 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001833
1834 1) setup many iBGP VPN routes via a pair of iBGP peers.
1835 2) Check EMCP forwarding to these peers
1836 3) withdraw the IGP route to one of these peers.
1837 4) check forwarding continues to the remaining peer
1838 """
1839
1840 #
1841 # IGP+LDP core routes
1842 #
1843 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1844 [VppRoutePath(self.pg0.remote_ip4,
1845 self.pg0.sw_if_index,
1846 labels=[45])])
1847 core_10_0_0_45.add_vpp_config()
1848
1849 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1850 [VppRoutePath(self.pg1.remote_ip4,
1851 self.pg1.sw_if_index,
1852 labels=[46])])
1853 core_10_0_0_46.add_vpp_config()
1854
1855 #
1856 # Lot's of VPN routes. We need more the 64 so VPP will build
1857 # the fast convergence indirection
1858 #
1859 vpn_routes = []
1860 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001861 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001862 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001863 vpn_routes.append(VppIpRoute(
1864 self, dst, 32,
1865 [VppRoutePath(
1866 "10.0.0.45",
1867 0xffffffff,
1868 labels=[145],
1869 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1870 VppRoutePath(
1871 "10.0.0.46",
1872 0xffffffff,
1873 labels=[146],
1874 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1875 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001876 vpn_routes[ii].add_vpp_config()
1877
1878 pkts.append(Ether(dst=self.pg2.local_mac,
1879 src=self.pg2.remote_mac) /
1880 IP(src=self.pg2.remote_ip4, dst=dst) /
1881 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001882 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001883
1884 #
1885 # Send the packet stream (one pkt to each VPN route)
1886 # - expect a 50-50 split of the traffic
1887 #
1888 self.pg2.add_stream(pkts)
1889 self.pg_enable_capture(self.pg_interfaces)
1890 self.pg_start()
1891
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001892 rx0 = self.pg0._get_capture(NUM_PKTS)
1893 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001894
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001895 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001896 # with the split ratio, just as long as neither is 0
1897 self.assertNotEqual(0, len(rx0))
1898 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001899 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1900 "Expected all (%s) packets across both ECMP paths. "
1901 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001902
1903 #
1904 # use a test CLI command to stop the FIB walk process, this
1905 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001906 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001907 #
1908 self.vapi.ppcli("test fib-walk-process disable")
1909
1910 #
1911 # Withdraw one of the IGP routes
1912 #
1913 core_10_0_0_46.remove_vpp_config()
1914
1915 #
1916 # now all packets should be forwarded through the remaining peer
1917 #
1918 self.vapi.ppcli("clear trace")
1919 self.pg2.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1921 self.pg_start()
1922
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001923 rx0 = self.pg0.get_capture(NUM_PKTS)
1924 self.assertEqual(len(pkts), len(rx0),
1925 "Expected all (%s) packets across single path. "
1926 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001927
1928 #
1929 # enable the FIB walk process to converge the FIB
1930 #
1931 self.vapi.ppcli("test fib-walk-process enable")
1932
1933 #
1934 # packets should still be forwarded through the remaining peer
1935 #
1936 self.pg2.add_stream(pkts)
1937 self.pg_enable_capture(self.pg_interfaces)
1938 self.pg_start()
1939
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001940 rx0 = self.pg0.get_capture(NUM_PKTS)
1941 self.assertEqual(len(pkts), len(rx0),
1942 "Expected all (%s) packets across single path. "
1943 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001944
1945 #
1946 # Add the IGP route back and we return to load-balancing
1947 #
1948 core_10_0_0_46.add_vpp_config()
1949
1950 self.pg2.add_stream(pkts)
1951 self.pg_enable_capture(self.pg_interfaces)
1952 self.pg_start()
1953
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001954 rx0 = self.pg0._get_capture(NUM_PKTS)
1955 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001956 self.assertNotEqual(0, len(rx0))
1957 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001958 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1959 "Expected all (%s) packets across both ECMP paths. "
1960 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001961
1962 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001963 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001964
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001965 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001966 2) Check EMCP forwarding to these peers
1967 3) withdraw one eBGP path - expect LB across remaining eBGP
1968 """
1969
1970 #
1971 # Lot's of VPN routes. We need more the 64 so VPP will build
1972 # the fast convergence indirection
1973 #
1974 vpn_routes = []
1975 vpn_bindings = []
1976 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001977 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001978 dst = "192.168.1.%d" % ii
1979 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001980 vpn_routes.append(VppIpRoute(
1981 self, dst, 32,
1982 [VppRoutePath(
1983 self.pg2.remote_ip4,
1984 0xffffffff,
1985 nh_table_id=1,
1986 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1987 VppRoutePath(
1988 self.pg3.remote_ip4,
1989 0xffffffff,
1990 nh_table_id=1,
1991 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1992 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001993 vpn_routes[ii].add_vpp_config()
1994
1995 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1996 ip_table_id=1))
1997 vpn_bindings[ii].add_vpp_config()
1998
1999 pkts.append(Ether(dst=self.pg0.local_mac,
2000 src=self.pg0.remote_mac) /
2001 MPLS(label=local_label, ttl=64) /
2002 IP(src=self.pg0.remote_ip4, dst=dst) /
2003 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002004 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002005
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002006 #
2007 # Send the packet stream (one pkt to each VPN route)
2008 # - expect a 50-50 split of the traffic
2009 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002010 self.pg0.add_stream(pkts)
2011 self.pg_enable_capture(self.pg_interfaces)
2012 self.pg_start()
2013
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002014 rx0 = self.pg2._get_capture(NUM_PKTS)
2015 rx1 = self.pg3._get_capture(NUM_PKTS)
2016
2017 # not testing the LB hashing algorithm so we're not concerned
2018 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07002019 self.assertNotEqual(0, len(rx0))
2020 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002021 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2022 "Expected all (%s) packets across both ECMP paths. "
2023 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002024
2025 #
2026 # use a test CLI command to stop the FIB walk process, this
2027 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002028 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002029 #
2030 self.vapi.ppcli("test fib-walk-process disable")
2031
2032 #
2033 # withdraw the connected prefix on the interface.
2034 #
2035 self.pg2.unconfig_ip4()
2036
2037 #
2038 # now all packets should be forwarded through the remaining peer
2039 #
2040 self.pg0.add_stream(pkts)
2041 self.pg_enable_capture(self.pg_interfaces)
2042 self.pg_start()
2043
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002044 rx0 = self.pg3.get_capture(NUM_PKTS)
2045 self.assertEqual(len(pkts), len(rx0),
2046 "Expected all (%s) packets across single path. "
2047 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002048
2049 #
2050 # enable the FIB walk process to converge the FIB
2051 #
2052 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002053
2054 #
2055 # packets should still be forwarded through the remaining peer
2056 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07002057 self.pg0.add_stream(pkts)
2058 self.pg_enable_capture(self.pg_interfaces)
2059 self.pg_start()
2060
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002061 rx0 = self.pg3.get_capture(NUM_PKTS)
2062 self.assertEqual(len(pkts), len(rx0),
2063 "Expected all (%s) packets across single path. "
2064 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002065
2066 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002067 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002068 #
2069 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002070 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002071
2072 self.pg0.add_stream(pkts)
2073 self.pg_enable_capture(self.pg_interfaces)
2074 self.pg_start()
2075
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002076 rx0 = self.pg2._get_capture(NUM_PKTS)
2077 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002078 self.assertNotEqual(0, len(rx0))
2079 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002080 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2081 "Expected all (%s) packets across both ECMP paths. "
2082 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002083
2084 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002085 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002086
2087 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2088 2) Check EMCP forwarding to these peers
2089 3) withdraw one eBGP path - expect LB across remaining eBGP
2090 """
2091
2092 #
2093 # Lot's of VPN routes. We need more the 64 so VPP will build
2094 # the fast convergence indirection
2095 #
2096 vpn_routes = []
2097 vpn_bindings = []
2098 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002099 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002100 dst = "3000::%d" % ii
2101 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07002102 vpn_routes.append(VppIpRoute(
2103 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002104 [VppRoutePath(
2105 self.pg2.remote_ip6,
2106 0xffffffff,
2107 nh_table_id=1,
2108 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
2109 VppRoutePath(
2110 self.pg3.remote_ip6,
2111 0xffffffff,
2112 nh_table_id=1,
2113 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
2114 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002115 vpn_routes[ii].add_vpp_config()
2116
2117 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002118 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002119 vpn_bindings[ii].add_vpp_config()
2120
2121 pkts.append(Ether(dst=self.pg0.local_mac,
2122 src=self.pg0.remote_mac) /
2123 MPLS(label=local_label, ttl=64) /
2124 IPv6(src=self.pg0.remote_ip6, dst=dst) /
2125 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002126 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002127 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002128
2129 self.pg0.add_stream(pkts)
2130 self.pg_enable_capture(self.pg_interfaces)
2131 self.pg_start()
2132
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002133 rx0 = self.pg2._get_capture(NUM_PKTS)
2134 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002135 self.assertNotEqual(0, len(rx0))
2136 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002137 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2138 "Expected all (%s) packets across both ECMP paths. "
2139 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002140
2141 #
2142 # use a test CLI command to stop the FIB walk process, this
2143 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002144 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002145 #
2146 self.vapi.ppcli("test fib-walk-process disable")
2147
2148 #
2149 # withdraw the connected prefix on the interface.
2150 # and shutdown the interface so the ND cache is flushed.
2151 #
2152 self.pg2.unconfig_ip6()
2153 self.pg2.admin_down()
2154
2155 #
2156 # now all packets should be forwarded through the remaining peer
2157 #
2158 self.pg0.add_stream(pkts)
2159 self.pg_enable_capture(self.pg_interfaces)
2160 self.pg_start()
2161
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002162 rx0 = self.pg3.get_capture(NUM_PKTS)
2163 self.assertEqual(len(pkts), len(rx0),
2164 "Expected all (%s) packets across single path. "
2165 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002166
2167 #
2168 # enable the FIB walk process to converge the FIB
2169 #
2170 self.vapi.ppcli("test fib-walk-process enable")
2171 self.pg0.add_stream(pkts)
2172 self.pg_enable_capture(self.pg_interfaces)
2173 self.pg_start()
2174
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002175 rx0 = self.pg3.get_capture(NUM_PKTS)
2176 self.assertEqual(len(pkts), len(rx0),
2177 "Expected all (%s) packets across single path. "
2178 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002179
2180 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002181 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002182 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002183 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002184 self.pg2.admin_up()
2185 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002186 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002187
2188 self.pg0.add_stream(pkts)
2189 self.pg_enable_capture(self.pg_interfaces)
2190 self.pg_start()
2191
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002192 rx0 = self.pg2._get_capture(NUM_PKTS)
2193 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002194 self.assertNotEqual(0, len(rx0))
2195 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002196 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2197 "Expected all (%s) packets across both ECMP paths. "
2198 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002199
2200
Neale Rannsda78f952017-05-24 09:15:43 -07002201class TestMPLSL2(VppTestCase):
2202 """ MPLS-L2 """
2203
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002204 @classmethod
2205 def setUpClass(cls):
2206 super(TestMPLSL2, cls).setUpClass()
2207
2208 @classmethod
2209 def tearDownClass(cls):
2210 super(TestMPLSL2, cls).tearDownClass()
2211
Neale Rannsda78f952017-05-24 09:15:43 -07002212 def setUp(self):
2213 super(TestMPLSL2, self).setUp()
2214
2215 # create 2 pg interfaces
2216 self.create_pg_interfaces(range(2))
2217
Neale Ranns15002542017-09-10 04:39:11 -07002218 # create the default MPLS table
2219 self.tables = []
2220 tbl = VppMplsTable(self, 0)
2221 tbl.add_vpp_config()
2222 self.tables.append(tbl)
2223
Neale Ranns1976f362019-11-06 13:13:01 +00002224 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002225 self.pg0.admin_up()
2226 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002227 self.pg0.enable_mpls()
2228
Neale Ranns15002542017-09-10 04:39:11 -07002229 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002230 for i in self.pg_interfaces[1:]:
2231 i.admin_up()
2232
2233 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002234 for i in self.pg_interfaces[1:]:
2235 i.admin_down()
2236
2237 self.pg0.disable_mpls()
2238 self.pg0.unconfig_ip4()
2239 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002240 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002241
Neale Ranns31ed7442018-02-23 05:29:09 -08002242 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002243 capture = verify_filter(capture, sent)
2244
2245 self.assertEqual(len(capture), len(sent))
2246
2247 for i in range(len(capture)):
2248 tx = sent[i]
2249 rx = capture[i]
2250
2251 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002252 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002253
2254 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002255 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002256
2257 self.assertEqual(rx_eth.src, tx_eth.src)
2258 self.assertEqual(rx_eth.dst, tx_eth.dst)
2259
Neale Ranns1976f362019-11-06 13:13:01 +00002260 def verify_arp_req(self, rx, smac, sip, dip):
2261 ether = rx[Ether]
2262 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2263 self.assertEqual(ether.src, smac)
2264
2265 arp = rx[ARP]
2266 self.assertEqual(arp.hwtype, 1)
2267 self.assertEqual(arp.ptype, 0x800)
2268 self.assertEqual(arp.hwlen, 6)
2269 self.assertEqual(arp.plen, 4)
2270 self.assertEqual(arp.op, ARP.who_has)
2271 self.assertEqual(arp.hwsrc, smac)
2272 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2273 self.assertEqual(arp.psrc, sip)
2274 self.assertEqual(arp.pdst, dip)
2275
Neale Rannsda78f952017-05-24 09:15:43 -07002276 def test_vpws(self):
2277 """ Virtual Private Wire Service """
2278
2279 #
2280 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002281 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2282 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002283 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002284 mpls_tun_1 = VppMPLSTunnelInterface(
2285 self,
2286 [VppRoutePath(self.pg0.remote_ip4,
2287 self.pg0.sw_if_index,
2288 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2289 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002290 mpls_tun_1.add_vpp_config()
2291 mpls_tun_1.admin_up()
2292
2293 #
2294 # Create a label entry to for 55 that does L2 input to the tunnel
2295 #
2296 route_55_eos = VppMplsRoute(
2297 self, 55, 1,
2298 [VppRoutePath("0.0.0.0",
2299 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002300 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2301 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2302 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002303 route_55_eos.add_vpp_config()
2304
2305 #
2306 # Cross-connect the tunnel with one of the customers L2 interfaces
2307 #
2308 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2309 mpls_tun_1.sw_if_index,
2310 enable=1)
2311 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2312 self.pg1.sw_if_index,
2313 enable=1)
2314
2315 #
2316 # inject a packet from the core
2317 #
2318 pcore = (Ether(dst=self.pg0.local_mac,
2319 src=self.pg0.remote_mac) /
2320 MPLS(label=55, ttl=64) /
2321 Ether(dst="00:00:de:ad:ba:be",
2322 src="00:00:de:ad:be:ef") /
2323 IP(src="10.10.10.10", dst="11.11.11.11") /
2324 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002325 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002326
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002327 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002328 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2329 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002330
Neale Ranns31ed7442018-02-23 05:29:09 -08002331 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2332 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002333
2334 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002335 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002336 # there's no resolved ARP entry so the first packet we see should be
2337 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002338 #
Neale Ranns1976f362019-11-06 13:13:01 +00002339 tx1 = pcore[MPLS].payload
2340 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2341
2342 self.verify_arp_req(rx1[0],
2343 self.pg0.local_mac,
2344 self.pg0.local_ip4,
2345 self.pg0.remote_ip4)
2346
2347 #
2348 # resolve the ARP entries and send again
2349 #
2350 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002351 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002352 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002353
Neale Ranns31ed7442018-02-23 05:29:09 -08002354 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002355
2356 def test_vpls(self):
2357 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002358
2359 # we skipped this in the setup
2360 self.pg0.resolve_arp()
2361
Neale Rannsda78f952017-05-24 09:15:43 -07002362 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002363 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002364 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002365 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002366 self,
2367 [VppRoutePath(self.pg0.remote_ip4,
2368 self.pg0.sw_if_index,
2369 labels=[VppMplsLabel(42)])],
2370 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002371 mpls_tun1.add_vpp_config()
2372 mpls_tun1.admin_up()
2373
2374 mpls_tun2 = VppMPLSTunnelInterface(
2375 self,
2376 [VppRoutePath(self.pg0.remote_ip4,
2377 self.pg0.sw_if_index,
2378 labels=[VppMplsLabel(43)])],
2379 is_l2=1)
2380 mpls_tun2.add_vpp_config()
2381 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002382
2383 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002384 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2385 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002386 #
2387 route_55_eos = VppMplsRoute(
2388 self, 55, 1,
2389 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002390 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002391 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2392 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2393 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002394
2395 route_56_eos = VppMplsRoute(
2396 self, 56, 1,
2397 [VppRoutePath("0.0.0.0",
2398 mpls_tun2.sw_if_index,
2399 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2400 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2401 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2402 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2403
2404 # move me
2405 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002406 route_55_eos.add_vpp_config()
2407
Neale Ranns1dbcf302019-07-19 11:44:53 +00002408 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2409
Neale Rannsda78f952017-05-24 09:15:43 -07002410 #
2411 # add to tunnel to the customers bridge-domain
2412 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002413 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002414 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2415 self.vapi.sw_interface_set_l2_bridge(
2416 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002417 self.vapi.sw_interface_set_l2_bridge(
2418 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002419
2420 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002421 # Packet from host on the customer interface to each host
2422 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002423 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002424 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2425 src="00:00:de:ad:be:ef") /
2426 IP(src="10.10.10.10", dst="11.11.11.11") /
2427 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002428 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002429 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2430 src="00:00:de:ad:be:ef") /
2431 IP(src="10.10.10.10", dst="11.11.11.12") /
2432 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002433 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002434 p_core1 = (Ether(dst=self.pg0.local_mac,
2435 src=self.pg0.remote_mac) /
2436 MPLS(label=55, ttl=64) /
2437 Ether(src="00:00:de:ad:ba:b1",
2438 dst="00:00:de:ad:be:ef") /
2439 IP(dst="10.10.10.10", src="11.11.11.11") /
2440 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002441 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002442 p_core2 = (Ether(dst=self.pg0.local_mac,
2443 src=self.pg0.remote_mac) /
2444 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002445 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002446 Ether(src="00:00:de:ad:ba:b2",
2447 dst="00:00:de:ad:be:ef") /
2448 IP(dst="10.10.10.10", src="11.11.11.12") /
2449 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002450 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002451
2452 #
2453 # The BD is learning, so send in one of each packet to learn
2454 #
Neale Rannsda78f952017-05-24 09:15:43 -07002455
Neale Ranns1dbcf302019-07-19 11:44:53 +00002456 # 2 packets due to BD flooding
2457 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2458 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002459
Neale Ranns1dbcf302019-07-19 11:44:53 +00002460 # we've learnt this so expect it be be forwarded not flooded
2461 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2462 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2463 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002464
Neale Ranns1dbcf302019-07-19 11:44:53 +00002465 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2466 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2467 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002468
2469 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002470 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002471 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002472 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2473 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002474 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002475
Neale Ranns1dbcf302019-07-19 11:44:53 +00002476 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2477 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2478 [VppMplsLabel(43)])
2479
2480 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2481 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2482
Neale Rannsda78f952017-05-24 09:15:43 -07002483 #
2484 # remove interfaces from customers bridge-domain
2485 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002486 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002487 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2488 self.vapi.sw_interface_set_l2_bridge(
2489 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002490 self.vapi.sw_interface_set_l2_bridge(
2491 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002492
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002493
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002494if __name__ == '__main__':
2495 unittest.main(testRunner=VppTestRunner)