blob: 2c40e8d198e9cb3e15c190f93704213cc7b45e03 [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
1072 for ii in range(10):
1073 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()
1081
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001082 def test_v4_exp_null(self):
1083 """ MPLS V4 Explicit NULL test """
1084
1085 #
1086 # The first test case has an MPLS TTL of 0
1087 # all packet should be dropped
1088 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001089 tx = self.create_stream_labelled_ip4(self.pg0,
1090 [VppMplsLabel(0, ttl=0)])
1091 self.send_and_assert_no_replies(self.pg0, tx,
1092 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001093
1094 #
1095 # a stream with a non-zero MPLS TTL
1096 # PG0 is in the default table
1097 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001098 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1099 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001100 self.verify_capture_ip4(self.pg0, rx, tx)
1101
1102 #
1103 # a stream with a non-zero MPLS TTL
1104 # PG1 is in table 1
1105 # we are ensuring the post-pop lookup occurs in the VRF table
1106 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001107 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1108 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1109 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001110
1111 def test_v6_exp_null(self):
1112 """ MPLS V6 Explicit NULL test """
1113
1114 #
1115 # a stream with a non-zero MPLS TTL
1116 # PG0 is in the default table
1117 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001118 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1119 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001120 self.verify_capture_ip6(self.pg0, rx, tx)
1121
1122 #
1123 # a stream with a non-zero MPLS TTL
1124 # PG1 is in table 1
1125 # we are ensuring the post-pop lookup occurs in the VRF table
1126 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001127 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1128 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001129 self.verify_capture_ip6(self.pg0, rx, tx)
1130
Neale Rannscb630ff2016-12-14 13:31:29 +01001131 def test_deag(self):
1132 """ MPLS Deagg """
1133
1134 #
1135 # A de-agg route - next-hop lookup in default table
1136 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001137 route_34_eos = VppMplsRoute(self, 34, 1,
1138 [VppRoutePath("0.0.0.0",
1139 0xffffffff,
1140 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001141 route_34_eos.add_vpp_config()
1142
1143 #
1144 # ping an interface in the default table
1145 # PG0 is in the default table
1146 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001147 tx = self.create_stream_labelled_ip4(self.pg0,
1148 [VppMplsLabel(34)],
1149 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001150 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001151 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001152 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1153
1154 #
1155 # A de-agg route - next-hop lookup in non-default table
1156 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001157 route_35_eos = VppMplsRoute(self, 35, 1,
1158 [VppRoutePath("0.0.0.0",
1159 0xffffffff,
1160 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001161 route_35_eos.add_vpp_config()
1162
1163 #
1164 # ping an interface in the non-default table
1165 # PG0 is in the default table. packet arrive labelled in the
1166 # default table and egress unlabelled in the non-default
1167 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001168 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001169 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1170 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001171 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1172
Neale Ranns6af1c042017-05-26 03:48:53 -07001173 #
1174 # Double pop
1175 #
1176 route_36_neos = VppMplsRoute(self, 36, 0,
1177 [VppRoutePath("0.0.0.0",
1178 0xffffffff)])
1179 route_36_neos.add_vpp_config()
1180
Neale Ranns31ed7442018-02-23 05:29:09 -08001181 tx = self.create_stream_labelled_ip4(self.pg0,
1182 [VppMplsLabel(36),
1183 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001184 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001185 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001186 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1187
1188 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001189 route_35_eos.remove_vpp_config()
1190 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001191
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001192 def test_interface_rx(self):
1193 """ MPLS Interface Receive """
1194
1195 #
1196 # Add a non-recursive route that will forward the traffic
1197 # post-interface-rx
1198 #
1199 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1200 table_id=1,
1201 paths=[VppRoutePath(self.pg1.remote_ip4,
1202 self.pg1.sw_if_index)])
1203 route_10_0_0_1.add_vpp_config()
1204
1205 #
1206 # An interface receive label that maps traffic to RX on interface
1207 # pg1
1208 # by injecting the packet in on pg0, which is in table 0
1209 # doing an interface-rx on pg1 and matching a route in table 1
1210 # if the packet egresses, then we must have swapped to pg1
1211 # so as to have matched the route in table 1
1212 #
Neale Ranns097fa662018-05-01 05:17:55 -07001213 route_34_eos = VppMplsRoute(
1214 self, 34, 1,
1215 [VppRoutePath("0.0.0.0",
1216 self.pg1.sw_if_index,
1217 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001218 route_34_eos.add_vpp_config()
1219
1220 #
1221 # ping an interface in the default table
1222 # PG0 is in the default table
1223 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001224 tx = self.create_stream_labelled_ip4(self.pg0,
1225 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001226 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001227 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001228 self.verify_capture_ip4(self.pg1, rx, tx)
1229
1230 def test_mcast_mid_point(self):
1231 """ MPLS Multicast Mid Point """
1232
1233 #
1234 # Add a non-recursive route that will forward the traffic
1235 # post-interface-rx
1236 #
1237 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1238 table_id=1,
1239 paths=[VppRoutePath(self.pg1.remote_ip4,
1240 self.pg1.sw_if_index)])
1241 route_10_0_0_1.add_vpp_config()
1242
1243 #
1244 # Add a mcast entry that replicate to pg2 and pg3
1245 # and replicate to a interface-rx (like a bud node would)
1246 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001247 route_3400_eos = VppMplsRoute(
1248 self, 3400, 1,
1249 [VppRoutePath(self.pg2.remote_ip4,
1250 self.pg2.sw_if_index,
1251 labels=[VppMplsLabel(3401)]),
1252 VppRoutePath(self.pg3.remote_ip4,
1253 self.pg3.sw_if_index,
1254 labels=[VppMplsLabel(3402)]),
1255 VppRoutePath("0.0.0.0",
1256 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001257 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001258 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001259 route_3400_eos.add_vpp_config()
1260
1261 #
1262 # ping an interface in the default table
1263 # PG0 is in the default table
1264 #
1265 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001266 tx = self.create_stream_labelled_ip4(self.pg0,
1267 [VppMplsLabel(3400, ttl=64)],
1268 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001269 dst_ip="10.0.0.1")
1270 self.pg0.add_stream(tx)
1271
1272 self.pg_enable_capture(self.pg_interfaces)
1273 self.pg_start()
1274
1275 rx = self.pg1.get_capture(257)
1276 self.verify_capture_ip4(self.pg1, rx, tx)
1277
1278 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001279 self.verify_capture_labelled(self.pg2, rx, tx,
1280 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001281 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001282 self.verify_capture_labelled(self.pg3, rx, tx,
1283 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001284
1285 def test_mcast_head(self):
1286 """ MPLS Multicast Head-end """
1287
Neale Ranns990f6942020-10-20 07:20:17 +00001288 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1289 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1290
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001291 #
1292 # Create a multicast tunnel with two replications
1293 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001294 mpls_tun = VppMPLSTunnelInterface(
1295 self,
1296 [VppRoutePath(self.pg2.remote_ip4,
1297 self.pg2.sw_if_index,
1298 labels=[VppMplsLabel(42)]),
1299 VppRoutePath(self.pg3.remote_ip4,
1300 self.pg3.sw_if_index,
1301 labels=[VppMplsLabel(43)])],
1302 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001303 mpls_tun.add_vpp_config()
1304 mpls_tun.admin_up()
1305
1306 #
1307 # add an unlabelled route through the new tunnel
1308 #
1309 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1310 [VppRoutePath("0.0.0.0",
1311 mpls_tun._sw_if_index)])
1312 route_10_0_0_3.add_vpp_config()
1313
1314 self.vapi.cli("clear trace")
1315 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1316 self.pg0.add_stream(tx)
1317
1318 self.pg_enable_capture(self.pg_interfaces)
1319 self.pg_start()
1320
1321 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001322 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001323 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001324 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001325
1326 #
1327 # An an IP multicast route via the tunnel
1328 # A (*,G).
1329 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1330 #
1331 route_232_1_1_1 = VppIpMRoute(
1332 self,
1333 "0.0.0.0",
1334 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001335 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001336 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001337 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001338 VppMRoutePath(mpls_tun._sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001339 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001340 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001341 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001342
1343 self.vapi.cli("clear trace")
1344 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1345 self.pg0.add_stream(tx)
1346
1347 self.pg_enable_capture(self.pg_interfaces)
1348 self.pg_start()
1349
1350 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001351 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001352 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001353 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001354
Neale Ranns31426c62017-05-24 10:32:58 -07001355 def test_mcast_ip4_tail(self):
1356 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001357
Neale Ranns990f6942020-10-20 07:20:17 +00001358 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1359 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1360
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001361 #
1362 # Add a multicast route that will forward the traffic
1363 # post-disposition
1364 #
1365 route_232_1_1_1 = VppIpMRoute(
1366 self,
1367 "0.0.0.0",
1368 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001369 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001370 table_id=1,
1371 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001372 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001373 route_232_1_1_1.add_vpp_config()
1374
1375 #
1376 # An interface receive label that maps traffic to RX on interface
1377 # pg1
1378 # by injecting the packet in on pg0, which is in table 0
1379 # doing an rpf-id and matching a route in table 1
1380 # if the packet egresses, then we must have matched the route in
1381 # table 1
1382 #
Neale Ranns097fa662018-05-01 05:17:55 -07001383 route_34_eos = VppMplsRoute(
1384 self, 34, 1,
1385 [VppRoutePath("0.0.0.0",
1386 0xffffffff,
1387 nh_table_id=1,
1388 rpf_id=55)],
1389 is_multicast=1,
1390 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001391
1392 route_34_eos.add_vpp_config()
1393
1394 #
1395 # Drop due to interface lookup miss
1396 #
1397 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001398 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001399 dst_ip="232.1.1.1", n=1)
1400 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1401
1402 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001403 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001404 #
1405 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001406 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001407
Neale Ranns31ed7442018-02-23 05:29:09 -08001408 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1409 dst_ip="232.1.1.1")
1410 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001411 self.verify_capture_ip4(self.pg1, rx, tx)
1412
1413 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001414 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001415 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001416 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001417 dst_ip="232.1.1.1", n=65,
1418 chksum=1)
1419 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1420
1421 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001422 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001423 #
1424 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001425 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001426 dst_ip="232.1.1.1")
1427 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1428
Neale Ranns31426c62017-05-24 10:32:58 -07001429 def test_mcast_ip6_tail(self):
1430 """ MPLS IPv6 Multicast Tail """
1431
Neale Ranns990f6942020-10-20 07:20:17 +00001432 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1433 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1434
Neale Ranns31426c62017-05-24 10:32:58 -07001435 #
1436 # Add a multicast route that will forward the traffic
1437 # post-disposition
1438 #
1439 route_ff = VppIpMRoute(
1440 self,
1441 "::",
1442 "ff01::1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001443 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001444 table_id=1,
1445 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001446 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001447 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001448 route_ff.add_vpp_config()
1449
1450 #
1451 # An interface receive label that maps traffic to RX on interface
1452 # pg1
1453 # by injecting the packet in on pg0, which is in table 0
1454 # doing an rpf-id and matching a route in table 1
1455 # if the packet egresses, then we must have matched the route in
1456 # table 1
1457 #
1458 route_34_eos = VppMplsRoute(
1459 self, 34, 1,
1460 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001461 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001462 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001463 rpf_id=55)],
1464 is_multicast=1,
1465 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001466
1467 route_34_eos.add_vpp_config()
1468
1469 #
1470 # Drop due to interface lookup miss
1471 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001472 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001473 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001474 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001475
1476 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001477 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001478 #
1479 route_ff.update_rpf_id(55)
1480
Neale Ranns31ed7442018-02-23 05:29:09 -08001481 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001482 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001483 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001484 self.verify_capture_ip6(self.pg1, rx, tx)
1485
1486 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001487 # disposed packets have hop-limit = 1
1488 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001489 tx = self.create_stream_labelled_ip6(self.pg0,
1490 [VppMplsLabel(34)],
1491 dst_ip="ff01::1",
1492 hlim=1)
1493 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001494 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001495
1496 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001497 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001498 #
1499 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001500 tx = self.create_stream_labelled_ip6(self.pg0,
1501 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001502 dst_ip="ff01::1")
1503 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1504
Neale Rannsd5d7b962019-08-04 03:30:56 -07001505 def test_6pe(self):
1506 """ MPLS 6PE """
1507
1508 #
1509 # Add a non-recursive route with a single out label
1510 #
1511 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1512 [VppRoutePath(self.pg0.remote_ip4,
1513 self.pg0.sw_if_index,
1514 labels=[VppMplsLabel(45)])])
1515 route_10_0_0_1.add_vpp_config()
1516
1517 # bind a local label to the route
1518 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1519 binding.add_vpp_config()
1520
1521 #
1522 # a labelled v6 route that resolves through the v4
1523 #
1524 route_2001_3 = VppIpRoute(
1525 self, "2001::3", 128,
1526 [VppRoutePath("10.0.0.1",
1527 INVALID_INDEX,
1528 labels=[VppMplsLabel(32)])])
1529 route_2001_3.add_vpp_config()
1530
1531 tx = self.create_stream_ip6(self.pg0, "2001::3")
1532 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1533
1534 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1535 [VppMplsLabel(45),
1536 VppMplsLabel(32)])
1537
1538 #
1539 # and a v4 recursive via the v6
1540 #
1541 route_20_3 = VppIpRoute(
1542 self, "20.0.0.3", 32,
1543 [VppRoutePath("2001::3",
1544 INVALID_INDEX,
1545 labels=[VppMplsLabel(99)])])
1546 route_20_3.add_vpp_config()
1547
1548 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1549 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1550
1551 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1552 [VppMplsLabel(45),
1553 VppMplsLabel(32),
1554 VppMplsLabel(99)])
1555
Neale Ranns180279b2017-03-16 15:49:09 -04001556
1557class TestMPLSDisabled(VppTestCase):
1558 """ MPLS disabled """
1559
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001560 @classmethod
1561 def setUpClass(cls):
1562 super(TestMPLSDisabled, cls).setUpClass()
1563
1564 @classmethod
1565 def tearDownClass(cls):
1566 super(TestMPLSDisabled, cls).tearDownClass()
1567
Neale Ranns180279b2017-03-16 15:49:09 -04001568 def setUp(self):
1569 super(TestMPLSDisabled, self).setUp()
1570
1571 # create 2 pg interfaces
1572 self.create_pg_interfaces(range(2))
1573
Neale Ranns15002542017-09-10 04:39:11 -07001574 self.tbl = VppMplsTable(self, 0)
1575 self.tbl.add_vpp_config()
1576
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001577 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001578 self.pg0.admin_up()
1579 self.pg0.config_ip4()
1580 self.pg0.resolve_arp()
1581 self.pg0.enable_mpls()
1582
1583 # PG 1 is not MPLS enabled
1584 self.pg1.admin_up()
1585
1586 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001587 for i in self.pg_interfaces:
1588 i.unconfig_ip4()
1589 i.admin_down()
1590
Neale Ranns15002542017-09-10 04:39:11 -07001591 self.pg0.disable_mpls()
1592 super(TestMPLSDisabled, self).tearDown()
1593
Neale Ranns180279b2017-03-16 15:49:09 -04001594 def test_mpls_disabled(self):
1595 """ MPLS Disabled """
1596
Neale Rannsde0b3b52021-06-15 12:43:12 +00001597 self.logger.info(self.vapi.cli("show mpls interface"))
1598 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1599 self.logger.info(self.vapi.cli("show mpls interface pg0"))
1600
Neale Ranns180279b2017-03-16 15:49:09 -04001601 tx = (Ether(src=self.pg1.remote_mac,
1602 dst=self.pg1.local_mac) /
1603 MPLS(label=32, ttl=64) /
1604 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1605 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001606 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001607
1608 #
1609 # A simple MPLS xconnect - eos label in label out
1610 #
1611 route_32_eos = VppMplsRoute(self, 32, 1,
1612 [VppRoutePath(self.pg0.remote_ip4,
1613 self.pg0.sw_if_index,
1614 labels=[33])])
1615 route_32_eos.add_vpp_config()
1616
1617 #
1618 # PG1 does not forward IP traffic
1619 #
1620 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1621
1622 #
1623 # MPLS enable PG1
1624 #
1625 self.pg1.enable_mpls()
1626
Neale Rannsde0b3b52021-06-15 12:43:12 +00001627 self.logger.info(self.vapi.cli("show mpls interface"))
1628 self.logger.info(self.vapi.cli("show mpls interface pg1"))
1629
Neale Ranns180279b2017-03-16 15:49:09 -04001630 #
1631 # Now we get packets through
1632 #
1633 self.pg1.add_stream(tx)
1634 self.pg_enable_capture(self.pg_interfaces)
1635 self.pg_start()
1636
1637 rx = self.pg0.get_capture(1)
1638
1639 #
1640 # Disable PG1
1641 #
1642 self.pg1.disable_mpls()
1643
1644 #
1645 # PG1 does not forward IP traffic
1646 #
1647 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1648 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1649
1650
Neale Rannsf12a83f2017-04-18 09:09:40 -07001651class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001652 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001653
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001654 @classmethod
1655 def setUpClass(cls):
1656 super(TestMPLSPIC, cls).setUpClass()
1657
1658 @classmethod
1659 def tearDownClass(cls):
1660 super(TestMPLSPIC, cls).tearDownClass()
1661
Neale Rannsf12a83f2017-04-18 09:09:40 -07001662 def setUp(self):
1663 super(TestMPLSPIC, self).setUp()
1664
1665 # create 2 pg interfaces
1666 self.create_pg_interfaces(range(4))
1667
Neale Ranns15002542017-09-10 04:39:11 -07001668 mpls_tbl = VppMplsTable(self, 0)
1669 mpls_tbl.add_vpp_config()
1670 tbl4 = VppIpTable(self, 1)
1671 tbl4.add_vpp_config()
1672 tbl6 = VppIpTable(self, 1, is_ip6=1)
1673 tbl6.add_vpp_config()
1674
Neale Rannsf12a83f2017-04-18 09:09:40 -07001675 # core links
1676 self.pg0.admin_up()
1677 self.pg0.config_ip4()
1678 self.pg0.resolve_arp()
1679 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001680
Neale Rannsf12a83f2017-04-18 09:09:40 -07001681 self.pg1.admin_up()
1682 self.pg1.config_ip4()
1683 self.pg1.resolve_arp()
1684 self.pg1.enable_mpls()
1685
1686 # VRF (customer facing) link
1687 self.pg2.admin_up()
1688 self.pg2.set_table_ip4(1)
1689 self.pg2.config_ip4()
1690 self.pg2.resolve_arp()
1691 self.pg2.set_table_ip6(1)
1692 self.pg2.config_ip6()
1693 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001694
Neale Rannsf12a83f2017-04-18 09:09:40 -07001695 self.pg3.admin_up()
1696 self.pg3.set_table_ip4(1)
1697 self.pg3.config_ip4()
1698 self.pg3.resolve_arp()
1699 self.pg3.set_table_ip6(1)
1700 self.pg3.config_ip6()
1701 self.pg3.resolve_ndp()
1702
1703 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001704 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001705 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001706 for i in self.pg_interfaces:
1707 i.unconfig_ip4()
1708 i.unconfig_ip6()
1709 i.set_table_ip4(0)
1710 i.set_table_ip6(0)
1711 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001712 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001713
1714 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001715 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001716
1717 1) setup many iBGP VPN routes via a pair of iBGP peers.
1718 2) Check EMCP forwarding to these peers
1719 3) withdraw the IGP route to one of these peers.
1720 4) check forwarding continues to the remaining peer
1721 """
1722
1723 #
1724 # IGP+LDP core routes
1725 #
1726 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1727 [VppRoutePath(self.pg0.remote_ip4,
1728 self.pg0.sw_if_index,
1729 labels=[45])])
1730 core_10_0_0_45.add_vpp_config()
1731
1732 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1733 [VppRoutePath(self.pg1.remote_ip4,
1734 self.pg1.sw_if_index,
1735 labels=[46])])
1736 core_10_0_0_46.add_vpp_config()
1737
1738 #
1739 # Lot's of VPN routes. We need more the 64 so VPP will build
1740 # the fast convergence indirection
1741 #
1742 vpn_routes = []
1743 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001744 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001745 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001746 vpn_routes.append(VppIpRoute(
1747 self, dst, 32,
1748 [VppRoutePath(
1749 "10.0.0.45",
1750 0xffffffff,
1751 labels=[145],
1752 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1753 VppRoutePath(
1754 "10.0.0.46",
1755 0xffffffff,
1756 labels=[146],
1757 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1758 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001759 vpn_routes[ii].add_vpp_config()
1760
1761 pkts.append(Ether(dst=self.pg2.local_mac,
1762 src=self.pg2.remote_mac) /
1763 IP(src=self.pg2.remote_ip4, dst=dst) /
1764 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001765 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001766
1767 #
1768 # Send the packet stream (one pkt to each VPN route)
1769 # - expect a 50-50 split of the traffic
1770 #
1771 self.pg2.add_stream(pkts)
1772 self.pg_enable_capture(self.pg_interfaces)
1773 self.pg_start()
1774
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001775 rx0 = self.pg0._get_capture(NUM_PKTS)
1776 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001777
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001778 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001779 # with the split ratio, just as long as neither is 0
1780 self.assertNotEqual(0, len(rx0))
1781 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001782 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1783 "Expected all (%s) packets across both ECMP paths. "
1784 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001785
1786 #
1787 # use a test CLI command to stop the FIB walk process, this
1788 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001789 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001790 #
1791 self.vapi.ppcli("test fib-walk-process disable")
1792
1793 #
1794 # Withdraw one of the IGP routes
1795 #
1796 core_10_0_0_46.remove_vpp_config()
1797
1798 #
1799 # now all packets should be forwarded through the remaining peer
1800 #
1801 self.vapi.ppcli("clear trace")
1802 self.pg2.add_stream(pkts)
1803 self.pg_enable_capture(self.pg_interfaces)
1804 self.pg_start()
1805
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001806 rx0 = self.pg0.get_capture(NUM_PKTS)
1807 self.assertEqual(len(pkts), len(rx0),
1808 "Expected all (%s) packets across single path. "
1809 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001810
1811 #
1812 # enable the FIB walk process to converge the FIB
1813 #
1814 self.vapi.ppcli("test fib-walk-process enable")
1815
1816 #
1817 # packets should still be forwarded through the remaining peer
1818 #
1819 self.pg2.add_stream(pkts)
1820 self.pg_enable_capture(self.pg_interfaces)
1821 self.pg_start()
1822
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001823 rx0 = self.pg0.get_capture(NUM_PKTS)
1824 self.assertEqual(len(pkts), len(rx0),
1825 "Expected all (%s) packets across single path. "
1826 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001827
1828 #
1829 # Add the IGP route back and we return to load-balancing
1830 #
1831 core_10_0_0_46.add_vpp_config()
1832
1833 self.pg2.add_stream(pkts)
1834 self.pg_enable_capture(self.pg_interfaces)
1835 self.pg_start()
1836
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001837 rx0 = self.pg0._get_capture(NUM_PKTS)
1838 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001839 self.assertNotEqual(0, len(rx0))
1840 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001841 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1842 "Expected all (%s) packets across both ECMP paths. "
1843 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001844
1845 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001846 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001847
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001848 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001849 2) Check EMCP forwarding to these peers
1850 3) withdraw one eBGP path - expect LB across remaining eBGP
1851 """
1852
1853 #
1854 # Lot's of VPN routes. We need more the 64 so VPP will build
1855 # the fast convergence indirection
1856 #
1857 vpn_routes = []
1858 vpn_bindings = []
1859 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001860 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001861 dst = "192.168.1.%d" % ii
1862 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001863 vpn_routes.append(VppIpRoute(
1864 self, dst, 32,
1865 [VppRoutePath(
1866 self.pg2.remote_ip4,
1867 0xffffffff,
1868 nh_table_id=1,
1869 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1870 VppRoutePath(
1871 self.pg3.remote_ip4,
1872 0xffffffff,
1873 nh_table_id=1,
1874 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1875 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001876 vpn_routes[ii].add_vpp_config()
1877
1878 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1879 ip_table_id=1))
1880 vpn_bindings[ii].add_vpp_config()
1881
1882 pkts.append(Ether(dst=self.pg0.local_mac,
1883 src=self.pg0.remote_mac) /
1884 MPLS(label=local_label, ttl=64) /
1885 IP(src=self.pg0.remote_ip4, dst=dst) /
1886 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001887 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001888
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001889 #
1890 # Send the packet stream (one pkt to each VPN route)
1891 # - expect a 50-50 split of the traffic
1892 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001893 self.pg0.add_stream(pkts)
1894 self.pg_enable_capture(self.pg_interfaces)
1895 self.pg_start()
1896
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001897 rx0 = self.pg2._get_capture(NUM_PKTS)
1898 rx1 = self.pg3._get_capture(NUM_PKTS)
1899
1900 # not testing the LB hashing algorithm so we're not concerned
1901 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001902 self.assertNotEqual(0, len(rx0))
1903 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001904 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1905 "Expected all (%s) packets across both ECMP paths. "
1906 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001907
1908 #
1909 # use a test CLI command to stop the FIB walk process, this
1910 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001911 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001912 #
1913 self.vapi.ppcli("test fib-walk-process disable")
1914
1915 #
1916 # withdraw the connected prefix on the interface.
1917 #
1918 self.pg2.unconfig_ip4()
1919
1920 #
1921 # now all packets should be forwarded through the remaining peer
1922 #
1923 self.pg0.add_stream(pkts)
1924 self.pg_enable_capture(self.pg_interfaces)
1925 self.pg_start()
1926
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001927 rx0 = self.pg3.get_capture(NUM_PKTS)
1928 self.assertEqual(len(pkts), len(rx0),
1929 "Expected all (%s) packets across single path. "
1930 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001931
1932 #
1933 # enable the FIB walk process to converge the FIB
1934 #
1935 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001936
1937 #
1938 # packets should still be forwarded through the remaining peer
1939 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001940 self.pg0.add_stream(pkts)
1941 self.pg_enable_capture(self.pg_interfaces)
1942 self.pg_start()
1943
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001944 rx0 = self.pg3.get_capture(NUM_PKTS)
1945 self.assertEqual(len(pkts), len(rx0),
1946 "Expected all (%s) packets across single path. "
1947 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001948
1949 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001950 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001951 #
1952 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001953 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001954
1955 self.pg0.add_stream(pkts)
1956 self.pg_enable_capture(self.pg_interfaces)
1957 self.pg_start()
1958
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001959 rx0 = self.pg2._get_capture(NUM_PKTS)
1960 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001961 self.assertNotEqual(0, len(rx0))
1962 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001963 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1964 "Expected all (%s) packets across both ECMP paths. "
1965 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001966
1967 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001968 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001969
1970 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1971 2) Check EMCP forwarding to these peers
1972 3) withdraw one eBGP path - expect LB across remaining eBGP
1973 """
1974
1975 #
1976 # Lot's of VPN routes. We need more the 64 so VPP will build
1977 # the fast convergence indirection
1978 #
1979 vpn_routes = []
1980 vpn_bindings = []
1981 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001982 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001983 dst = "3000::%d" % ii
1984 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001985 vpn_routes.append(VppIpRoute(
1986 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001987 [VppRoutePath(
1988 self.pg2.remote_ip6,
1989 0xffffffff,
1990 nh_table_id=1,
1991 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1992 VppRoutePath(
1993 self.pg3.remote_ip6,
1994 0xffffffff,
1995 nh_table_id=1,
1996 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1997 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001998 vpn_routes[ii].add_vpp_config()
1999
2000 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07002001 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002002 vpn_bindings[ii].add_vpp_config()
2003
2004 pkts.append(Ether(dst=self.pg0.local_mac,
2005 src=self.pg0.remote_mac) /
2006 MPLS(label=local_label, ttl=64) /
2007 IPv6(src=self.pg0.remote_ip6, dst=dst) /
2008 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002009 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002010 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002011
2012 self.pg0.add_stream(pkts)
2013 self.pg_enable_capture(self.pg_interfaces)
2014 self.pg_start()
2015
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002016 rx0 = self.pg2._get_capture(NUM_PKTS)
2017 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002018 self.assertNotEqual(0, len(rx0))
2019 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002020 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2021 "Expected all (%s) packets across both ECMP paths. "
2022 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002023
2024 #
2025 # use a test CLI command to stop the FIB walk process, this
2026 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002027 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002028 #
2029 self.vapi.ppcli("test fib-walk-process disable")
2030
2031 #
2032 # withdraw the connected prefix on the interface.
2033 # and shutdown the interface so the ND cache is flushed.
2034 #
2035 self.pg2.unconfig_ip6()
2036 self.pg2.admin_down()
2037
2038 #
2039 # now all packets should be forwarded through the remaining peer
2040 #
2041 self.pg0.add_stream(pkts)
2042 self.pg_enable_capture(self.pg_interfaces)
2043 self.pg_start()
2044
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002045 rx0 = self.pg3.get_capture(NUM_PKTS)
2046 self.assertEqual(len(pkts), len(rx0),
2047 "Expected all (%s) packets across single path. "
2048 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002049
2050 #
2051 # enable the FIB walk process to converge the FIB
2052 #
2053 self.vapi.ppcli("test fib-walk-process enable")
2054 self.pg0.add_stream(pkts)
2055 self.pg_enable_capture(self.pg_interfaces)
2056 self.pg_start()
2057
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002058 rx0 = self.pg3.get_capture(NUM_PKTS)
2059 self.assertEqual(len(pkts), len(rx0),
2060 "Expected all (%s) packets across single path. "
2061 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002062
2063 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002064 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002065 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002066 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002067 self.pg2.admin_up()
2068 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002069 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002070
2071 self.pg0.add_stream(pkts)
2072 self.pg_enable_capture(self.pg_interfaces)
2073 self.pg_start()
2074
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002075 rx0 = self.pg2._get_capture(NUM_PKTS)
2076 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002077 self.assertNotEqual(0, len(rx0))
2078 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002079 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2080 "Expected all (%s) packets across both ECMP paths. "
2081 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002082
2083
Neale Rannsda78f952017-05-24 09:15:43 -07002084class TestMPLSL2(VppTestCase):
2085 """ MPLS-L2 """
2086
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002087 @classmethod
2088 def setUpClass(cls):
2089 super(TestMPLSL2, cls).setUpClass()
2090
2091 @classmethod
2092 def tearDownClass(cls):
2093 super(TestMPLSL2, cls).tearDownClass()
2094
Neale Rannsda78f952017-05-24 09:15:43 -07002095 def setUp(self):
2096 super(TestMPLSL2, self).setUp()
2097
2098 # create 2 pg interfaces
2099 self.create_pg_interfaces(range(2))
2100
Neale Ranns15002542017-09-10 04:39:11 -07002101 # create the default MPLS table
2102 self.tables = []
2103 tbl = VppMplsTable(self, 0)
2104 tbl.add_vpp_config()
2105 self.tables.append(tbl)
2106
Neale Ranns1976f362019-11-06 13:13:01 +00002107 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002108 self.pg0.admin_up()
2109 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002110 self.pg0.enable_mpls()
2111
Neale Ranns15002542017-09-10 04:39:11 -07002112 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002113 for i in self.pg_interfaces[1:]:
2114 i.admin_up()
2115
2116 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002117 for i in self.pg_interfaces[1:]:
2118 i.admin_down()
2119
2120 self.pg0.disable_mpls()
2121 self.pg0.unconfig_ip4()
2122 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002123 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002124
Neale Ranns31ed7442018-02-23 05:29:09 -08002125 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002126 capture = verify_filter(capture, sent)
2127
2128 self.assertEqual(len(capture), len(sent))
2129
2130 for i in range(len(capture)):
2131 tx = sent[i]
2132 rx = capture[i]
2133
2134 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002135 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002136
2137 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002138 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002139
2140 self.assertEqual(rx_eth.src, tx_eth.src)
2141 self.assertEqual(rx_eth.dst, tx_eth.dst)
2142
Neale Ranns1976f362019-11-06 13:13:01 +00002143 def verify_arp_req(self, rx, smac, sip, dip):
2144 ether = rx[Ether]
2145 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2146 self.assertEqual(ether.src, smac)
2147
2148 arp = rx[ARP]
2149 self.assertEqual(arp.hwtype, 1)
2150 self.assertEqual(arp.ptype, 0x800)
2151 self.assertEqual(arp.hwlen, 6)
2152 self.assertEqual(arp.plen, 4)
2153 self.assertEqual(arp.op, ARP.who_has)
2154 self.assertEqual(arp.hwsrc, smac)
2155 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2156 self.assertEqual(arp.psrc, sip)
2157 self.assertEqual(arp.pdst, dip)
2158
Neale Rannsda78f952017-05-24 09:15:43 -07002159 def test_vpws(self):
2160 """ Virtual Private Wire Service """
2161
2162 #
2163 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002164 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2165 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002166 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002167 mpls_tun_1 = VppMPLSTunnelInterface(
2168 self,
2169 [VppRoutePath(self.pg0.remote_ip4,
2170 self.pg0.sw_if_index,
2171 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2172 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002173 mpls_tun_1.add_vpp_config()
2174 mpls_tun_1.admin_up()
2175
2176 #
2177 # Create a label entry to for 55 that does L2 input to the tunnel
2178 #
2179 route_55_eos = VppMplsRoute(
2180 self, 55, 1,
2181 [VppRoutePath("0.0.0.0",
2182 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002183 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2184 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2185 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002186 route_55_eos.add_vpp_config()
2187
2188 #
2189 # Cross-connect the tunnel with one of the customers L2 interfaces
2190 #
2191 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2192 mpls_tun_1.sw_if_index,
2193 enable=1)
2194 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2195 self.pg1.sw_if_index,
2196 enable=1)
2197
2198 #
2199 # inject a packet from the core
2200 #
2201 pcore = (Ether(dst=self.pg0.local_mac,
2202 src=self.pg0.remote_mac) /
2203 MPLS(label=55, ttl=64) /
2204 Ether(dst="00:00:de:ad:ba:be",
2205 src="00:00:de:ad:be:ef") /
2206 IP(src="10.10.10.10", dst="11.11.11.11") /
2207 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002208 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002209
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002210 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002211 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2212 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002213
Neale Ranns31ed7442018-02-23 05:29:09 -08002214 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2215 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002216
2217 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002218 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002219 # there's no resolved ARP entry so the first packet we see should be
2220 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002221 #
Neale Ranns1976f362019-11-06 13:13:01 +00002222 tx1 = pcore[MPLS].payload
2223 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2224
2225 self.verify_arp_req(rx1[0],
2226 self.pg0.local_mac,
2227 self.pg0.local_ip4,
2228 self.pg0.remote_ip4)
2229
2230 #
2231 # resolve the ARP entries and send again
2232 #
2233 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002234 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002235 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002236
Neale Ranns31ed7442018-02-23 05:29:09 -08002237 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002238
2239 def test_vpls(self):
2240 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002241
2242 # we skipped this in the setup
2243 self.pg0.resolve_arp()
2244
Neale Rannsda78f952017-05-24 09:15:43 -07002245 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002246 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002247 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002248 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002249 self,
2250 [VppRoutePath(self.pg0.remote_ip4,
2251 self.pg0.sw_if_index,
2252 labels=[VppMplsLabel(42)])],
2253 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002254 mpls_tun1.add_vpp_config()
2255 mpls_tun1.admin_up()
2256
2257 mpls_tun2 = VppMPLSTunnelInterface(
2258 self,
2259 [VppRoutePath(self.pg0.remote_ip4,
2260 self.pg0.sw_if_index,
2261 labels=[VppMplsLabel(43)])],
2262 is_l2=1)
2263 mpls_tun2.add_vpp_config()
2264 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002265
2266 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002267 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2268 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002269 #
2270 route_55_eos = VppMplsRoute(
2271 self, 55, 1,
2272 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002273 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002274 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2275 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2276 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002277
2278 route_56_eos = VppMplsRoute(
2279 self, 56, 1,
2280 [VppRoutePath("0.0.0.0",
2281 mpls_tun2.sw_if_index,
2282 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2283 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2284 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2285 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2286
2287 # move me
2288 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002289 route_55_eos.add_vpp_config()
2290
Neale Ranns1dbcf302019-07-19 11:44:53 +00002291 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2292
Neale Rannsda78f952017-05-24 09:15:43 -07002293 #
2294 # add to tunnel to the customers bridge-domain
2295 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002296 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002297 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2298 self.vapi.sw_interface_set_l2_bridge(
2299 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002300 self.vapi.sw_interface_set_l2_bridge(
2301 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002302
2303 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002304 # Packet from host on the customer interface to each host
2305 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002306 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002307 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2308 src="00:00:de:ad:be:ef") /
2309 IP(src="10.10.10.10", dst="11.11.11.11") /
2310 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002311 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002312 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2313 src="00:00:de:ad:be:ef") /
2314 IP(src="10.10.10.10", dst="11.11.11.12") /
2315 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002316 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002317 p_core1 = (Ether(dst=self.pg0.local_mac,
2318 src=self.pg0.remote_mac) /
2319 MPLS(label=55, ttl=64) /
2320 Ether(src="00:00:de:ad:ba:b1",
2321 dst="00:00:de:ad:be:ef") /
2322 IP(dst="10.10.10.10", src="11.11.11.11") /
2323 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002324 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002325 p_core2 = (Ether(dst=self.pg0.local_mac,
2326 src=self.pg0.remote_mac) /
2327 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002328 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002329 Ether(src="00:00:de:ad:ba:b2",
2330 dst="00:00:de:ad:be:ef") /
2331 IP(dst="10.10.10.10", src="11.11.11.12") /
2332 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002333 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002334
2335 #
2336 # The BD is learning, so send in one of each packet to learn
2337 #
Neale Rannsda78f952017-05-24 09:15:43 -07002338
Neale Ranns1dbcf302019-07-19 11:44:53 +00002339 # 2 packets due to BD flooding
2340 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2341 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002342
Neale Ranns1dbcf302019-07-19 11:44:53 +00002343 # we've learnt this so expect it be be forwarded not flooded
2344 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2345 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2346 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002347
Neale Ranns1dbcf302019-07-19 11:44:53 +00002348 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2349 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2350 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002351
2352 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002353 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002354 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002355 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2356 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002357 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002358
Neale Ranns1dbcf302019-07-19 11:44:53 +00002359 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2360 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2361 [VppMplsLabel(43)])
2362
2363 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2364 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2365
Neale Rannsda78f952017-05-24 09:15:43 -07002366 #
2367 # remove interfaces from customers bridge-domain
2368 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002369 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002370 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2371 self.vapi.sw_interface_set_l2_bridge(
2372 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002373 self.vapi.sw_interface_set_l2_bridge(
2374 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002375
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002376
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002377if __name__ == '__main__':
2378 unittest.main(testRunner=VppTestRunner)