blob: 34645a9fce1f7c7da11be193d349e3486f9b2e1a [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002
3import unittest
Gabriel Gannea9b2d582016-12-06 10:25:34 +01004import socket
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00006from framework import tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +00007from framework import VppTestCase, VppTestRunner
Neale Rannsd5d7b962019-08-04 03:30:56 -07008from vpp_ip import DpoProto, INVALID_INDEX
Neale Ranns5a8123b2017-01-26 01:18:23 -08009from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -080010 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Ranns990f6942020-10-20 07:20:17 +000011 VppIpTable, VppMplsTable, \
Neale Ranns097fa662018-05-01 05:17:55 -070012 VppMplsLabel, MplsLspMode, find_mpls_route, \
13 FibPathProto, FibPathType, FibPathFlags, VppMplsLabel, MplsLspMode
Neale Ranns0f26c5a2017-03-01 15:12:11 -080014from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns990f6942020-10-20 07:20:17 +000015from vpp_papi import VppEnum
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070017import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000018from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000019from scapy.layers.l2 import Ether, ARP
Neale Rannscb630ff2016-12-14 13:31:29 +010020from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070021from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000022from scapy.contrib.mpls import MPLS
23
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040024NUM_PKTS = 67
25
Neale Ranns1976f362019-11-06 13:13:01 +000026# scapy removed these attributes.
27# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
28# semantic names have more meaning than numbers. so here they are.
29ARP.who_has = 1
30ARP.is_at = 2
31
Klement Sekeradab231a2016-12-21 08:50:14 +010032
Neale Rannsda78f952017-05-24 09:15:43 -070033def verify_filter(capture, sent):
34 if not len(capture) == len(sent):
35 # filter out any IPv6 RAs from the capture
36 for p in capture:
37 if p.haslayer(IPv6):
38 capture.remove(p)
39 return capture
40
41
Neale Ranns31ed7442018-02-23 05:29:09 -080042def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070043 # the rx'd packet has the MPLS label popped
44 eth = rx[Ether]
45 tst.assertEqual(eth.type, 0x8847)
46
47 rx_mpls = rx[MPLS]
48
49 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080050 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
51 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
52 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
53
Neale Rannsda78f952017-05-24 09:15:43 -070054 if ii == len(mpls_labels) - 1:
55 tst.assertEqual(rx_mpls.s, 1)
56 else:
57 # not end of stack
58 tst.assertEqual(rx_mpls.s, 0)
59 # pop the label to expose the next
60 rx_mpls = rx_mpls[MPLS].payload
61
62
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000063@tag_fixme_vpp_workers
Neale Ranns8fe8cc22016-11-01 10:05:08 +000064class TestMPLS(VppTestCase):
65 """ MPLS Test Case """
66
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070067 @classmethod
68 def setUpClass(cls):
69 super(TestMPLS, cls).setUpClass()
70
71 @classmethod
72 def tearDownClass(cls):
73 super(TestMPLS, cls).tearDownClass()
74
Neale Ranns8fe8cc22016-11-01 10:05:08 +000075 def setUp(self):
76 super(TestMPLS, self).setUp()
77
78 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080079 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000080
81 # setup both interfaces
82 # assign them different tables.
83 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070084 self.tables = []
85
86 tbl = VppMplsTable(self, 0)
87 tbl.add_vpp_config()
88 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000089
90 for i in self.pg_interfaces:
91 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070092
93 if table_id != 0:
94 tbl = VppIpTable(self, table_id)
95 tbl.add_vpp_config()
96 self.tables.append(tbl)
97 tbl = VppIpTable(self, table_id, is_ip6=1)
98 tbl.add_vpp_config()
99 self.tables.append(tbl)
100
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000101 i.set_table_ip4(table_id)
102 i.set_table_ip6(table_id)
103 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000104 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000105 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000106 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000107 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000108 table_id += 1
109
110 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800111 for i in self.pg_interfaces:
112 i.unconfig_ip4()
113 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700114 i.set_table_ip4(0)
115 i.set_table_ip6(0)
116 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800117 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700118 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000119
Neale Rannsad422ed2016-11-02 14:20:04 +0000120 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100121 def create_stream_labelled_ip4(
122 self,
123 src_if,
124 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100125 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800126 ip_itf=None,
127 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700128 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800129 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800130 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100131 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000132 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800133 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100134 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000135 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000136 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
137
138 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800139 p = p / MPLS(label=mpls_labels[ii].value,
140 ttl=mpls_labels[ii].ttl,
141 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100142 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800143 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800144 p = (p / IP(src=src_if.local_ip4,
145 dst=src_if.remote_ip4,
146 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800147 UDP(sport=1234, dport=1234) /
148 Raw(payload))
149 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800150 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800151 UDP(sport=1234, dport=1234) /
152 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100153 else:
154 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800155 dst=ip_itf.local_ip4,
156 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100157 ICMP())
158
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700159 if chksum:
160 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000161 info.data = p.copy()
162 pkts.append(p)
163 return pkts
164
Ole Troaneb284a12019-10-09 13:33:19 +0200165 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64,
166 ip_dscp=0, payload_size=None):
Klement Sekeradab231a2016-12-21 08:50:14 +0100167 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000168 pkts = []
169 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100170 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000171 payload = self.info_to_payload(info)
172 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800173 IP(src=src_if.remote_ip4, dst=dst_ip,
174 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000175 UDP(sport=1234, dport=1234) /
176 Raw(payload))
177 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200178 if payload_size:
179 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000180 pkts.append(p)
181 return pkts
182
Neale Ranns31ed7442018-02-23 05:29:09 -0800183 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
184 self.reset_packet_infos()
185 pkts = []
186 for i in range(0, 257):
187 info = self.create_packet_info(src_if, src_if)
188 payload = self.info_to_payload(info)
189 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
190 IPv6(src=src_if.remote_ip6, dst=dst_ip,
191 hlim=ip_ttl, tc=ip_dscp) /
192 UDP(sport=1234, dport=1234) /
193 Raw(payload))
194 info.data = p.copy()
195 pkts.append(p)
196 return pkts
197
198 def create_stream_labelled_ip6(self, src_if, mpls_labels,
199 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700200 if dst_ip is None:
201 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100202 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000203 pkts = []
204 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100205 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000206 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800207 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
208 for l in mpls_labels:
209 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
210
211 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
212 UDP(sport=1234, dport=1234) /
213 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000214 info.data = p.copy()
215 pkts.append(p)
216 return pkts
217
Neale Ranns31ed7442018-02-23 05:29:09 -0800218 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
219 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000220 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700221 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000222
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000223 self.assertEqual(len(capture), len(sent))
224
225 for i in range(len(capture)):
226 tx = sent[i]
227 rx = capture[i]
228
229 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000230 eth = rx[Ether]
231 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000232
233 tx_ip = tx[IP]
234 rx_ip = rx[IP]
235
Neale Rannscb630ff2016-12-14 13:31:29 +0100236 if not ping_resp:
237 self.assertEqual(rx_ip.src, tx_ip.src)
238 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800239 self.assertEqual(rx_ip.tos, ip_dscp)
240 if not ip_ttl:
241 # IP processing post pop has decremented the TTL
242 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
243 else:
244 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100245 else:
246 self.assertEqual(rx_ip.src, tx_ip.dst)
247 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000248
249 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000250 raise
251
Neale Rannsad422ed2016-11-02 14:20:04 +0000252 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800253 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000254 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700255 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000256
257 self.assertEqual(len(capture), len(sent))
258
259 for i in range(len(capture)):
260 tx = sent[i]
261 rx = capture[i]
262 tx_ip = tx[IP]
263 rx_ip = rx[IP]
264
Neale Ranns31ed7442018-02-23 05:29:09 -0800265 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000266
267 self.assertEqual(rx_ip.src, tx_ip.src)
268 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800269 if not ip_ttl:
270 # IP processing post pop has decremented the TTL
271 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
272 else:
273 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000274
275 except:
276 raise
277
Neale Ranns31ed7442018-02-23 05:29:09 -0800278 def verify_capture_labelled_ip6(self, src_if, capture, sent,
279 mpls_labels, ip_ttl=None):
280 try:
281 capture = verify_filter(capture, sent)
282
283 self.assertEqual(len(capture), len(sent))
284
285 for i in range(len(capture)):
286 tx = sent[i]
287 rx = capture[i]
288 tx_ip = tx[IPv6]
289 rx_ip = rx[IPv6]
290
291 verify_mpls_stack(self, rx, mpls_labels)
292
293 self.assertEqual(rx_ip.src, tx_ip.src)
294 self.assertEqual(rx_ip.dst, tx_ip.dst)
295 if not ip_ttl:
296 # IP processing post pop has decremented the TTL
297 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
298 else:
299 self.assertEqual(rx_ip.hlim, ip_ttl)
300
301 except:
302 raise
303
304 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000305 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700306 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000307
308 self.assertEqual(len(capture), len(sent))
309
310 for i in range(len(capture)):
311 tx = sent[i]
312 rx = capture[i]
313 tx_ip = tx[IP]
314 rx_ip = rx[IP]
315
Neale Ranns31ed7442018-02-23 05:29:09 -0800316 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000317
318 self.assertEqual(rx_ip.src, tx_ip.src)
319 self.assertEqual(rx_ip.dst, tx_ip.dst)
320 # IP processing post pop has decremented the TTL
321 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
322
323 except:
324 raise
325
326 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800327 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000328 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700329 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000330
331 self.assertEqual(len(capture), len(sent))
332
333 for i in range(len(capture)):
334 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800335 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000336 except:
337 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000338
Neale Ranns31ed7442018-02-23 05:29:09 -0800339 def verify_capture_ip6(self, src_if, capture, sent,
340 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000341 try:
342 self.assertEqual(len(capture), len(sent))
343
344 for i in range(len(capture)):
345 tx = sent[i]
346 rx = capture[i]
347
348 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000349 eth = rx[Ether]
350 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000351
352 tx_ip = tx[IPv6]
353 rx_ip = rx[IPv6]
354
355 self.assertEqual(rx_ip.src, tx_ip.src)
356 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800357 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000358 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800359 if not ip_hlim:
360 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
361 else:
362 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000363
364 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000365 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000366
Neale Ranns62fe07c2017-10-31 12:28:22 -0700367 def verify_capture_ip6_icmp(self, src_if, capture, sent):
368 try:
369 self.assertEqual(len(capture), len(sent))
370
371 for i in range(len(capture)):
372 tx = sent[i]
373 rx = capture[i]
374
375 # the rx'd packet has the MPLS label popped
376 eth = rx[Ether]
377 self.assertEqual(eth.type, 0x86DD)
378
379 tx_ip = tx[IPv6]
380 rx_ip = rx[IPv6]
381
382 self.assertEqual(rx_ip.dst, tx_ip.src)
383 # ICMP sourced from the interface's address
384 self.assertEqual(rx_ip.src, src_if.local_ip6)
385 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200386 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700387
388 icmp = rx[ICMPv6TimeExceeded]
389
390 except:
391 raise
392
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530393 def verify_capture_fragmented_labelled_ip4(self, src_if, capture, sent,
394 mpls_labels, ip_ttl=None):
395 try:
396 capture = verify_filter(capture, sent)
397
398 for i in range(len(capture)):
399 tx = sent[0]
400 rx = capture[i]
401 tx_ip = tx[IP]
402 rx_ip = rx[IP]
403
404 verify_mpls_stack(self, rx, mpls_labels)
405
406 self.assertEqual(rx_ip.src, tx_ip.src)
407 self.assertEqual(rx_ip.dst, tx_ip.dst)
408 if not ip_ttl:
409 # IP processing post pop has decremented the TTL
410 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
411 else:
412 self.assertEqual(rx_ip.ttl, ip_ttl)
413
414 except:
415 raise
416
Neale Rannsad422ed2016-11-02 14:20:04 +0000417 def test_swap(self):
418 """ MPLS label swap tests """
419
420 #
421 # A simple MPLS xconnect - eos label in label out
422 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800423 route_32_eos = VppMplsRoute(self, 32, 1,
424 [VppRoutePath(self.pg0.remote_ip4,
425 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800426 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000427 route_32_eos.add_vpp_config()
428
Neale Ranns775f73c2018-12-20 03:01:49 -0800429 self.assertTrue(
430 find_mpls_route(self, 0, 32, 1,
431 [VppRoutePath(self.pg0.remote_ip4,
432 self.pg0.sw_if_index,
433 labels=[VppMplsLabel(33)])]))
434
Neale Rannsad422ed2016-11-02 14:20:04 +0000435 #
436 # a stream that matches the route for 10.0.0.1
437 # PG0 is in the default table
438 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800439 tx = self.create_stream_labelled_ip4(self.pg0,
440 [VppMplsLabel(32, ttl=32, exp=1)])
441 rx = self.send_and_expect(self.pg0, tx, self.pg0)
442 self.verify_capture_labelled(self.pg0, rx, tx,
443 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000444
Neale Ranns008dbe12018-09-07 09:32:36 -0700445 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
446
Neale Rannsad422ed2016-11-02 14:20:04 +0000447 #
448 # A simple MPLS xconnect - non-eos label in label out
449 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800450 route_32_neos = VppMplsRoute(self, 32, 0,
451 [VppRoutePath(self.pg0.remote_ip4,
452 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800453 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000454 route_32_neos.add_vpp_config()
455
456 #
457 # a stream that matches the route for 10.0.0.1
458 # PG0 is in the default table
459 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800460 tx = self.create_stream_labelled_ip4(self.pg0,
461 [VppMplsLabel(32, ttl=21, exp=7),
462 VppMplsLabel(99)])
463 rx = self.send_and_expect(self.pg0, tx, self.pg0)
464 self.verify_capture_labelled(self.pg0, rx, tx,
465 [VppMplsLabel(33, ttl=20, exp=7),
466 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700467 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000468
Neale Ranns31ed7442018-02-23 05:29:09 -0800469 #
470 # A simple MPLS xconnect - non-eos label in label out, uniform mode
471 #
472 route_42_neos = VppMplsRoute(
473 self, 42, 0,
474 [VppRoutePath(self.pg0.remote_ip4,
475 self.pg0.sw_if_index,
476 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
477 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000478
Neale Ranns31ed7442018-02-23 05:29:09 -0800479 tx = self.create_stream_labelled_ip4(self.pg0,
480 [VppMplsLabel(42, ttl=21, exp=7),
481 VppMplsLabel(99)])
482 rx = self.send_and_expect(self.pg0, tx, self.pg0)
483 self.verify_capture_labelled(self.pg0, rx, tx,
484 [VppMplsLabel(43, ttl=20, exp=7),
485 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000486
487 #
488 # An MPLS xconnect - EOS label in IP out
489 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800490 route_33_eos = VppMplsRoute(self, 33, 1,
491 [VppRoutePath(self.pg0.remote_ip4,
492 self.pg0.sw_if_index,
493 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000494 route_33_eos.add_vpp_config()
495
Neale Ranns31ed7442018-02-23 05:29:09 -0800496 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
497 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000498 self.verify_capture_ip4(self.pg0, rx, tx)
499
500 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700501 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700502 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800503 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700504 dst_ip=self.pg0.remote_ip4,
505 n=65,
506 chksum=1)
507 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
508
509 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800510 # An MPLS xconnect - EOS label in IP out, uniform mode
511 #
512 route_3333_eos = VppMplsRoute(
513 self, 3333, 1,
514 [VppRoutePath(self.pg0.remote_ip4,
515 self.pg0.sw_if_index,
516 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
517 route_3333_eos.add_vpp_config()
518
519 tx = self.create_stream_labelled_ip4(
520 self.pg0,
521 [VppMplsLabel(3333, ttl=55, exp=3)])
522 rx = self.send_and_expect(self.pg0, tx, self.pg0)
523 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
524 tx = self.create_stream_labelled_ip4(
525 self.pg0,
526 [VppMplsLabel(3333, ttl=66, exp=4)])
527 rx = self.send_and_expect(self.pg0, tx, self.pg0)
528 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
529
530 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700531 # An MPLS xconnect - EOS label in IPv6 out
532 #
533 route_333_eos = VppMplsRoute(
534 self, 333, 1,
535 [VppRoutePath(self.pg0.remote_ip6,
536 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700537 labels=[])],
538 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700539 route_333_eos.add_vpp_config()
540
Neale Ranns31ed7442018-02-23 05:29:09 -0800541 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
542 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700543 self.verify_capture_ip6(self.pg0, rx, tx)
544
545 #
546 # disposed packets have an TTL expired
547 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800548 tx = self.create_stream_labelled_ip6(self.pg0,
549 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700550 dst_ip=self.pg1.remote_ip6,
551 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800552 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700553 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
554
555 #
556 # An MPLS xconnect - EOS label in IPv6 out w imp-null
557 #
558 route_334_eos = VppMplsRoute(
559 self, 334, 1,
560 [VppRoutePath(self.pg0.remote_ip6,
561 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700562 labels=[VppMplsLabel(3)])],
563 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700564 route_334_eos.add_vpp_config()
565
Neale Ranns31ed7442018-02-23 05:29:09 -0800566 tx = self.create_stream_labelled_ip6(self.pg0,
567 [VppMplsLabel(334, ttl=64)])
568 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700569 self.verify_capture_ip6(self.pg0, rx, tx)
570
571 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800572 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
573 #
574 route_335_eos = VppMplsRoute(
575 self, 335, 1,
576 [VppRoutePath(self.pg0.remote_ip6,
577 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700578 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
579 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 route_335_eos.add_vpp_config()
581
582 tx = self.create_stream_labelled_ip6(
583 self.pg0,
584 [VppMplsLabel(335, ttl=27, exp=4)])
585 rx = self.send_and_expect(self.pg0, tx, self.pg0)
586 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
587
588 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700589 # disposed packets have an TTL expired
590 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800591 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700592 dst_ip=self.pg1.remote_ip6,
593 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800594 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700595 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
596
597 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000598 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
599 # so this traffic should be dropped.
600 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800601 route_33_neos = VppMplsRoute(self, 33, 0,
602 [VppRoutePath(self.pg0.remote_ip4,
603 self.pg0.sw_if_index,
604 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000605 route_33_neos.add_vpp_config()
606
Neale Ranns31ed7442018-02-23 05:29:09 -0800607 tx = self.create_stream_labelled_ip4(self.pg0,
608 [VppMplsLabel(33),
609 VppMplsLabel(99)])
610 self.send_and_assert_no_replies(
611 self.pg0, tx,
612 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000613
614 #
615 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800616 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000617 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800618 route_34_eos = VppMplsRoute(self, 34, 1,
619 [VppRoutePath("0.0.0.0",
620 0xffffffff,
621 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800622 labels=[VppMplsLabel(44),
623 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000624 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700625 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000626
Neale Ranns31ed7442018-02-23 05:29:09 -0800627 tx = self.create_stream_labelled_ip4(self.pg0,
628 [VppMplsLabel(34, ttl=3)])
629 rx = self.send_and_expect(self.pg0, tx, self.pg0)
630 self.verify_capture_labelled(self.pg0, rx, tx,
631 [VppMplsLabel(33),
632 VppMplsLabel(44),
633 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000634
Neale Ranns008dbe12018-09-07 09:32:36 -0700635 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
636 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
637
Neale Ranns31ed7442018-02-23 05:29:09 -0800638 #
639 # A recursive EOS x-connect, which resolves through another x-connect
640 # in uniform mode
641 #
642 route_35_eos = VppMplsRoute(
643 self, 35, 1,
644 [VppRoutePath("0.0.0.0",
645 0xffffffff,
646 nh_via_label=42,
647 labels=[VppMplsLabel(44)])])
648 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000649
Neale Ranns31ed7442018-02-23 05:29:09 -0800650 tx = self.create_stream_labelled_ip4(self.pg0,
651 [VppMplsLabel(35, ttl=3)])
652 rx = self.send_and_expect(self.pg0, tx, self.pg0)
653 self.verify_capture_labelled(self.pg0, rx, tx,
654 [VppMplsLabel(43, ttl=2),
655 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000656
657 #
Matej Klottondeb69842016-12-09 15:05:46 +0100658 # A recursive non-EOS x-connect, which resolves through another
659 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000660 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800661 route_34_neos = VppMplsRoute(self, 34, 0,
662 [VppRoutePath("0.0.0.0",
663 0xffffffff,
664 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800665 labels=[VppMplsLabel(44),
666 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000667 route_34_neos.add_vpp_config()
668
Neale Ranns31ed7442018-02-23 05:29:09 -0800669 tx = self.create_stream_labelled_ip4(self.pg0,
670 [VppMplsLabel(34, ttl=45),
671 VppMplsLabel(99)])
672 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100673 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800674 self.verify_capture_labelled(self.pg0, rx, tx,
675 [VppMplsLabel(33),
676 VppMplsLabel(44),
677 VppMplsLabel(46, ttl=44),
678 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000679
680 #
Matej Klottondeb69842016-12-09 15:05:46 +0100681 # an recursive IP route that resolves through the recursive non-eos
682 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000683 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800684 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
685 [VppRoutePath("0.0.0.0",
686 0xffffffff,
687 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800688 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000689 ip_10_0_0_1.add_vpp_config()
690
Neale Rannsad422ed2016-11-02 14:20:04 +0000691 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800692 rx = self.send_and_expect(self.pg0, tx, self.pg0)
693 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
694 [VppMplsLabel(33),
695 VppMplsLabel(44),
696 VppMplsLabel(46),
697 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700698 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000699
700 ip_10_0_0_1.remove_vpp_config()
701 route_34_neos.remove_vpp_config()
702 route_34_eos.remove_vpp_config()
703 route_33_neos.remove_vpp_config()
704 route_33_eos.remove_vpp_config()
705 route_32_neos.remove_vpp_config()
706 route_32_eos.remove_vpp_config()
707
708 def test_bind(self):
709 """ MPLS Local Label Binding test """
710
711 #
712 # Add a non-recursive route with a single out label
713 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800714 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
715 [VppRoutePath(self.pg0.remote_ip4,
716 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800717 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000718 route_10_0_0_1.add_vpp_config()
719
720 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800721 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000722 binding.add_vpp_config()
723
724 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800725 tx = self.create_stream_labelled_ip4(self.pg0,
726 [VppMplsLabel(44),
727 VppMplsLabel(99)])
728 rx = self.send_and_expect(self.pg0, tx, self.pg0)
729 self.verify_capture_labelled(self.pg0, rx, tx,
730 [VppMplsLabel(45, ttl=63),
731 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000732
733 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800734 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
735 rx = self.send_and_expect(self.pg0, tx, self.pg0)
736 self.verify_capture_labelled(self.pg0, rx, tx,
737 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000738
739 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000740 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800741 rx = self.send_and_expect(self.pg0, tx, self.pg0)
742 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000743
744 #
745 # cleanup
746 #
747 binding.remove_vpp_config()
748 route_10_0_0_1.remove_vpp_config()
749
750 def test_imposition(self):
751 """ MPLS label imposition test """
752
753 #
754 # Add a non-recursive route with a single out label
755 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800756 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
757 [VppRoutePath(self.pg0.remote_ip4,
758 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800759 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000760 route_10_0_0_1.add_vpp_config()
761
762 #
763 # a stream that matches the route for 10.0.0.1
764 # PG0 is in the default table
765 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000766 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800767 rx = self.send_and_expect(self.pg0, tx, self.pg0)
768 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000769
770 #
771 # Add a non-recursive route with a 3 out labels
772 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800773 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
774 [VppRoutePath(self.pg0.remote_ip4,
775 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800776 labels=[VppMplsLabel(32),
777 VppMplsLabel(33),
778 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000779 route_10_0_0_2.add_vpp_config()
780
Neale Ranns31ed7442018-02-23 05:29:09 -0800781 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
782 ip_ttl=44, ip_dscp=0xff)
783 rx = self.send_and_expect(self.pg0, tx, self.pg0)
784 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
785 [VppMplsLabel(32),
786 VppMplsLabel(33),
787 VppMplsLabel(34)],
788 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000789
Neale Ranns31ed7442018-02-23 05:29:09 -0800790 #
791 # Add a non-recursive route with a single out label in uniform mode
792 #
793 route_10_0_0_3 = VppIpRoute(
794 self, "10.0.0.3", 32,
795 [VppRoutePath(self.pg0.remote_ip4,
796 self.pg0.sw_if_index,
797 labels=[VppMplsLabel(32,
798 mode=MplsLspMode.UNIFORM)])])
799 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000800
Neale Ranns31ed7442018-02-23 05:29:09 -0800801 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
802 ip_ttl=54, ip_dscp=0xbe)
803 rx = self.send_and_expect(self.pg0, tx, self.pg0)
804 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
805 [VppMplsLabel(32, ttl=53, exp=5)])
806
807 #
808 # Add a IPv6 non-recursive route with a single out label in
809 # uniform mode
810 #
811 route_2001_3 = VppIpRoute(
812 self, "2001::3", 128,
813 [VppRoutePath(self.pg0.remote_ip6,
814 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800815 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700816 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800817 route_2001_3.add_vpp_config()
818
819 tx = self.create_stream_ip6(self.pg0, "2001::3",
820 ip_ttl=54, ip_dscp=0xbe)
821 rx = self.send_and_expect(self.pg0, tx, self.pg0)
822 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
823 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000824
825 #
Matej Klottondeb69842016-12-09 15:05:46 +0100826 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000827 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800828 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
829 [VppRoutePath("10.0.0.1",
830 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800831 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000832 route_11_0_0_1.add_vpp_config()
833
834 #
835 # a stream that matches the route for 11.0.0.1, should pick up
836 # the label stack for 11.0.0.1 and 10.0.0.1
837 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000838 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800839 rx = self.send_and_expect(self.pg0, tx, self.pg0)
840 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
841 [VppMplsLabel(32),
842 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000843
Neale Ranns008dbe12018-09-07 09:32:36 -0700844 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
845
Neale Rannsad422ed2016-11-02 14:20:04 +0000846 #
847 # add a recursive path, with 2 labels, via the 3 label route
848 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800849 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
850 [VppRoutePath("10.0.0.2",
851 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800852 labels=[VppMplsLabel(44),
853 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000854 route_11_0_0_2.add_vpp_config()
855
856 #
857 # a stream that matches the route for 11.0.0.1, should pick up
858 # the label stack for 11.0.0.1 and 10.0.0.1
859 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000860 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800861 rx = self.send_and_expect(self.pg0, tx, self.pg0)
862 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
863 [VppMplsLabel(32),
864 VppMplsLabel(33),
865 VppMplsLabel(34),
866 VppMplsLabel(44),
867 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000868
Neale Ranns008dbe12018-09-07 09:32:36 -0700869 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
870
871 rx = self.send_and_expect(self.pg0, tx, self.pg0)
872 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
873 [VppMplsLabel(32),
874 VppMplsLabel(33),
875 VppMplsLabel(34),
876 VppMplsLabel(44),
877 VppMplsLabel(45)])
878
879 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
880
Neale Rannsad422ed2016-11-02 14:20:04 +0000881 #
882 # cleanup
883 #
884 route_11_0_0_2.remove_vpp_config()
885 route_11_0_0_1.remove_vpp_config()
886 route_10_0_0_2.remove_vpp_config()
887 route_10_0_0_1.remove_vpp_config()
888
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530889 def test_imposition_fragmentation(self):
890 """ MPLS label imposition fragmentation test """
891
892 #
893 # Add a ipv4 non-recursive route with a single out label
894 #
895 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
896 [VppRoutePath(self.pg0.remote_ip4,
897 self.pg0.sw_if_index,
898 labels=[VppMplsLabel(32)])])
899 route_10_0_0_1.add_vpp_config()
900
901 #
902 # a stream that matches the route for 10.0.0.1
903 # PG0 is in the default table
904 #
905 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
906 for i in range(0, 257):
907 self.extend_packet(tx[i], 10000)
908
909 #
910 # 5 fragments per packet (257*5=1285)
911 #
912 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
913 self.verify_capture_fragmented_labelled_ip4(self.pg0, rx, tx,
914 [VppMplsLabel(32)])
915
916 #
917 # cleanup
918 #
919 route_10_0_0_1.remove_vpp_config()
920
Neale Ranns31ed7442018-02-23 05:29:09 -0800921 def test_tunnel_pipe(self):
922 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000923
924 #
Ole Troaneb284a12019-10-09 13:33:19 +0200925 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +0000926 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800927 mpls_tun = VppMPLSTunnelInterface(
928 self,
929 [VppRoutePath(self.pg0.remote_ip4,
930 self.pg0.sw_if_index,
931 labels=[VppMplsLabel(44),
932 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800933 mpls_tun.add_vpp_config()
934 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000935
936 #
937 # add an unlabelled route through the new tunnel
938 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800939 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
940 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800941 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800942 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000943
944 self.vapi.cli("clear trace")
945 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
946 self.pg0.add_stream(tx)
947
948 self.pg_enable_capture(self.pg_interfaces)
949 self.pg_start()
950
951 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800952 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
953 [VppMplsLabel(44),
954 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000955
Neale Ranns8c4611b2017-05-23 03:43:47 -0700956 #
957 # add a labelled route through the new tunnel
958 #
959 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
960 [VppRoutePath("0.0.0.0",
961 mpls_tun._sw_if_index,
962 labels=[33])])
963 route_10_0_0_4.add_vpp_config()
964
965 self.vapi.cli("clear trace")
966 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
967 self.pg0.add_stream(tx)
968
969 self.pg_enable_capture(self.pg_interfaces)
970 self.pg_start()
971
972 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800973 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
974 [VppMplsLabel(44),
975 VppMplsLabel(46),
976 VppMplsLabel(33, ttl=255)])
977
Ole Troaneb284a12019-10-09 13:33:19 +0200978 #
979 # change tunnel's MTU to a low value
980 #
981 mpls_tun.set_l3_mtu(1200)
982
983 # send IP into the tunnel to be fragmented
984 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
985 payload_size=1500)
986 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
987
988 fake_tx = []
989 for p in tx:
990 fake_tx.append(p)
991 fake_tx.append(p)
992 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
993 [VppMplsLabel(44),
994 VppMplsLabel(46)])
995
996 # send MPLS into the tunnel to be fragmented
997 tx = self.create_stream_ip4(self.pg0, "10.0.0.4",
998 payload_size=1500)
999 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
1000
1001 fake_tx = []
1002 for p in tx:
1003 fake_tx.append(p)
1004 fake_tx.append(p)
1005 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1006 [VppMplsLabel(44),
1007 VppMplsLabel(46),
1008 VppMplsLabel(33, ttl=255)])
1009
Neale Ranns31ed7442018-02-23 05:29:09 -08001010 def test_tunnel_uniform(self):
1011 """ MPLS Tunnel Tests - Uniform """
1012
1013 #
1014 # Create a tunnel with a single out label
1015 # The label stack is specified here from outer to inner
1016 #
1017 mpls_tun = VppMPLSTunnelInterface(
1018 self,
1019 [VppRoutePath(self.pg0.remote_ip4,
1020 self.pg0.sw_if_index,
1021 labels=[VppMplsLabel(44, ttl=32),
1022 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1023 mpls_tun.add_vpp_config()
1024 mpls_tun.admin_up()
1025
1026 #
1027 # add an unlabelled route through the new tunnel
1028 #
1029 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1030 [VppRoutePath("0.0.0.0",
1031 mpls_tun._sw_if_index)])
1032 route_10_0_0_3.add_vpp_config()
1033
1034 self.vapi.cli("clear trace")
1035 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
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()
1042 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1043 [VppMplsLabel(44, ttl=32),
1044 VppMplsLabel(46, ttl=23)])
1045
1046 #
1047 # add a labelled route through the new tunnel
1048 #
1049 route_10_0_0_4 = VppIpRoute(
1050 self, "10.0.0.4", 32,
1051 [VppRoutePath("0.0.0.0",
1052 mpls_tun._sw_if_index,
1053 labels=[VppMplsLabel(33, ttl=47)])])
1054 route_10_0_0_4.add_vpp_config()
1055
1056 self.vapi.cli("clear trace")
1057 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1058 self.pg0.add_stream(tx)
1059
1060 self.pg_enable_capture(self.pg_interfaces)
1061 self.pg_start()
1062
1063 rx = self.pg0.get_capture()
1064 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1065 [VppMplsLabel(44, ttl=32),
1066 VppMplsLabel(46, ttl=47),
1067 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001068
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001069 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001070 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001071
Neale Ranns397228d2021-10-21 12:02:53 +00001072 for ii in range(100):
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001073 mpls_tun = VppMPLSTunnelInterface(
1074 self,
1075 [VppRoutePath(self.pg0.remote_ip4,
1076 self.pg0.sw_if_index,
1077 labels=[VppMplsLabel(44, ttl=32),
1078 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1079 mpls_tun.add_vpp_config()
1080 mpls_tun.admin_up()
Neale Ranns397228d2021-10-21 12:02:53 +00001081 for ii in range(100):
1082 mpls_tun = VppMPLSTunnelInterface(
1083 self,
1084 [VppRoutePath(self.pg0.remote_ip4,
1085 self.pg0.sw_if_index,
1086 labels=[VppMplsLabel(44, ttl=32),
1087 VppMplsLabel(46, MplsLspMode.UNIFORM)])],
1088 is_l2=1)
1089 mpls_tun.add_vpp_config()
1090 mpls_tun.admin_up()
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001091
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001092 def test_v4_exp_null(self):
1093 """ MPLS V4 Explicit NULL test """
1094
1095 #
1096 # The first test case has an MPLS TTL of 0
1097 # all packet should be dropped
1098 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001099 tx = self.create_stream_labelled_ip4(self.pg0,
1100 [VppMplsLabel(0, ttl=0)])
1101 self.send_and_assert_no_replies(self.pg0, tx,
1102 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001103
1104 #
1105 # a stream with a non-zero MPLS TTL
1106 # PG0 is in the default table
1107 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001108 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1109 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001110 self.verify_capture_ip4(self.pg0, rx, tx)
1111
1112 #
1113 # a stream with a non-zero MPLS TTL
1114 # PG1 is in table 1
1115 # we are ensuring the post-pop lookup occurs in the VRF table
1116 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001117 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1118 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1119 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001120
1121 def test_v6_exp_null(self):
1122 """ MPLS V6 Explicit NULL test """
1123
1124 #
1125 # a stream with a non-zero MPLS TTL
1126 # PG0 is in the default table
1127 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001128 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1129 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001130 self.verify_capture_ip6(self.pg0, rx, tx)
1131
1132 #
1133 # a stream with a non-zero MPLS TTL
1134 # PG1 is in table 1
1135 # we are ensuring the post-pop lookup occurs in the VRF table
1136 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001137 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1138 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001139 self.verify_capture_ip6(self.pg0, rx, tx)
1140
Neale Rannscb630ff2016-12-14 13:31:29 +01001141 def test_deag(self):
1142 """ MPLS Deagg """
1143
1144 #
1145 # A de-agg route - next-hop lookup in default table
1146 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001147 route_34_eos = VppMplsRoute(self, 34, 1,
1148 [VppRoutePath("0.0.0.0",
1149 0xffffffff,
1150 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001151 route_34_eos.add_vpp_config()
1152
1153 #
1154 # ping an interface in the default table
1155 # PG0 is in the default table
1156 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001157 tx = self.create_stream_labelled_ip4(self.pg0,
1158 [VppMplsLabel(34)],
1159 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001160 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001161 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001162 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1163
1164 #
1165 # A de-agg route - next-hop lookup in non-default table
1166 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001167 route_35_eos = VppMplsRoute(self, 35, 1,
1168 [VppRoutePath("0.0.0.0",
1169 0xffffffff,
1170 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001171 route_35_eos.add_vpp_config()
1172
1173 #
1174 # ping an interface in the non-default table
1175 # PG0 is in the default table. packet arrive labelled in the
1176 # default table and egress unlabelled in the non-default
1177 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001178 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001179 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1180 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001181 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1182
Neale Ranns6af1c042017-05-26 03:48:53 -07001183 #
1184 # Double pop
1185 #
1186 route_36_neos = VppMplsRoute(self, 36, 0,
1187 [VppRoutePath("0.0.0.0",
1188 0xffffffff)])
1189 route_36_neos.add_vpp_config()
1190
Neale Ranns31ed7442018-02-23 05:29:09 -08001191 tx = self.create_stream_labelled_ip4(self.pg0,
1192 [VppMplsLabel(36),
1193 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001194 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001195 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001196 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1197
1198 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001199 route_35_eos.remove_vpp_config()
1200 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001201
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001202 def test_interface_rx(self):
1203 """ MPLS Interface Receive """
1204
1205 #
1206 # Add a non-recursive route that will forward the traffic
1207 # post-interface-rx
1208 #
1209 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1210 table_id=1,
1211 paths=[VppRoutePath(self.pg1.remote_ip4,
1212 self.pg1.sw_if_index)])
1213 route_10_0_0_1.add_vpp_config()
1214
1215 #
1216 # An interface receive label that maps traffic to RX on interface
1217 # pg1
1218 # by injecting the packet in on pg0, which is in table 0
1219 # doing an interface-rx on pg1 and matching a route in table 1
1220 # if the packet egresses, then we must have swapped to pg1
1221 # so as to have matched the route in table 1
1222 #
Neale Ranns097fa662018-05-01 05:17:55 -07001223 route_34_eos = VppMplsRoute(
1224 self, 34, 1,
1225 [VppRoutePath("0.0.0.0",
1226 self.pg1.sw_if_index,
1227 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001228 route_34_eos.add_vpp_config()
1229
1230 #
1231 # ping an interface in the default table
1232 # PG0 is in the default table
1233 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001234 tx = self.create_stream_labelled_ip4(self.pg0,
1235 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001236 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001237 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001238 self.verify_capture_ip4(self.pg1, rx, tx)
1239
1240 def test_mcast_mid_point(self):
1241 """ MPLS Multicast Mid Point """
1242
1243 #
1244 # Add a non-recursive route that will forward the traffic
1245 # post-interface-rx
1246 #
1247 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1248 table_id=1,
1249 paths=[VppRoutePath(self.pg1.remote_ip4,
1250 self.pg1.sw_if_index)])
1251 route_10_0_0_1.add_vpp_config()
1252
1253 #
1254 # Add a mcast entry that replicate to pg2 and pg3
1255 # and replicate to a interface-rx (like a bud node would)
1256 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001257 route_3400_eos = VppMplsRoute(
1258 self, 3400, 1,
1259 [VppRoutePath(self.pg2.remote_ip4,
1260 self.pg2.sw_if_index,
1261 labels=[VppMplsLabel(3401)]),
1262 VppRoutePath(self.pg3.remote_ip4,
1263 self.pg3.sw_if_index,
1264 labels=[VppMplsLabel(3402)]),
1265 VppRoutePath("0.0.0.0",
1266 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001267 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001268 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001269 route_3400_eos.add_vpp_config()
1270
1271 #
1272 # ping an interface in the default table
1273 # PG0 is in the default table
1274 #
1275 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001276 tx = self.create_stream_labelled_ip4(self.pg0,
1277 [VppMplsLabel(3400, ttl=64)],
1278 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001279 dst_ip="10.0.0.1")
1280 self.pg0.add_stream(tx)
1281
1282 self.pg_enable_capture(self.pg_interfaces)
1283 self.pg_start()
1284
1285 rx = self.pg1.get_capture(257)
1286 self.verify_capture_ip4(self.pg1, rx, tx)
1287
1288 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001289 self.verify_capture_labelled(self.pg2, rx, tx,
1290 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001291 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001292 self.verify_capture_labelled(self.pg3, rx, tx,
1293 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001294
1295 def test_mcast_head(self):
1296 """ MPLS Multicast Head-end """
1297
Neale Ranns990f6942020-10-20 07:20:17 +00001298 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1299 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1300
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001301 #
1302 # Create a multicast tunnel with two replications
1303 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001304 mpls_tun = VppMPLSTunnelInterface(
1305 self,
1306 [VppRoutePath(self.pg2.remote_ip4,
1307 self.pg2.sw_if_index,
1308 labels=[VppMplsLabel(42)]),
1309 VppRoutePath(self.pg3.remote_ip4,
1310 self.pg3.sw_if_index,
1311 labels=[VppMplsLabel(43)])],
1312 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001313 mpls_tun.add_vpp_config()
1314 mpls_tun.admin_up()
1315
1316 #
1317 # add an unlabelled route through the new tunnel
1318 #
1319 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1320 [VppRoutePath("0.0.0.0",
1321 mpls_tun._sw_if_index)])
1322 route_10_0_0_3.add_vpp_config()
1323
1324 self.vapi.cli("clear trace")
1325 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1326 self.pg0.add_stream(tx)
1327
1328 self.pg_enable_capture(self.pg_interfaces)
1329 self.pg_start()
1330
1331 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001332 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001333 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001334 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001335
1336 #
1337 # An an IP multicast route via the tunnel
1338 # A (*,G).
1339 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1340 #
1341 route_232_1_1_1 = VppIpMRoute(
1342 self,
1343 "0.0.0.0",
1344 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001345 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001346 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001347 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001348 VppMRoutePath(mpls_tun._sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001349 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001350 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001351 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001352
1353 self.vapi.cli("clear trace")
1354 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1355 self.pg0.add_stream(tx)
1356
1357 self.pg_enable_capture(self.pg_interfaces)
1358 self.pg_start()
1359
1360 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001361 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001362 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001363 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001364
Neale Ranns31426c62017-05-24 10:32:58 -07001365 def test_mcast_ip4_tail(self):
1366 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001367
Neale Ranns990f6942020-10-20 07:20:17 +00001368 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1369 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1370
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001371 #
1372 # Add a multicast route that will forward the traffic
1373 # post-disposition
1374 #
1375 route_232_1_1_1 = VppIpMRoute(
1376 self,
1377 "0.0.0.0",
1378 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001379 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001380 table_id=1,
1381 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001382 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001383 route_232_1_1_1.add_vpp_config()
1384
1385 #
1386 # An interface receive label that maps traffic to RX on interface
1387 # pg1
1388 # by injecting the packet in on pg0, which is in table 0
1389 # doing an rpf-id and matching a route in table 1
1390 # if the packet egresses, then we must have matched the route in
1391 # table 1
1392 #
Neale Ranns097fa662018-05-01 05:17:55 -07001393 route_34_eos = VppMplsRoute(
1394 self, 34, 1,
1395 [VppRoutePath("0.0.0.0",
1396 0xffffffff,
1397 nh_table_id=1,
1398 rpf_id=55)],
1399 is_multicast=1,
1400 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001401
1402 route_34_eos.add_vpp_config()
1403
1404 #
1405 # Drop due to interface lookup miss
1406 #
1407 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001408 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001409 dst_ip="232.1.1.1", n=1)
1410 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1411
1412 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001413 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001414 #
1415 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001416 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001417
Neale Ranns31ed7442018-02-23 05:29:09 -08001418 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1419 dst_ip="232.1.1.1")
1420 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001421 self.verify_capture_ip4(self.pg1, rx, tx)
1422
1423 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001424 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001425 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001426 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001427 dst_ip="232.1.1.1", n=65,
1428 chksum=1)
1429 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1430
1431 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001432 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001433 #
1434 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001435 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001436 dst_ip="232.1.1.1")
1437 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1438
Neale Ranns31426c62017-05-24 10:32:58 -07001439 def test_mcast_ip6_tail(self):
1440 """ MPLS IPv6 Multicast Tail """
1441
Neale Ranns990f6942020-10-20 07:20:17 +00001442 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1443 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1444
Neale Ranns31426c62017-05-24 10:32:58 -07001445 #
1446 # Add a multicast route that will forward the traffic
1447 # post-disposition
1448 #
1449 route_ff = VppIpMRoute(
1450 self,
1451 "::",
1452 "ff01::1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001453 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001454 table_id=1,
1455 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001456 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001457 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001458 route_ff.add_vpp_config()
1459
1460 #
1461 # An interface receive label that maps traffic to RX on interface
1462 # pg1
1463 # by injecting the packet in on pg0, which is in table 0
1464 # doing an rpf-id and matching a route in table 1
1465 # if the packet egresses, then we must have matched the route in
1466 # table 1
1467 #
1468 route_34_eos = VppMplsRoute(
1469 self, 34, 1,
1470 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001471 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001472 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001473 rpf_id=55)],
1474 is_multicast=1,
1475 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001476
1477 route_34_eos.add_vpp_config()
1478
1479 #
1480 # Drop due to interface lookup miss
1481 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001482 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001483 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001484 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001485
1486 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001487 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001488 #
1489 route_ff.update_rpf_id(55)
1490
Neale Ranns31ed7442018-02-23 05:29:09 -08001491 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001492 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001493 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001494 self.verify_capture_ip6(self.pg1, rx, tx)
1495
1496 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001497 # disposed packets have hop-limit = 1
1498 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001499 tx = self.create_stream_labelled_ip6(self.pg0,
1500 [VppMplsLabel(34)],
1501 dst_ip="ff01::1",
1502 hlim=1)
1503 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001504 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001505
1506 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001507 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001508 #
1509 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001510 tx = self.create_stream_labelled_ip6(self.pg0,
1511 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001512 dst_ip="ff01::1")
1513 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1514
Neale Rannsd5d7b962019-08-04 03:30:56 -07001515 def test_6pe(self):
1516 """ MPLS 6PE """
1517
1518 #
1519 # Add a non-recursive route with a single out label
1520 #
1521 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1522 [VppRoutePath(self.pg0.remote_ip4,
1523 self.pg0.sw_if_index,
1524 labels=[VppMplsLabel(45)])])
1525 route_10_0_0_1.add_vpp_config()
1526
1527 # bind a local label to the route
1528 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1529 binding.add_vpp_config()
1530
1531 #
1532 # a labelled v6 route that resolves through the v4
1533 #
1534 route_2001_3 = VppIpRoute(
1535 self, "2001::3", 128,
1536 [VppRoutePath("10.0.0.1",
1537 INVALID_INDEX,
1538 labels=[VppMplsLabel(32)])])
1539 route_2001_3.add_vpp_config()
1540
1541 tx = self.create_stream_ip6(self.pg0, "2001::3")
1542 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1543
1544 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1545 [VppMplsLabel(45),
1546 VppMplsLabel(32)])
1547
1548 #
1549 # and a v4 recursive via the v6
1550 #
1551 route_20_3 = VppIpRoute(
1552 self, "20.0.0.3", 32,
1553 [VppRoutePath("2001::3",
1554 INVALID_INDEX,
1555 labels=[VppMplsLabel(99)])])
1556 route_20_3.add_vpp_config()
1557
1558 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1559 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1560
1561 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1562 [VppMplsLabel(45),
1563 VppMplsLabel(32),
1564 VppMplsLabel(99)])
1565
Neale Ranns53962fb2021-12-20 18:18:42 +00001566 def test_attached(self):
1567 """ Attach Routes with Local Label """
1568
1569 #
1570 # test that if a local label is associated with an attached/connected
1571 # prefix, that we can reach hosts in the prefix.
1572 #
1573 binding = VppMplsIpBind(self, 44,
1574 self.pg0._local_ip4_subnet,
1575 self.pg0.local_ip4_prefix_len)
1576 binding.add_vpp_config()
1577
1578 tx = (Ether(src=self.pg1.remote_mac,
1579 dst=self.pg1.local_mac) /
1580 MPLS(label=44, ttl=64) /
1581 IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
1582 UDP(sport=1234, dport=1234) /
1583 Raw(b'\xa5' * 100))
1584 rxs = self.send_and_expect(self.pg0, [tx], self.pg0)
1585 for rx in rxs:
1586 # if there's an ARP then the label is linked to the glean
1587 # which is wrong.
1588 self.assertFalse(rx.haslayer(ARP))
1589 # it should be unicasted to the host
1590 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1591 self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
1592
Neale Ranns180279b2017-03-16 15:49:09 -04001593
1594class TestMPLSDisabled(VppTestCase):
1595 """ MPLS disabled """
1596
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001597 @classmethod
1598 def setUpClass(cls):
1599 super(TestMPLSDisabled, cls).setUpClass()
1600
1601 @classmethod
1602 def tearDownClass(cls):
1603 super(TestMPLSDisabled, cls).tearDownClass()
1604
Neale Ranns180279b2017-03-16 15:49:09 -04001605 def setUp(self):
1606 super(TestMPLSDisabled, self).setUp()
1607
1608 # create 2 pg interfaces
1609 self.create_pg_interfaces(range(2))
1610
Neale Ranns15002542017-09-10 04:39:11 -07001611 self.tbl = VppMplsTable(self, 0)
1612 self.tbl.add_vpp_config()
1613
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001614 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001615 self.pg0.admin_up()
1616 self.pg0.config_ip4()
1617 self.pg0.resolve_arp()
1618 self.pg0.enable_mpls()
1619
1620 # PG 1 is not MPLS enabled
1621 self.pg1.admin_up()
1622
1623 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001624 for i in self.pg_interfaces:
1625 i.unconfig_ip4()
1626 i.admin_down()
1627
Neale Ranns15002542017-09-10 04:39:11 -07001628 self.pg0.disable_mpls()
1629 super(TestMPLSDisabled, self).tearDown()
1630
Neale Ranns180279b2017-03-16 15:49:09 -04001631 def test_mpls_disabled(self):
1632 """ MPLS Disabled """
1633
Neale Rannsde0b3b52021-06-15 12:43:12 +00001634 self.logger.info(self.vapi.cli("show mpls interface"))
1635 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1636 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1637
Neale Ranns180279b2017-03-16 15:49:09 -04001638 tx = (Ether(src=self.pg1.remote_mac,
1639 dst=self.pg1.local_mac) /
1640 MPLS(label=32, ttl=64) /
1641 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1642 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001643 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001644
1645 #
1646 # A simple MPLS xconnect - eos label in label out
1647 #
1648 route_32_eos = VppMplsRoute(self, 32, 1,
1649 [VppRoutePath(self.pg0.remote_ip4,
1650 self.pg0.sw_if_index,
1651 labels=[33])])
1652 route_32_eos.add_vpp_config()
1653
1654 #
1655 # PG1 does not forward IP traffic
1656 #
1657 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1658
1659 #
1660 # MPLS enable PG1
1661 #
1662 self.pg1.enable_mpls()
1663
Neale Rannsde0b3b52021-06-15 12:43:12 +00001664 self.logger.info(self.vapi.cli("show mpls interface"))
1665 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1666
Neale Ranns180279b2017-03-16 15:49:09 -04001667 #
1668 # Now we get packets through
1669 #
1670 self.pg1.add_stream(tx)
1671 self.pg_enable_capture(self.pg_interfaces)
1672 self.pg_start()
1673
1674 rx = self.pg0.get_capture(1)
1675
1676 #
1677 # Disable PG1
1678 #
1679 self.pg1.disable_mpls()
1680
1681 #
1682 # PG1 does not forward IP traffic
1683 #
1684 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1685 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1686
1687
Neale Rannsf12a83f2017-04-18 09:09:40 -07001688class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001689 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001690
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001691 @classmethod
1692 def setUpClass(cls):
1693 super(TestMPLSPIC, cls).setUpClass()
1694
1695 @classmethod
1696 def tearDownClass(cls):
1697 super(TestMPLSPIC, cls).tearDownClass()
1698
Neale Rannsf12a83f2017-04-18 09:09:40 -07001699 def setUp(self):
1700 super(TestMPLSPIC, self).setUp()
1701
1702 # create 2 pg interfaces
1703 self.create_pg_interfaces(range(4))
1704
Neale Ranns15002542017-09-10 04:39:11 -07001705 mpls_tbl = VppMplsTable(self, 0)
1706 mpls_tbl.add_vpp_config()
1707 tbl4 = VppIpTable(self, 1)
1708 tbl4.add_vpp_config()
1709 tbl6 = VppIpTable(self, 1, is_ip6=1)
1710 tbl6.add_vpp_config()
1711
Neale Rannsf12a83f2017-04-18 09:09:40 -07001712 # core links
1713 self.pg0.admin_up()
1714 self.pg0.config_ip4()
1715 self.pg0.resolve_arp()
1716 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001717
Neale Rannsf12a83f2017-04-18 09:09:40 -07001718 self.pg1.admin_up()
1719 self.pg1.config_ip4()
1720 self.pg1.resolve_arp()
1721 self.pg1.enable_mpls()
1722
1723 # VRF (customer facing) link
1724 self.pg2.admin_up()
1725 self.pg2.set_table_ip4(1)
1726 self.pg2.config_ip4()
1727 self.pg2.resolve_arp()
1728 self.pg2.set_table_ip6(1)
1729 self.pg2.config_ip6()
1730 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001731
Neale Rannsf12a83f2017-04-18 09:09:40 -07001732 self.pg3.admin_up()
1733 self.pg3.set_table_ip4(1)
1734 self.pg3.config_ip4()
1735 self.pg3.resolve_arp()
1736 self.pg3.set_table_ip6(1)
1737 self.pg3.config_ip6()
1738 self.pg3.resolve_ndp()
1739
1740 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001741 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001742 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001743 for i in self.pg_interfaces:
1744 i.unconfig_ip4()
1745 i.unconfig_ip6()
1746 i.set_table_ip4(0)
1747 i.set_table_ip6(0)
1748 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001749 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001750
1751 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001752 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001753
1754 1) setup many iBGP VPN routes via a pair of iBGP peers.
1755 2) Check EMCP forwarding to these peers
1756 3) withdraw the IGP route to one of these peers.
1757 4) check forwarding continues to the remaining peer
1758 """
1759
1760 #
1761 # IGP+LDP core routes
1762 #
1763 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1764 [VppRoutePath(self.pg0.remote_ip4,
1765 self.pg0.sw_if_index,
1766 labels=[45])])
1767 core_10_0_0_45.add_vpp_config()
1768
1769 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1770 [VppRoutePath(self.pg1.remote_ip4,
1771 self.pg1.sw_if_index,
1772 labels=[46])])
1773 core_10_0_0_46.add_vpp_config()
1774
1775 #
1776 # Lot's of VPN routes. We need more the 64 so VPP will build
1777 # the fast convergence indirection
1778 #
1779 vpn_routes = []
1780 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001781 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001782 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001783 vpn_routes.append(VppIpRoute(
1784 self, dst, 32,
1785 [VppRoutePath(
1786 "10.0.0.45",
1787 0xffffffff,
1788 labels=[145],
1789 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1790 VppRoutePath(
1791 "10.0.0.46",
1792 0xffffffff,
1793 labels=[146],
1794 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1795 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001796 vpn_routes[ii].add_vpp_config()
1797
1798 pkts.append(Ether(dst=self.pg2.local_mac,
1799 src=self.pg2.remote_mac) /
1800 IP(src=self.pg2.remote_ip4, dst=dst) /
1801 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001802 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001803
1804 #
1805 # Send the packet stream (one pkt to each VPN route)
1806 # - expect a 50-50 split of the traffic
1807 #
1808 self.pg2.add_stream(pkts)
1809 self.pg_enable_capture(self.pg_interfaces)
1810 self.pg_start()
1811
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001812 rx0 = self.pg0._get_capture(NUM_PKTS)
1813 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001814
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001815 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001816 # with the split ratio, just as long as neither is 0
1817 self.assertNotEqual(0, len(rx0))
1818 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001819 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1820 "Expected all (%s) packets across both ECMP paths. "
1821 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001822
1823 #
1824 # use a test CLI command to stop the FIB walk process, this
1825 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001826 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001827 #
1828 self.vapi.ppcli("test fib-walk-process disable")
1829
1830 #
1831 # Withdraw one of the IGP routes
1832 #
1833 core_10_0_0_46.remove_vpp_config()
1834
1835 #
1836 # now all packets should be forwarded through the remaining peer
1837 #
1838 self.vapi.ppcli("clear trace")
1839 self.pg2.add_stream(pkts)
1840 self.pg_enable_capture(self.pg_interfaces)
1841 self.pg_start()
1842
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001843 rx0 = self.pg0.get_capture(NUM_PKTS)
1844 self.assertEqual(len(pkts), len(rx0),
1845 "Expected all (%s) packets across single path. "
1846 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001847
1848 #
1849 # enable the FIB walk process to converge the FIB
1850 #
1851 self.vapi.ppcli("test fib-walk-process enable")
1852
1853 #
1854 # packets should still be forwarded through the remaining peer
1855 #
1856 self.pg2.add_stream(pkts)
1857 self.pg_enable_capture(self.pg_interfaces)
1858 self.pg_start()
1859
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001860 rx0 = self.pg0.get_capture(NUM_PKTS)
1861 self.assertEqual(len(pkts), len(rx0),
1862 "Expected all (%s) packets across single path. "
1863 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001864
1865 #
1866 # Add the IGP route back and we return to load-balancing
1867 #
1868 core_10_0_0_46.add_vpp_config()
1869
1870 self.pg2.add_stream(pkts)
1871 self.pg_enable_capture(self.pg_interfaces)
1872 self.pg_start()
1873
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001874 rx0 = self.pg0._get_capture(NUM_PKTS)
1875 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001876 self.assertNotEqual(0, len(rx0))
1877 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001878 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1879 "Expected all (%s) packets across both ECMP paths. "
1880 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001881
1882 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001883 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001884
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001885 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001886 2) Check EMCP forwarding to these peers
1887 3) withdraw one eBGP path - expect LB across remaining eBGP
1888 """
1889
1890 #
1891 # Lot's of VPN routes. We need more the 64 so VPP will build
1892 # the fast convergence indirection
1893 #
1894 vpn_routes = []
1895 vpn_bindings = []
1896 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001897 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001898 dst = "192.168.1.%d" % ii
1899 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001900 vpn_routes.append(VppIpRoute(
1901 self, dst, 32,
1902 [VppRoutePath(
1903 self.pg2.remote_ip4,
1904 0xffffffff,
1905 nh_table_id=1,
1906 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1907 VppRoutePath(
1908 self.pg3.remote_ip4,
1909 0xffffffff,
1910 nh_table_id=1,
1911 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1912 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001913 vpn_routes[ii].add_vpp_config()
1914
1915 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1916 ip_table_id=1))
1917 vpn_bindings[ii].add_vpp_config()
1918
1919 pkts.append(Ether(dst=self.pg0.local_mac,
1920 src=self.pg0.remote_mac) /
1921 MPLS(label=local_label, ttl=64) /
1922 IP(src=self.pg0.remote_ip4, dst=dst) /
1923 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001924 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001925
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001926 #
1927 # Send the packet stream (one pkt to each VPN route)
1928 # - expect a 50-50 split of the traffic
1929 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001930 self.pg0.add_stream(pkts)
1931 self.pg_enable_capture(self.pg_interfaces)
1932 self.pg_start()
1933
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001934 rx0 = self.pg2._get_capture(NUM_PKTS)
1935 rx1 = self.pg3._get_capture(NUM_PKTS)
1936
1937 # not testing the LB hashing algorithm so we're not concerned
1938 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001939 self.assertNotEqual(0, len(rx0))
1940 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001941 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1942 "Expected all (%s) packets across both ECMP paths. "
1943 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001944
1945 #
1946 # use a test CLI command to stop the FIB walk process, this
1947 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001948 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001949 #
1950 self.vapi.ppcli("test fib-walk-process disable")
1951
1952 #
1953 # withdraw the connected prefix on the interface.
1954 #
1955 self.pg2.unconfig_ip4()
1956
1957 #
1958 # now all packets should be forwarded through the remaining peer
1959 #
1960 self.pg0.add_stream(pkts)
1961 self.pg_enable_capture(self.pg_interfaces)
1962 self.pg_start()
1963
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001964 rx0 = self.pg3.get_capture(NUM_PKTS)
1965 self.assertEqual(len(pkts), len(rx0),
1966 "Expected all (%s) packets across single path. "
1967 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001968
1969 #
1970 # enable the FIB walk process to converge the FIB
1971 #
1972 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001973
1974 #
1975 # packets should still be forwarded through the remaining peer
1976 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001977 self.pg0.add_stream(pkts)
1978 self.pg_enable_capture(self.pg_interfaces)
1979 self.pg_start()
1980
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001981 rx0 = self.pg3.get_capture(NUM_PKTS)
1982 self.assertEqual(len(pkts), len(rx0),
1983 "Expected all (%s) packets across single path. "
1984 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001985
1986 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001987 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001988 #
1989 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001990 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001991
1992 self.pg0.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1994 self.pg_start()
1995
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001996 rx0 = self.pg2._get_capture(NUM_PKTS)
1997 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001998 self.assertNotEqual(0, len(rx0))
1999 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002000 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2001 "Expected all (%s) packets across both ECMP paths. "
2002 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002003
2004 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002005 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07002006
2007 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
2008 2) Check EMCP forwarding to these peers
2009 3) withdraw one eBGP path - expect LB across remaining eBGP
2010 """
2011
2012 #
2013 # Lot's of VPN routes. We need more the 64 so VPP will build
2014 # the fast convergence indirection
2015 #
2016 vpn_routes = []
2017 vpn_bindings = []
2018 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002019 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07002020 dst = "3000::%d" % ii
2021 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07002022 vpn_routes.append(VppIpRoute(
2023 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002024 [VppRoutePath(
2025 self.pg2.remote_ip6,
2026 0xffffffff,
2027 nh_table_id=1,
2028 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
2029 VppRoutePath(
2030 self.pg3.remote_ip6,
2031 0xffffffff,
2032 nh_table_id=1,
2033 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
2034 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002035 vpn_routes[ii].add_vpp_config()
2036
2037 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002038 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002039 vpn_bindings[ii].add_vpp_config()
2040
2041 pkts.append(Ether(dst=self.pg0.local_mac,
2042 src=self.pg0.remote_mac) /
2043 MPLS(label=local_label, ttl=64) /
2044 IPv6(src=self.pg0.remote_ip6, dst=dst) /
2045 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002046 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002047 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002048
2049 self.pg0.add_stream(pkts)
2050 self.pg_enable_capture(self.pg_interfaces)
2051 self.pg_start()
2052
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002053 rx0 = self.pg2._get_capture(NUM_PKTS)
2054 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002055 self.assertNotEqual(0, len(rx0))
2056 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002057 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2058 "Expected all (%s) packets across both ECMP paths. "
2059 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002060
2061 #
2062 # use a test CLI command to stop the FIB walk process, this
2063 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002064 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002065 #
2066 self.vapi.ppcli("test fib-walk-process disable")
2067
2068 #
2069 # withdraw the connected prefix on the interface.
2070 # and shutdown the interface so the ND cache is flushed.
2071 #
2072 self.pg2.unconfig_ip6()
2073 self.pg2.admin_down()
2074
2075 #
2076 # now all packets should be forwarded through the remaining peer
2077 #
2078 self.pg0.add_stream(pkts)
2079 self.pg_enable_capture(self.pg_interfaces)
2080 self.pg_start()
2081
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002082 rx0 = self.pg3.get_capture(NUM_PKTS)
2083 self.assertEqual(len(pkts), len(rx0),
2084 "Expected all (%s) packets across single path. "
2085 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002086
2087 #
2088 # enable the FIB walk process to converge the FIB
2089 #
2090 self.vapi.ppcli("test fib-walk-process enable")
2091 self.pg0.add_stream(pkts)
2092 self.pg_enable_capture(self.pg_interfaces)
2093 self.pg_start()
2094
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002095 rx0 = self.pg3.get_capture(NUM_PKTS)
2096 self.assertEqual(len(pkts), len(rx0),
2097 "Expected all (%s) packets across single path. "
2098 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002099
2100 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002101 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002102 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002103 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002104 self.pg2.admin_up()
2105 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002106 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002107
2108 self.pg0.add_stream(pkts)
2109 self.pg_enable_capture(self.pg_interfaces)
2110 self.pg_start()
2111
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002112 rx0 = self.pg2._get_capture(NUM_PKTS)
2113 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002114 self.assertNotEqual(0, len(rx0))
2115 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002116 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2117 "Expected all (%s) packets across both ECMP paths. "
2118 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002119
2120
Neale Rannsda78f952017-05-24 09:15:43 -07002121class TestMPLSL2(VppTestCase):
2122 """ MPLS-L2 """
2123
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002124 @classmethod
2125 def setUpClass(cls):
2126 super(TestMPLSL2, cls).setUpClass()
2127
2128 @classmethod
2129 def tearDownClass(cls):
2130 super(TestMPLSL2, cls).tearDownClass()
2131
Neale Rannsda78f952017-05-24 09:15:43 -07002132 def setUp(self):
2133 super(TestMPLSL2, self).setUp()
2134
2135 # create 2 pg interfaces
2136 self.create_pg_interfaces(range(2))
2137
Neale Ranns15002542017-09-10 04:39:11 -07002138 # create the default MPLS table
2139 self.tables = []
2140 tbl = VppMplsTable(self, 0)
2141 tbl.add_vpp_config()
2142 self.tables.append(tbl)
2143
Neale Ranns1976f362019-11-06 13:13:01 +00002144 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002145 self.pg0.admin_up()
2146 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002147 self.pg0.enable_mpls()
2148
Neale Ranns15002542017-09-10 04:39:11 -07002149 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002150 for i in self.pg_interfaces[1:]:
2151 i.admin_up()
2152
2153 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002154 for i in self.pg_interfaces[1:]:
2155 i.admin_down()
2156
2157 self.pg0.disable_mpls()
2158 self.pg0.unconfig_ip4()
2159 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002160 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002161
Neale Ranns31ed7442018-02-23 05:29:09 -08002162 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002163 capture = verify_filter(capture, sent)
2164
2165 self.assertEqual(len(capture), len(sent))
2166
2167 for i in range(len(capture)):
2168 tx = sent[i]
2169 rx = capture[i]
2170
2171 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002172 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002173
2174 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002175 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002176
2177 self.assertEqual(rx_eth.src, tx_eth.src)
2178 self.assertEqual(rx_eth.dst, tx_eth.dst)
2179
Neale Ranns1976f362019-11-06 13:13:01 +00002180 def verify_arp_req(self, rx, smac, sip, dip):
2181 ether = rx[Ether]
2182 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2183 self.assertEqual(ether.src, smac)
2184
2185 arp = rx[ARP]
2186 self.assertEqual(arp.hwtype, 1)
2187 self.assertEqual(arp.ptype, 0x800)
2188 self.assertEqual(arp.hwlen, 6)
2189 self.assertEqual(arp.plen, 4)
2190 self.assertEqual(arp.op, ARP.who_has)
2191 self.assertEqual(arp.hwsrc, smac)
2192 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2193 self.assertEqual(arp.psrc, sip)
2194 self.assertEqual(arp.pdst, dip)
2195
Neale Rannsda78f952017-05-24 09:15:43 -07002196 def test_vpws(self):
2197 """ Virtual Private Wire Service """
2198
2199 #
2200 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002201 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2202 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002203 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002204 mpls_tun_1 = VppMPLSTunnelInterface(
2205 self,
2206 [VppRoutePath(self.pg0.remote_ip4,
2207 self.pg0.sw_if_index,
2208 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2209 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002210 mpls_tun_1.add_vpp_config()
2211 mpls_tun_1.admin_up()
2212
2213 #
2214 # Create a label entry to for 55 that does L2 input to the tunnel
2215 #
2216 route_55_eos = VppMplsRoute(
2217 self, 55, 1,
2218 [VppRoutePath("0.0.0.0",
2219 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002220 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2221 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2222 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002223 route_55_eos.add_vpp_config()
2224
2225 #
2226 # Cross-connect the tunnel with one of the customers L2 interfaces
2227 #
2228 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2229 mpls_tun_1.sw_if_index,
2230 enable=1)
2231 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2232 self.pg1.sw_if_index,
2233 enable=1)
2234
2235 #
2236 # inject a packet from the core
2237 #
2238 pcore = (Ether(dst=self.pg0.local_mac,
2239 src=self.pg0.remote_mac) /
2240 MPLS(label=55, ttl=64) /
2241 Ether(dst="00:00:de:ad:ba:be",
2242 src="00:00:de:ad:be:ef") /
2243 IP(src="10.10.10.10", dst="11.11.11.11") /
2244 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002245 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002246
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002247 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002248 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2249 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002250
Neale Ranns31ed7442018-02-23 05:29:09 -08002251 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2252 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002253
2254 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002255 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002256 # there's no resolved ARP entry so the first packet we see should be
2257 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002258 #
Neale Ranns1976f362019-11-06 13:13:01 +00002259 tx1 = pcore[MPLS].payload
2260 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2261
2262 self.verify_arp_req(rx1[0],
2263 self.pg0.local_mac,
2264 self.pg0.local_ip4,
2265 self.pg0.remote_ip4)
2266
2267 #
2268 # resolve the ARP entries and send again
2269 #
2270 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002271 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002272 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002273
Neale Ranns31ed7442018-02-23 05:29:09 -08002274 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002275
2276 def test_vpls(self):
2277 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002278
2279 # we skipped this in the setup
2280 self.pg0.resolve_arp()
2281
Neale Rannsda78f952017-05-24 09:15:43 -07002282 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002283 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002284 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002285 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002286 self,
2287 [VppRoutePath(self.pg0.remote_ip4,
2288 self.pg0.sw_if_index,
2289 labels=[VppMplsLabel(42)])],
2290 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002291 mpls_tun1.add_vpp_config()
2292 mpls_tun1.admin_up()
2293
2294 mpls_tun2 = VppMPLSTunnelInterface(
2295 self,
2296 [VppRoutePath(self.pg0.remote_ip4,
2297 self.pg0.sw_if_index,
2298 labels=[VppMplsLabel(43)])],
2299 is_l2=1)
2300 mpls_tun2.add_vpp_config()
2301 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002302
2303 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002304 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2305 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002306 #
2307 route_55_eos = VppMplsRoute(
2308 self, 55, 1,
2309 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002310 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002311 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2312 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2313 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002314
2315 route_56_eos = VppMplsRoute(
2316 self, 56, 1,
2317 [VppRoutePath("0.0.0.0",
2318 mpls_tun2.sw_if_index,
2319 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2320 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2321 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2322 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2323
2324 # move me
2325 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002326 route_55_eos.add_vpp_config()
2327
Neale Ranns1dbcf302019-07-19 11:44:53 +00002328 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2329
Neale Rannsda78f952017-05-24 09:15:43 -07002330 #
2331 # add to tunnel to the customers bridge-domain
2332 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002333 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002334 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2335 self.vapi.sw_interface_set_l2_bridge(
2336 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002337 self.vapi.sw_interface_set_l2_bridge(
2338 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002339
2340 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002341 # Packet from host on the customer interface to each host
2342 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002343 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002344 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2345 src="00:00:de:ad:be:ef") /
2346 IP(src="10.10.10.10", dst="11.11.11.11") /
2347 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002348 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002349 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2350 src="00:00:de:ad:be:ef") /
2351 IP(src="10.10.10.10", dst="11.11.11.12") /
2352 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002353 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002354 p_core1 = (Ether(dst=self.pg0.local_mac,
2355 src=self.pg0.remote_mac) /
2356 MPLS(label=55, ttl=64) /
2357 Ether(src="00:00:de:ad:ba:b1",
2358 dst="00:00:de:ad:be:ef") /
2359 IP(dst="10.10.10.10", src="11.11.11.11") /
2360 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002361 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002362 p_core2 = (Ether(dst=self.pg0.local_mac,
2363 src=self.pg0.remote_mac) /
2364 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002365 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002366 Ether(src="00:00:de:ad:ba:b2",
2367 dst="00:00:de:ad:be:ef") /
2368 IP(dst="10.10.10.10", src="11.11.11.12") /
2369 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002370 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002371
2372 #
2373 # The BD is learning, so send in one of each packet to learn
2374 #
Neale Rannsda78f952017-05-24 09:15:43 -07002375
Neale Ranns1dbcf302019-07-19 11:44:53 +00002376 # 2 packets due to BD flooding
2377 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2378 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002379
Neale Ranns1dbcf302019-07-19 11:44:53 +00002380 # we've learnt this so expect it be be forwarded not flooded
2381 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2382 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2383 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002384
Neale Ranns1dbcf302019-07-19 11:44:53 +00002385 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2386 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2387 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002388
2389 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002390 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002391 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002392 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2393 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002394 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002395
Neale Ranns1dbcf302019-07-19 11:44:53 +00002396 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2397 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2398 [VppMplsLabel(43)])
2399
2400 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2401 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2402
Neale Rannsda78f952017-05-24 09:15:43 -07002403 #
2404 # remove interfaces from customers bridge-domain
2405 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002406 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002407 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2408 self.vapi.sw_interface_set_l2_bridge(
2409 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002410 self.vapi.sw_interface_set_l2_bridge(
2411 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002412
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002413
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002414if __name__ == '__main__':
2415 unittest.main(testRunner=VppTestRunner)