blob: 2b959e48fb62748d7276bed4e867c15dfa201601 [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 Ranns180279b2017-03-16 15:49:09 -04001566
1567class TestMPLSDisabled(VppTestCase):
1568 """ MPLS disabled """
1569
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001570 @classmethod
1571 def setUpClass(cls):
1572 super(TestMPLSDisabled, cls).setUpClass()
1573
1574 @classmethod
1575 def tearDownClass(cls):
1576 super(TestMPLSDisabled, cls).tearDownClass()
1577
Neale Ranns180279b2017-03-16 15:49:09 -04001578 def setUp(self):
1579 super(TestMPLSDisabled, self).setUp()
1580
1581 # create 2 pg interfaces
1582 self.create_pg_interfaces(range(2))
1583
Neale Ranns15002542017-09-10 04:39:11 -07001584 self.tbl = VppMplsTable(self, 0)
1585 self.tbl.add_vpp_config()
1586
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001587 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001588 self.pg0.admin_up()
1589 self.pg0.config_ip4()
1590 self.pg0.resolve_arp()
1591 self.pg0.enable_mpls()
1592
1593 # PG 1 is not MPLS enabled
1594 self.pg1.admin_up()
1595
1596 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001597 for i in self.pg_interfaces:
1598 i.unconfig_ip4()
1599 i.admin_down()
1600
Neale Ranns15002542017-09-10 04:39:11 -07001601 self.pg0.disable_mpls()
1602 super(TestMPLSDisabled, self).tearDown()
1603
Neale Ranns180279b2017-03-16 15:49:09 -04001604 def test_mpls_disabled(self):
1605 """ MPLS Disabled """
1606
Neale Rannsde0b3b52021-06-15 12:43:12 +00001607 self.logger.info(self.vapi.cli("show mpls interface"))
1608 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1609 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1610
Neale Ranns180279b2017-03-16 15:49:09 -04001611 tx = (Ether(src=self.pg1.remote_mac,
1612 dst=self.pg1.local_mac) /
1613 MPLS(label=32, ttl=64) /
1614 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1615 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001616 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001617
1618 #
1619 # A simple MPLS xconnect - eos label in label out
1620 #
1621 route_32_eos = VppMplsRoute(self, 32, 1,
1622 [VppRoutePath(self.pg0.remote_ip4,
1623 self.pg0.sw_if_index,
1624 labels=[33])])
1625 route_32_eos.add_vpp_config()
1626
1627 #
1628 # PG1 does not forward IP traffic
1629 #
1630 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1631
1632 #
1633 # MPLS enable PG1
1634 #
1635 self.pg1.enable_mpls()
1636
Neale Rannsde0b3b52021-06-15 12:43:12 +00001637 self.logger.info(self.vapi.cli("show mpls interface"))
1638 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1639
Neale Ranns180279b2017-03-16 15:49:09 -04001640 #
1641 # Now we get packets through
1642 #
1643 self.pg1.add_stream(tx)
1644 self.pg_enable_capture(self.pg_interfaces)
1645 self.pg_start()
1646
1647 rx = self.pg0.get_capture(1)
1648
1649 #
1650 # Disable PG1
1651 #
1652 self.pg1.disable_mpls()
1653
1654 #
1655 # PG1 does not forward IP traffic
1656 #
1657 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1658 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1659
1660
Neale Rannsf12a83f2017-04-18 09:09:40 -07001661class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001662 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001663
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001664 @classmethod
1665 def setUpClass(cls):
1666 super(TestMPLSPIC, cls).setUpClass()
1667
1668 @classmethod
1669 def tearDownClass(cls):
1670 super(TestMPLSPIC, cls).tearDownClass()
1671
Neale Rannsf12a83f2017-04-18 09:09:40 -07001672 def setUp(self):
1673 super(TestMPLSPIC, self).setUp()
1674
1675 # create 2 pg interfaces
1676 self.create_pg_interfaces(range(4))
1677
Neale Ranns15002542017-09-10 04:39:11 -07001678 mpls_tbl = VppMplsTable(self, 0)
1679 mpls_tbl.add_vpp_config()
1680 tbl4 = VppIpTable(self, 1)
1681 tbl4.add_vpp_config()
1682 tbl6 = VppIpTable(self, 1, is_ip6=1)
1683 tbl6.add_vpp_config()
1684
Neale Rannsf12a83f2017-04-18 09:09:40 -07001685 # core links
1686 self.pg0.admin_up()
1687 self.pg0.config_ip4()
1688 self.pg0.resolve_arp()
1689 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001690
Neale Rannsf12a83f2017-04-18 09:09:40 -07001691 self.pg1.admin_up()
1692 self.pg1.config_ip4()
1693 self.pg1.resolve_arp()
1694 self.pg1.enable_mpls()
1695
1696 # VRF (customer facing) link
1697 self.pg2.admin_up()
1698 self.pg2.set_table_ip4(1)
1699 self.pg2.config_ip4()
1700 self.pg2.resolve_arp()
1701 self.pg2.set_table_ip6(1)
1702 self.pg2.config_ip6()
1703 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001704
Neale Rannsf12a83f2017-04-18 09:09:40 -07001705 self.pg3.admin_up()
1706 self.pg3.set_table_ip4(1)
1707 self.pg3.config_ip4()
1708 self.pg3.resolve_arp()
1709 self.pg3.set_table_ip6(1)
1710 self.pg3.config_ip6()
1711 self.pg3.resolve_ndp()
1712
1713 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001714 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001715 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001716 for i in self.pg_interfaces:
1717 i.unconfig_ip4()
1718 i.unconfig_ip6()
1719 i.set_table_ip4(0)
1720 i.set_table_ip6(0)
1721 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001722 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001723
1724 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001725 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001726
1727 1) setup many iBGP VPN routes via a pair of iBGP peers.
1728 2) Check EMCP forwarding to these peers
1729 3) withdraw the IGP route to one of these peers.
1730 4) check forwarding continues to the remaining peer
1731 """
1732
1733 #
1734 # IGP+LDP core routes
1735 #
1736 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1737 [VppRoutePath(self.pg0.remote_ip4,
1738 self.pg0.sw_if_index,
1739 labels=[45])])
1740 core_10_0_0_45.add_vpp_config()
1741
1742 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1743 [VppRoutePath(self.pg1.remote_ip4,
1744 self.pg1.sw_if_index,
1745 labels=[46])])
1746 core_10_0_0_46.add_vpp_config()
1747
1748 #
1749 # Lot's of VPN routes. We need more the 64 so VPP will build
1750 # the fast convergence indirection
1751 #
1752 vpn_routes = []
1753 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001754 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001755 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001756 vpn_routes.append(VppIpRoute(
1757 self, dst, 32,
1758 [VppRoutePath(
1759 "10.0.0.45",
1760 0xffffffff,
1761 labels=[145],
1762 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1763 VppRoutePath(
1764 "10.0.0.46",
1765 0xffffffff,
1766 labels=[146],
1767 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1768 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001769 vpn_routes[ii].add_vpp_config()
1770
1771 pkts.append(Ether(dst=self.pg2.local_mac,
1772 src=self.pg2.remote_mac) /
1773 IP(src=self.pg2.remote_ip4, dst=dst) /
1774 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001775 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001776
1777 #
1778 # Send the packet stream (one pkt to each VPN route)
1779 # - expect a 50-50 split of the traffic
1780 #
1781 self.pg2.add_stream(pkts)
1782 self.pg_enable_capture(self.pg_interfaces)
1783 self.pg_start()
1784
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001785 rx0 = self.pg0._get_capture(NUM_PKTS)
1786 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001787
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001788 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001789 # with the split ratio, just as long as neither is 0
1790 self.assertNotEqual(0, len(rx0))
1791 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001792 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1793 "Expected all (%s) packets across both ECMP paths. "
1794 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001795
1796 #
1797 # use a test CLI command to stop the FIB walk process, this
1798 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001799 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001800 #
1801 self.vapi.ppcli("test fib-walk-process disable")
1802
1803 #
1804 # Withdraw one of the IGP routes
1805 #
1806 core_10_0_0_46.remove_vpp_config()
1807
1808 #
1809 # now all packets should be forwarded through the remaining peer
1810 #
1811 self.vapi.ppcli("clear trace")
1812 self.pg2.add_stream(pkts)
1813 self.pg_enable_capture(self.pg_interfaces)
1814 self.pg_start()
1815
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001816 rx0 = self.pg0.get_capture(NUM_PKTS)
1817 self.assertEqual(len(pkts), len(rx0),
1818 "Expected all (%s) packets across single path. "
1819 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001820
1821 #
1822 # enable the FIB walk process to converge the FIB
1823 #
1824 self.vapi.ppcli("test fib-walk-process enable")
1825
1826 #
1827 # packets should still be forwarded through the remaining peer
1828 #
1829 self.pg2.add_stream(pkts)
1830 self.pg_enable_capture(self.pg_interfaces)
1831 self.pg_start()
1832
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001833 rx0 = self.pg0.get_capture(NUM_PKTS)
1834 self.assertEqual(len(pkts), len(rx0),
1835 "Expected all (%s) packets across single path. "
1836 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001837
1838 #
1839 # Add the IGP route back and we return to load-balancing
1840 #
1841 core_10_0_0_46.add_vpp_config()
1842
1843 self.pg2.add_stream(pkts)
1844 self.pg_enable_capture(self.pg_interfaces)
1845 self.pg_start()
1846
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001847 rx0 = self.pg0._get_capture(NUM_PKTS)
1848 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001849 self.assertNotEqual(0, len(rx0))
1850 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001851 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1852 "Expected all (%s) packets across both ECMP paths. "
1853 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001854
1855 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001856 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001857
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001858 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001859 2) Check EMCP forwarding to these peers
1860 3) withdraw one eBGP path - expect LB across remaining eBGP
1861 """
1862
1863 #
1864 # Lot's of VPN routes. We need more the 64 so VPP will build
1865 # the fast convergence indirection
1866 #
1867 vpn_routes = []
1868 vpn_bindings = []
1869 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001870 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001871 dst = "192.168.1.%d" % ii
1872 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001873 vpn_routes.append(VppIpRoute(
1874 self, dst, 32,
1875 [VppRoutePath(
1876 self.pg2.remote_ip4,
1877 0xffffffff,
1878 nh_table_id=1,
1879 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1880 VppRoutePath(
1881 self.pg3.remote_ip4,
1882 0xffffffff,
1883 nh_table_id=1,
1884 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1885 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001886 vpn_routes[ii].add_vpp_config()
1887
1888 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1889 ip_table_id=1))
1890 vpn_bindings[ii].add_vpp_config()
1891
1892 pkts.append(Ether(dst=self.pg0.local_mac,
1893 src=self.pg0.remote_mac) /
1894 MPLS(label=local_label, ttl=64) /
1895 IP(src=self.pg0.remote_ip4, dst=dst) /
1896 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001897 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001898
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001899 #
1900 # Send the packet stream (one pkt to each VPN route)
1901 # - expect a 50-50 split of the traffic
1902 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001903 self.pg0.add_stream(pkts)
1904 self.pg_enable_capture(self.pg_interfaces)
1905 self.pg_start()
1906
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001907 rx0 = self.pg2._get_capture(NUM_PKTS)
1908 rx1 = self.pg3._get_capture(NUM_PKTS)
1909
1910 # not testing the LB hashing algorithm so we're not concerned
1911 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001912 self.assertNotEqual(0, len(rx0))
1913 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001914 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1915 "Expected all (%s) packets across both ECMP paths. "
1916 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001917
1918 #
1919 # use a test CLI command to stop the FIB walk process, this
1920 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001921 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001922 #
1923 self.vapi.ppcli("test fib-walk-process disable")
1924
1925 #
1926 # withdraw the connected prefix on the interface.
1927 #
1928 self.pg2.unconfig_ip4()
1929
1930 #
1931 # now all packets should be forwarded through the remaining peer
1932 #
1933 self.pg0.add_stream(pkts)
1934 self.pg_enable_capture(self.pg_interfaces)
1935 self.pg_start()
1936
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001937 rx0 = self.pg3.get_capture(NUM_PKTS)
1938 self.assertEqual(len(pkts), len(rx0),
1939 "Expected all (%s) packets across single path. "
1940 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001941
1942 #
1943 # enable the FIB walk process to converge the FIB
1944 #
1945 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001946
1947 #
1948 # packets should still be forwarded through the remaining peer
1949 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001950 self.pg0.add_stream(pkts)
1951 self.pg_enable_capture(self.pg_interfaces)
1952 self.pg_start()
1953
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001954 rx0 = self.pg3.get_capture(NUM_PKTS)
1955 self.assertEqual(len(pkts), len(rx0),
1956 "Expected all (%s) packets across single path. "
1957 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001958
1959 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001960 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001961 #
1962 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001963 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001964
1965 self.pg0.add_stream(pkts)
1966 self.pg_enable_capture(self.pg_interfaces)
1967 self.pg_start()
1968
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001969 rx0 = self.pg2._get_capture(NUM_PKTS)
1970 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001971 self.assertNotEqual(0, len(rx0))
1972 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001973 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1974 "Expected all (%s) packets across both ECMP paths. "
1975 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001976
1977 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001978 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001979
1980 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1981 2) Check EMCP forwarding to these peers
1982 3) withdraw one eBGP path - expect LB across remaining eBGP
1983 """
1984
1985 #
1986 # Lot's of VPN routes. We need more the 64 so VPP will build
1987 # the fast convergence indirection
1988 #
1989 vpn_routes = []
1990 vpn_bindings = []
1991 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001992 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001993 dst = "3000::%d" % ii
1994 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001995 vpn_routes.append(VppIpRoute(
1996 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001997 [VppRoutePath(
1998 self.pg2.remote_ip6,
1999 0xffffffff,
2000 nh_table_id=1,
2001 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
2002 VppRoutePath(
2003 self.pg3.remote_ip6,
2004 0xffffffff,
2005 nh_table_id=1,
2006 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
2007 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002008 vpn_routes[ii].add_vpp_config()
2009
2010 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002011 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002012 vpn_bindings[ii].add_vpp_config()
2013
2014 pkts.append(Ether(dst=self.pg0.local_mac,
2015 src=self.pg0.remote_mac) /
2016 MPLS(label=local_label, ttl=64) /
2017 IPv6(src=self.pg0.remote_ip6, dst=dst) /
2018 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002019 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002020 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002021
2022 self.pg0.add_stream(pkts)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
2025
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002026 rx0 = self.pg2._get_capture(NUM_PKTS)
2027 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002028 self.assertNotEqual(0, len(rx0))
2029 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002030 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2031 "Expected all (%s) packets across both ECMP paths. "
2032 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002033
2034 #
2035 # use a test CLI command to stop the FIB walk process, this
2036 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002037 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002038 #
2039 self.vapi.ppcli("test fib-walk-process disable")
2040
2041 #
2042 # withdraw the connected prefix on the interface.
2043 # and shutdown the interface so the ND cache is flushed.
2044 #
2045 self.pg2.unconfig_ip6()
2046 self.pg2.admin_down()
2047
2048 #
2049 # now all packets should be forwarded through the remaining peer
2050 #
2051 self.pg0.add_stream(pkts)
2052 self.pg_enable_capture(self.pg_interfaces)
2053 self.pg_start()
2054
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002055 rx0 = self.pg3.get_capture(NUM_PKTS)
2056 self.assertEqual(len(pkts), len(rx0),
2057 "Expected all (%s) packets across single path. "
2058 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002059
2060 #
2061 # enable the FIB walk process to converge the FIB
2062 #
2063 self.vapi.ppcli("test fib-walk-process enable")
2064 self.pg0.add_stream(pkts)
2065 self.pg_enable_capture(self.pg_interfaces)
2066 self.pg_start()
2067
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002068 rx0 = self.pg3.get_capture(NUM_PKTS)
2069 self.assertEqual(len(pkts), len(rx0),
2070 "Expected all (%s) packets across single path. "
2071 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002072
2073 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002074 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002075 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002076 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002077 self.pg2.admin_up()
2078 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002079 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002080
2081 self.pg0.add_stream(pkts)
2082 self.pg_enable_capture(self.pg_interfaces)
2083 self.pg_start()
2084
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002085 rx0 = self.pg2._get_capture(NUM_PKTS)
2086 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002087 self.assertNotEqual(0, len(rx0))
2088 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002089 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2090 "Expected all (%s) packets across both ECMP paths. "
2091 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002092
2093
Neale Rannsda78f952017-05-24 09:15:43 -07002094class TestMPLSL2(VppTestCase):
2095 """ MPLS-L2 """
2096
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002097 @classmethod
2098 def setUpClass(cls):
2099 super(TestMPLSL2, cls).setUpClass()
2100
2101 @classmethod
2102 def tearDownClass(cls):
2103 super(TestMPLSL2, cls).tearDownClass()
2104
Neale Rannsda78f952017-05-24 09:15:43 -07002105 def setUp(self):
2106 super(TestMPLSL2, self).setUp()
2107
2108 # create 2 pg interfaces
2109 self.create_pg_interfaces(range(2))
2110
Neale Ranns15002542017-09-10 04:39:11 -07002111 # create the default MPLS table
2112 self.tables = []
2113 tbl = VppMplsTable(self, 0)
2114 tbl.add_vpp_config()
2115 self.tables.append(tbl)
2116
Neale Ranns1976f362019-11-06 13:13:01 +00002117 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002118 self.pg0.admin_up()
2119 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002120 self.pg0.enable_mpls()
2121
Neale Ranns15002542017-09-10 04:39:11 -07002122 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002123 for i in self.pg_interfaces[1:]:
2124 i.admin_up()
2125
2126 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002127 for i in self.pg_interfaces[1:]:
2128 i.admin_down()
2129
2130 self.pg0.disable_mpls()
2131 self.pg0.unconfig_ip4()
2132 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002133 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002134
Neale Ranns31ed7442018-02-23 05:29:09 -08002135 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002136 capture = verify_filter(capture, sent)
2137
2138 self.assertEqual(len(capture), len(sent))
2139
2140 for i in range(len(capture)):
2141 tx = sent[i]
2142 rx = capture[i]
2143
2144 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002145 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002146
2147 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002148 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002149
2150 self.assertEqual(rx_eth.src, tx_eth.src)
2151 self.assertEqual(rx_eth.dst, tx_eth.dst)
2152
Neale Ranns1976f362019-11-06 13:13:01 +00002153 def verify_arp_req(self, rx, smac, sip, dip):
2154 ether = rx[Ether]
2155 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2156 self.assertEqual(ether.src, smac)
2157
2158 arp = rx[ARP]
2159 self.assertEqual(arp.hwtype, 1)
2160 self.assertEqual(arp.ptype, 0x800)
2161 self.assertEqual(arp.hwlen, 6)
2162 self.assertEqual(arp.plen, 4)
2163 self.assertEqual(arp.op, ARP.who_has)
2164 self.assertEqual(arp.hwsrc, smac)
2165 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2166 self.assertEqual(arp.psrc, sip)
2167 self.assertEqual(arp.pdst, dip)
2168
Neale Rannsda78f952017-05-24 09:15:43 -07002169 def test_vpws(self):
2170 """ Virtual Private Wire Service """
2171
2172 #
2173 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002174 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2175 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002176 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002177 mpls_tun_1 = VppMPLSTunnelInterface(
2178 self,
2179 [VppRoutePath(self.pg0.remote_ip4,
2180 self.pg0.sw_if_index,
2181 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2182 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002183 mpls_tun_1.add_vpp_config()
2184 mpls_tun_1.admin_up()
2185
2186 #
2187 # Create a label entry to for 55 that does L2 input to the tunnel
2188 #
2189 route_55_eos = VppMplsRoute(
2190 self, 55, 1,
2191 [VppRoutePath("0.0.0.0",
2192 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002193 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2194 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2195 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002196 route_55_eos.add_vpp_config()
2197
2198 #
2199 # Cross-connect the tunnel with one of the customers L2 interfaces
2200 #
2201 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2202 mpls_tun_1.sw_if_index,
2203 enable=1)
2204 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2205 self.pg1.sw_if_index,
2206 enable=1)
2207
2208 #
2209 # inject a packet from the core
2210 #
2211 pcore = (Ether(dst=self.pg0.local_mac,
2212 src=self.pg0.remote_mac) /
2213 MPLS(label=55, ttl=64) /
2214 Ether(dst="00:00:de:ad:ba:be",
2215 src="00:00:de:ad:be:ef") /
2216 IP(src="10.10.10.10", dst="11.11.11.11") /
2217 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002218 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002219
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002220 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002221 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2222 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002223
Neale Ranns31ed7442018-02-23 05:29:09 -08002224 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2225 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002226
2227 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002228 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002229 # there's no resolved ARP entry so the first packet we see should be
2230 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002231 #
Neale Ranns1976f362019-11-06 13:13:01 +00002232 tx1 = pcore[MPLS].payload
2233 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2234
2235 self.verify_arp_req(rx1[0],
2236 self.pg0.local_mac,
2237 self.pg0.local_ip4,
2238 self.pg0.remote_ip4)
2239
2240 #
2241 # resolve the ARP entries and send again
2242 #
2243 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002244 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002245 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002246
Neale Ranns31ed7442018-02-23 05:29:09 -08002247 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002248
2249 def test_vpls(self):
2250 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002251
2252 # we skipped this in the setup
2253 self.pg0.resolve_arp()
2254
Neale Rannsda78f952017-05-24 09:15:43 -07002255 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002256 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002257 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002258 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002259 self,
2260 [VppRoutePath(self.pg0.remote_ip4,
2261 self.pg0.sw_if_index,
2262 labels=[VppMplsLabel(42)])],
2263 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002264 mpls_tun1.add_vpp_config()
2265 mpls_tun1.admin_up()
2266
2267 mpls_tun2 = VppMPLSTunnelInterface(
2268 self,
2269 [VppRoutePath(self.pg0.remote_ip4,
2270 self.pg0.sw_if_index,
2271 labels=[VppMplsLabel(43)])],
2272 is_l2=1)
2273 mpls_tun2.add_vpp_config()
2274 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002275
2276 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002277 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2278 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002279 #
2280 route_55_eos = VppMplsRoute(
2281 self, 55, 1,
2282 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002283 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002284 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2285 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2286 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002287
2288 route_56_eos = VppMplsRoute(
2289 self, 56, 1,
2290 [VppRoutePath("0.0.0.0",
2291 mpls_tun2.sw_if_index,
2292 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2293 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2294 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2295 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2296
2297 # move me
2298 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002299 route_55_eos.add_vpp_config()
2300
Neale Ranns1dbcf302019-07-19 11:44:53 +00002301 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2302
Neale Rannsda78f952017-05-24 09:15:43 -07002303 #
2304 # add to tunnel to the customers bridge-domain
2305 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002306 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002307 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2308 self.vapi.sw_interface_set_l2_bridge(
2309 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002310 self.vapi.sw_interface_set_l2_bridge(
2311 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002312
2313 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002314 # Packet from host on the customer interface to each host
2315 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002316 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002317 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2318 src="00:00:de:ad:be:ef") /
2319 IP(src="10.10.10.10", dst="11.11.11.11") /
2320 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002321 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002322 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2323 src="00:00:de:ad:be:ef") /
2324 IP(src="10.10.10.10", dst="11.11.11.12") /
2325 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002326 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002327 p_core1 = (Ether(dst=self.pg0.local_mac,
2328 src=self.pg0.remote_mac) /
2329 MPLS(label=55, ttl=64) /
2330 Ether(src="00:00:de:ad:ba:b1",
2331 dst="00:00:de:ad:be:ef") /
2332 IP(dst="10.10.10.10", src="11.11.11.11") /
2333 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002334 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002335 p_core2 = (Ether(dst=self.pg0.local_mac,
2336 src=self.pg0.remote_mac) /
2337 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002338 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002339 Ether(src="00:00:de:ad:ba:b2",
2340 dst="00:00:de:ad:be:ef") /
2341 IP(dst="10.10.10.10", src="11.11.11.12") /
2342 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002343 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002344
2345 #
2346 # The BD is learning, so send in one of each packet to learn
2347 #
Neale Rannsda78f952017-05-24 09:15:43 -07002348
Neale Ranns1dbcf302019-07-19 11:44:53 +00002349 # 2 packets due to BD flooding
2350 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2351 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002352
Neale Ranns1dbcf302019-07-19 11:44:53 +00002353 # we've learnt this so expect it be be forwarded not flooded
2354 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2355 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2356 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002357
Neale Ranns1dbcf302019-07-19 11:44:53 +00002358 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2359 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2360 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002361
2362 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002363 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002364 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002365 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2366 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002367 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002368
Neale Ranns1dbcf302019-07-19 11:44:53 +00002369 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2370 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2371 [VppMplsLabel(43)])
2372
2373 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2374 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2375
Neale Rannsda78f952017-05-24 09:15:43 -07002376 #
2377 # remove interfaces from customers bridge-domain
2378 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002379 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002380 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2381 self.vapi.sw_interface_set_l2_bridge(
2382 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002383 self.vapi.sw_interface_set_l2_bridge(
2384 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002385
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002386
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002387if __name__ == '__main__':
2388 unittest.main(testRunner=VppTestRunner)