blob: 038ffd34f6c737d07ccd949640195bf844cc2c22 [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
6from framework import VppTestCase, VppTestRunner
Neale Rannsd5d7b962019-08-04 03:30:56 -07007from vpp_ip import DpoProto, INVALID_INDEX
Neale Ranns5a8123b2017-01-26 01:18:23 -08008from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -08009 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Rannsc0a93142018-09-05 15:42:26 -070010 MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \
Neale Ranns097fa662018-05-01 05:17:55 -070011 VppMplsLabel, MplsLspMode, find_mpls_route, \
12 FibPathProto, FibPathType, FibPathFlags, VppMplsLabel, MplsLspMode
Neale Ranns0f26c5a2017-03-01 15:12:11 -080013from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns8fe8cc22016-11-01 10:05:08 +000014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000017from scapy.layers.l2 import Ether, ARP
Neale Rannscb630ff2016-12-14 13:31:29 +010018from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070019from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000020from scapy.contrib.mpls import MPLS
21
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040022NUM_PKTS = 67
23
Neale Ranns1976f362019-11-06 13:13:01 +000024# scapy removed these attributes.
25# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
26# semantic names have more meaning than numbers. so here they are.
27ARP.who_has = 1
28ARP.is_at = 2
29
Klement Sekeradab231a2016-12-21 08:50:14 +010030
Neale Rannsda78f952017-05-24 09:15:43 -070031def verify_filter(capture, sent):
32 if not len(capture) == len(sent):
33 # filter out any IPv6 RAs from the capture
34 for p in capture:
35 if p.haslayer(IPv6):
36 capture.remove(p)
37 return capture
38
39
Neale Ranns31ed7442018-02-23 05:29:09 -080040def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070041 # the rx'd packet has the MPLS label popped
42 eth = rx[Ether]
43 tst.assertEqual(eth.type, 0x8847)
44
45 rx_mpls = rx[MPLS]
46
47 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080048 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
49 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
50 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
51
Neale Rannsda78f952017-05-24 09:15:43 -070052 if ii == len(mpls_labels) - 1:
53 tst.assertEqual(rx_mpls.s, 1)
54 else:
55 # not end of stack
56 tst.assertEqual(rx_mpls.s, 0)
57 # pop the label to expose the next
58 rx_mpls = rx_mpls[MPLS].payload
59
60
Neale Ranns8fe8cc22016-11-01 10:05:08 +000061class TestMPLS(VppTestCase):
62 """ MPLS Test Case """
63
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070064 @classmethod
65 def setUpClass(cls):
66 super(TestMPLS, cls).setUpClass()
67
68 @classmethod
69 def tearDownClass(cls):
70 super(TestMPLS, cls).tearDownClass()
71
Neale Ranns8fe8cc22016-11-01 10:05:08 +000072 def setUp(self):
73 super(TestMPLS, self).setUp()
74
75 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080076 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000077
78 # setup both interfaces
79 # assign them different tables.
80 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070081 self.tables = []
82
83 tbl = VppMplsTable(self, 0)
84 tbl.add_vpp_config()
85 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000086
87 for i in self.pg_interfaces:
88 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070089
90 if table_id != 0:
91 tbl = VppIpTable(self, table_id)
92 tbl.add_vpp_config()
93 self.tables.append(tbl)
94 tbl = VppIpTable(self, table_id, is_ip6=1)
95 tbl.add_vpp_config()
96 self.tables.append(tbl)
97
Neale Ranns8fe8cc22016-11-01 10:05:08 +000098 i.set_table_ip4(table_id)
99 i.set_table_ip6(table_id)
100 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000101 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000102 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000103 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000104 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000105 table_id += 1
106
107 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800108 for i in self.pg_interfaces:
109 i.unconfig_ip4()
110 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700111 i.set_table_ip4(0)
112 i.set_table_ip6(0)
113 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800114 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700115 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000116
Neale Rannsad422ed2016-11-02 14:20:04 +0000117 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100118 def create_stream_labelled_ip4(
119 self,
120 src_if,
121 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100122 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800123 ip_itf=None,
124 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700125 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800126 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800127 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100128 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000129 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800130 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100131 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000132 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000133 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
134
135 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800136 p = p / MPLS(label=mpls_labels[ii].value,
137 ttl=mpls_labels[ii].ttl,
138 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100139 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800140 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800141 p = (p / IP(src=src_if.local_ip4,
142 dst=src_if.remote_ip4,
143 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800144 UDP(sport=1234, dport=1234) /
145 Raw(payload))
146 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800147 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800148 UDP(sport=1234, dport=1234) /
149 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100150 else:
151 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800152 dst=ip_itf.local_ip4,
153 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100154 ICMP())
155
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700156 if chksum:
157 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000158 info.data = p.copy()
159 pkts.append(p)
160 return pkts
161
Ole Troaneb284a12019-10-09 13:33:19 +0200162 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64,
163 ip_dscp=0, payload_size=None):
Klement Sekeradab231a2016-12-21 08:50:14 +0100164 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000165 pkts = []
166 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100167 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000168 payload = self.info_to_payload(info)
169 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800170 IP(src=src_if.remote_ip4, dst=dst_ip,
171 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000172 UDP(sport=1234, dport=1234) /
173 Raw(payload))
174 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200175 if payload_size:
176 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000177 pkts.append(p)
178 return pkts
179
Neale Ranns31ed7442018-02-23 05:29:09 -0800180 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
181 self.reset_packet_infos()
182 pkts = []
183 for i in range(0, 257):
184 info = self.create_packet_info(src_if, src_if)
185 payload = self.info_to_payload(info)
186 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
187 IPv6(src=src_if.remote_ip6, dst=dst_ip,
188 hlim=ip_ttl, tc=ip_dscp) /
189 UDP(sport=1234, dport=1234) /
190 Raw(payload))
191 info.data = p.copy()
192 pkts.append(p)
193 return pkts
194
195 def create_stream_labelled_ip6(self, src_if, mpls_labels,
196 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700197 if dst_ip is None:
198 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100199 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000200 pkts = []
201 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100202 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000203 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800204 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
205 for l in mpls_labels:
206 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
207
208 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
209 UDP(sport=1234, dport=1234) /
210 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000211 info.data = p.copy()
212 pkts.append(p)
213 return pkts
214
Neale Ranns31ed7442018-02-23 05:29:09 -0800215 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
216 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000217 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700218 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000219
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000220 self.assertEqual(len(capture), len(sent))
221
222 for i in range(len(capture)):
223 tx = sent[i]
224 rx = capture[i]
225
226 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000227 eth = rx[Ether]
228 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000229
230 tx_ip = tx[IP]
231 rx_ip = rx[IP]
232
Neale Rannscb630ff2016-12-14 13:31:29 +0100233 if not ping_resp:
234 self.assertEqual(rx_ip.src, tx_ip.src)
235 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800236 self.assertEqual(rx_ip.tos, ip_dscp)
237 if not ip_ttl:
238 # IP processing post pop has decremented the TTL
239 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
240 else:
241 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100242 else:
243 self.assertEqual(rx_ip.src, tx_ip.dst)
244 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000245
246 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000247 raise
248
Neale Rannsad422ed2016-11-02 14:20:04 +0000249 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800250 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000251 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700252 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000253
254 self.assertEqual(len(capture), len(sent))
255
256 for i in range(len(capture)):
257 tx = sent[i]
258 rx = capture[i]
259 tx_ip = tx[IP]
260 rx_ip = rx[IP]
261
Neale Ranns31ed7442018-02-23 05:29:09 -0800262 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000263
264 self.assertEqual(rx_ip.src, tx_ip.src)
265 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800266 if not ip_ttl:
267 # IP processing post pop has decremented the TTL
268 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
269 else:
270 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000271
272 except:
273 raise
274
Neale Ranns31ed7442018-02-23 05:29:09 -0800275 def verify_capture_labelled_ip6(self, src_if, capture, sent,
276 mpls_labels, ip_ttl=None):
277 try:
278 capture = verify_filter(capture, sent)
279
280 self.assertEqual(len(capture), len(sent))
281
282 for i in range(len(capture)):
283 tx = sent[i]
284 rx = capture[i]
285 tx_ip = tx[IPv6]
286 rx_ip = rx[IPv6]
287
288 verify_mpls_stack(self, rx, mpls_labels)
289
290 self.assertEqual(rx_ip.src, tx_ip.src)
291 self.assertEqual(rx_ip.dst, tx_ip.dst)
292 if not ip_ttl:
293 # IP processing post pop has decremented the TTL
294 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
295 else:
296 self.assertEqual(rx_ip.hlim, ip_ttl)
297
298 except:
299 raise
300
301 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000302 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700303 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000304
305 self.assertEqual(len(capture), len(sent))
306
307 for i in range(len(capture)):
308 tx = sent[i]
309 rx = capture[i]
310 tx_ip = tx[IP]
311 rx_ip = rx[IP]
312
Neale Ranns31ed7442018-02-23 05:29:09 -0800313 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000314
315 self.assertEqual(rx_ip.src, tx_ip.src)
316 self.assertEqual(rx_ip.dst, tx_ip.dst)
317 # IP processing post pop has decremented the TTL
318 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
319
320 except:
321 raise
322
323 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800324 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000325 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700326 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000327
328 self.assertEqual(len(capture), len(sent))
329
330 for i in range(len(capture)):
331 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800332 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000333 except:
334 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000335
Neale Ranns31ed7442018-02-23 05:29:09 -0800336 def verify_capture_ip6(self, src_if, capture, sent,
337 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000338 try:
339 self.assertEqual(len(capture), len(sent))
340
341 for i in range(len(capture)):
342 tx = sent[i]
343 rx = capture[i]
344
345 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000346 eth = rx[Ether]
347 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000348
349 tx_ip = tx[IPv6]
350 rx_ip = rx[IPv6]
351
352 self.assertEqual(rx_ip.src, tx_ip.src)
353 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800354 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000355 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800356 if not ip_hlim:
357 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
358 else:
359 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000360
361 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000362 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000363
Neale Ranns62fe07c2017-10-31 12:28:22 -0700364 def verify_capture_ip6_icmp(self, src_if, capture, sent):
365 try:
366 self.assertEqual(len(capture), len(sent))
367
368 for i in range(len(capture)):
369 tx = sent[i]
370 rx = capture[i]
371
372 # the rx'd packet has the MPLS label popped
373 eth = rx[Ether]
374 self.assertEqual(eth.type, 0x86DD)
375
376 tx_ip = tx[IPv6]
377 rx_ip = rx[IPv6]
378
379 self.assertEqual(rx_ip.dst, tx_ip.src)
380 # ICMP sourced from the interface's address
381 self.assertEqual(rx_ip.src, src_if.local_ip6)
382 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200383 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700384
385 icmp = rx[ICMPv6TimeExceeded]
386
387 except:
388 raise
389
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530390 def verify_capture_fragmented_labelled_ip4(self, src_if, capture, sent,
391 mpls_labels, ip_ttl=None):
392 try:
393 capture = verify_filter(capture, sent)
394
395 for i in range(len(capture)):
396 tx = sent[0]
397 rx = capture[i]
398 tx_ip = tx[IP]
399 rx_ip = rx[IP]
400
401 verify_mpls_stack(self, rx, mpls_labels)
402
403 self.assertEqual(rx_ip.src, tx_ip.src)
404 self.assertEqual(rx_ip.dst, tx_ip.dst)
405 if not ip_ttl:
406 # IP processing post pop has decremented the TTL
407 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
408 else:
409 self.assertEqual(rx_ip.ttl, ip_ttl)
410
411 except:
412 raise
413
Neale Rannsad422ed2016-11-02 14:20:04 +0000414 def test_swap(self):
415 """ MPLS label swap tests """
416
417 #
418 # A simple MPLS xconnect - eos label in label out
419 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800420 route_32_eos = VppMplsRoute(self, 32, 1,
421 [VppRoutePath(self.pg0.remote_ip4,
422 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800423 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000424 route_32_eos.add_vpp_config()
425
Neale Ranns775f73c2018-12-20 03:01:49 -0800426 self.assertTrue(
427 find_mpls_route(self, 0, 32, 1,
428 [VppRoutePath(self.pg0.remote_ip4,
429 self.pg0.sw_if_index,
430 labels=[VppMplsLabel(33)])]))
431
Neale Rannsad422ed2016-11-02 14:20:04 +0000432 #
433 # a stream that matches the route for 10.0.0.1
434 # PG0 is in the default table
435 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800436 tx = self.create_stream_labelled_ip4(self.pg0,
437 [VppMplsLabel(32, ttl=32, exp=1)])
438 rx = self.send_and_expect(self.pg0, tx, self.pg0)
439 self.verify_capture_labelled(self.pg0, rx, tx,
440 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000441
Neale Ranns008dbe12018-09-07 09:32:36 -0700442 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
443
Neale Rannsad422ed2016-11-02 14:20:04 +0000444 #
445 # A simple MPLS xconnect - non-eos label in label out
446 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800447 route_32_neos = VppMplsRoute(self, 32, 0,
448 [VppRoutePath(self.pg0.remote_ip4,
449 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800450 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000451 route_32_neos.add_vpp_config()
452
453 #
454 # a stream that matches the route for 10.0.0.1
455 # PG0 is in the default table
456 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800457 tx = self.create_stream_labelled_ip4(self.pg0,
458 [VppMplsLabel(32, ttl=21, exp=7),
459 VppMplsLabel(99)])
460 rx = self.send_and_expect(self.pg0, tx, self.pg0)
461 self.verify_capture_labelled(self.pg0, rx, tx,
462 [VppMplsLabel(33, ttl=20, exp=7),
463 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700464 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000465
Neale Ranns31ed7442018-02-23 05:29:09 -0800466 #
467 # A simple MPLS xconnect - non-eos label in label out, uniform mode
468 #
469 route_42_neos = VppMplsRoute(
470 self, 42, 0,
471 [VppRoutePath(self.pg0.remote_ip4,
472 self.pg0.sw_if_index,
473 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
474 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000475
Neale Ranns31ed7442018-02-23 05:29:09 -0800476 tx = self.create_stream_labelled_ip4(self.pg0,
477 [VppMplsLabel(42, ttl=21, exp=7),
478 VppMplsLabel(99)])
479 rx = self.send_and_expect(self.pg0, tx, self.pg0)
480 self.verify_capture_labelled(self.pg0, rx, tx,
481 [VppMplsLabel(43, ttl=20, exp=7),
482 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000483
484 #
485 # An MPLS xconnect - EOS label in IP out
486 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800487 route_33_eos = VppMplsRoute(self, 33, 1,
488 [VppRoutePath(self.pg0.remote_ip4,
489 self.pg0.sw_if_index,
490 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000491 route_33_eos.add_vpp_config()
492
Neale Ranns31ed7442018-02-23 05:29:09 -0800493 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
494 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000495 self.verify_capture_ip4(self.pg0, rx, tx)
496
497 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700498 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700499 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800500 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700501 dst_ip=self.pg0.remote_ip4,
502 n=65,
503 chksum=1)
504 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
505
506 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800507 # An MPLS xconnect - EOS label in IP out, uniform mode
508 #
509 route_3333_eos = VppMplsRoute(
510 self, 3333, 1,
511 [VppRoutePath(self.pg0.remote_ip4,
512 self.pg0.sw_if_index,
513 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
514 route_3333_eos.add_vpp_config()
515
516 tx = self.create_stream_labelled_ip4(
517 self.pg0,
518 [VppMplsLabel(3333, ttl=55, exp=3)])
519 rx = self.send_and_expect(self.pg0, tx, self.pg0)
520 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
521 tx = self.create_stream_labelled_ip4(
522 self.pg0,
523 [VppMplsLabel(3333, ttl=66, exp=4)])
524 rx = self.send_and_expect(self.pg0, tx, self.pg0)
525 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
526
527 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700528 # An MPLS xconnect - EOS label in IPv6 out
529 #
530 route_333_eos = VppMplsRoute(
531 self, 333, 1,
532 [VppRoutePath(self.pg0.remote_ip6,
533 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700534 labels=[])],
535 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700536 route_333_eos.add_vpp_config()
537
Neale Ranns31ed7442018-02-23 05:29:09 -0800538 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
539 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700540 self.verify_capture_ip6(self.pg0, rx, tx)
541
542 #
543 # disposed packets have an TTL expired
544 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800545 tx = self.create_stream_labelled_ip6(self.pg0,
546 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700547 dst_ip=self.pg1.remote_ip6,
548 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800549 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700550 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
551
552 #
553 # An MPLS xconnect - EOS label in IPv6 out w imp-null
554 #
555 route_334_eos = VppMplsRoute(
556 self, 334, 1,
557 [VppRoutePath(self.pg0.remote_ip6,
558 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700559 labels=[VppMplsLabel(3)])],
560 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700561 route_334_eos.add_vpp_config()
562
Neale Ranns31ed7442018-02-23 05:29:09 -0800563 tx = self.create_stream_labelled_ip6(self.pg0,
564 [VppMplsLabel(334, ttl=64)])
565 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700566 self.verify_capture_ip6(self.pg0, rx, tx)
567
568 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800569 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
570 #
571 route_335_eos = VppMplsRoute(
572 self, 335, 1,
573 [VppRoutePath(self.pg0.remote_ip6,
574 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700575 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
576 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800577 route_335_eos.add_vpp_config()
578
579 tx = self.create_stream_labelled_ip6(
580 self.pg0,
581 [VppMplsLabel(335, ttl=27, exp=4)])
582 rx = self.send_and_expect(self.pg0, tx, self.pg0)
583 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
584
585 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700586 # disposed packets have an TTL expired
587 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800588 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700589 dst_ip=self.pg1.remote_ip6,
590 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800591 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700592 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
593
594 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000595 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
596 # so this traffic should be dropped.
597 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800598 route_33_neos = VppMplsRoute(self, 33, 0,
599 [VppRoutePath(self.pg0.remote_ip4,
600 self.pg0.sw_if_index,
601 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000602 route_33_neos.add_vpp_config()
603
Neale Ranns31ed7442018-02-23 05:29:09 -0800604 tx = self.create_stream_labelled_ip4(self.pg0,
605 [VppMplsLabel(33),
606 VppMplsLabel(99)])
607 self.send_and_assert_no_replies(
608 self.pg0, tx,
609 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000610
611 #
612 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800613 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000614 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800615 route_34_eos = VppMplsRoute(self, 34, 1,
616 [VppRoutePath("0.0.0.0",
617 0xffffffff,
618 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800619 labels=[VppMplsLabel(44),
620 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000621 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700622 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000623
Neale Ranns31ed7442018-02-23 05:29:09 -0800624 tx = self.create_stream_labelled_ip4(self.pg0,
625 [VppMplsLabel(34, ttl=3)])
626 rx = self.send_and_expect(self.pg0, tx, self.pg0)
627 self.verify_capture_labelled(self.pg0, rx, tx,
628 [VppMplsLabel(33),
629 VppMplsLabel(44),
630 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000631
Neale Ranns008dbe12018-09-07 09:32:36 -0700632 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
633 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
634
Neale Ranns31ed7442018-02-23 05:29:09 -0800635 #
636 # A recursive EOS x-connect, which resolves through another x-connect
637 # in uniform mode
638 #
639 route_35_eos = VppMplsRoute(
640 self, 35, 1,
641 [VppRoutePath("0.0.0.0",
642 0xffffffff,
643 nh_via_label=42,
644 labels=[VppMplsLabel(44)])])
645 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000646
Neale Ranns31ed7442018-02-23 05:29:09 -0800647 tx = self.create_stream_labelled_ip4(self.pg0,
648 [VppMplsLabel(35, ttl=3)])
649 rx = self.send_and_expect(self.pg0, tx, self.pg0)
650 self.verify_capture_labelled(self.pg0, rx, tx,
651 [VppMplsLabel(43, ttl=2),
652 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000653
654 #
Matej Klottondeb69842016-12-09 15:05:46 +0100655 # A recursive non-EOS x-connect, which resolves through another
656 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000657 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800658 route_34_neos = VppMplsRoute(self, 34, 0,
659 [VppRoutePath("0.0.0.0",
660 0xffffffff,
661 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800662 labels=[VppMplsLabel(44),
663 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000664 route_34_neos.add_vpp_config()
665
Neale Ranns31ed7442018-02-23 05:29:09 -0800666 tx = self.create_stream_labelled_ip4(self.pg0,
667 [VppMplsLabel(34, ttl=45),
668 VppMplsLabel(99)])
669 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100670 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800671 self.verify_capture_labelled(self.pg0, rx, tx,
672 [VppMplsLabel(33),
673 VppMplsLabel(44),
674 VppMplsLabel(46, ttl=44),
675 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000676
677 #
Matej Klottondeb69842016-12-09 15:05:46 +0100678 # an recursive IP route that resolves through the recursive non-eos
679 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000680 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800681 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
682 [VppRoutePath("0.0.0.0",
683 0xffffffff,
684 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800685 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000686 ip_10_0_0_1.add_vpp_config()
687
Neale Rannsad422ed2016-11-02 14:20:04 +0000688 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800689 rx = self.send_and_expect(self.pg0, tx, self.pg0)
690 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
691 [VppMplsLabel(33),
692 VppMplsLabel(44),
693 VppMplsLabel(46),
694 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700695 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000696
697 ip_10_0_0_1.remove_vpp_config()
698 route_34_neos.remove_vpp_config()
699 route_34_eos.remove_vpp_config()
700 route_33_neos.remove_vpp_config()
701 route_33_eos.remove_vpp_config()
702 route_32_neos.remove_vpp_config()
703 route_32_eos.remove_vpp_config()
704
705 def test_bind(self):
706 """ MPLS Local Label Binding test """
707
708 #
709 # Add a non-recursive route with a single out label
710 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800711 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
712 [VppRoutePath(self.pg0.remote_ip4,
713 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800714 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000715 route_10_0_0_1.add_vpp_config()
716
717 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800718 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000719 binding.add_vpp_config()
720
721 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800722 tx = self.create_stream_labelled_ip4(self.pg0,
723 [VppMplsLabel(44),
724 VppMplsLabel(99)])
725 rx = self.send_and_expect(self.pg0, tx, self.pg0)
726 self.verify_capture_labelled(self.pg0, rx, tx,
727 [VppMplsLabel(45, ttl=63),
728 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000729
730 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800731 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
732 rx = self.send_and_expect(self.pg0, tx, self.pg0)
733 self.verify_capture_labelled(self.pg0, rx, tx,
734 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000735
736 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000737 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800738 rx = self.send_and_expect(self.pg0, tx, self.pg0)
739 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000740
741 #
742 # cleanup
743 #
744 binding.remove_vpp_config()
745 route_10_0_0_1.remove_vpp_config()
746
747 def test_imposition(self):
748 """ MPLS label imposition test """
749
750 #
751 # Add a non-recursive route with a single out label
752 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800753 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
754 [VppRoutePath(self.pg0.remote_ip4,
755 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800756 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000757 route_10_0_0_1.add_vpp_config()
758
759 #
760 # a stream that matches the route for 10.0.0.1
761 # PG0 is in the default table
762 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000763 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800764 rx = self.send_and_expect(self.pg0, tx, self.pg0)
765 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000766
767 #
768 # Add a non-recursive route with a 3 out labels
769 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800770 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
771 [VppRoutePath(self.pg0.remote_ip4,
772 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800773 labels=[VppMplsLabel(32),
774 VppMplsLabel(33),
775 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000776 route_10_0_0_2.add_vpp_config()
777
Neale Ranns31ed7442018-02-23 05:29:09 -0800778 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
779 ip_ttl=44, ip_dscp=0xff)
780 rx = self.send_and_expect(self.pg0, tx, self.pg0)
781 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
782 [VppMplsLabel(32),
783 VppMplsLabel(33),
784 VppMplsLabel(34)],
785 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000786
Neale Ranns31ed7442018-02-23 05:29:09 -0800787 #
788 # Add a non-recursive route with a single out label in uniform mode
789 #
790 route_10_0_0_3 = VppIpRoute(
791 self, "10.0.0.3", 32,
792 [VppRoutePath(self.pg0.remote_ip4,
793 self.pg0.sw_if_index,
794 labels=[VppMplsLabel(32,
795 mode=MplsLspMode.UNIFORM)])])
796 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000797
Neale Ranns31ed7442018-02-23 05:29:09 -0800798 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
799 ip_ttl=54, ip_dscp=0xbe)
800 rx = self.send_and_expect(self.pg0, tx, self.pg0)
801 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
802 [VppMplsLabel(32, ttl=53, exp=5)])
803
804 #
805 # Add a IPv6 non-recursive route with a single out label in
806 # uniform mode
807 #
808 route_2001_3 = VppIpRoute(
809 self, "2001::3", 128,
810 [VppRoutePath(self.pg0.remote_ip6,
811 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800812 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700813 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800814 route_2001_3.add_vpp_config()
815
816 tx = self.create_stream_ip6(self.pg0, "2001::3",
817 ip_ttl=54, ip_dscp=0xbe)
818 rx = self.send_and_expect(self.pg0, tx, self.pg0)
819 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
820 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000821
822 #
Matej Klottondeb69842016-12-09 15:05:46 +0100823 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000824 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800825 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
826 [VppRoutePath("10.0.0.1",
827 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800828 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000829 route_11_0_0_1.add_vpp_config()
830
831 #
832 # a stream that matches the route for 11.0.0.1, should pick up
833 # the label stack for 11.0.0.1 and 10.0.0.1
834 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000835 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800836 rx = self.send_and_expect(self.pg0, tx, self.pg0)
837 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
838 [VppMplsLabel(32),
839 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000840
Neale Ranns008dbe12018-09-07 09:32:36 -0700841 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
842
Neale Rannsad422ed2016-11-02 14:20:04 +0000843 #
844 # add a recursive path, with 2 labels, via the 3 label route
845 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800846 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
847 [VppRoutePath("10.0.0.2",
848 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800849 labels=[VppMplsLabel(44),
850 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000851 route_11_0_0_2.add_vpp_config()
852
853 #
854 # a stream that matches the route for 11.0.0.1, should pick up
855 # the label stack for 11.0.0.1 and 10.0.0.1
856 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000857 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800858 rx = self.send_and_expect(self.pg0, tx, self.pg0)
859 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
860 [VppMplsLabel(32),
861 VppMplsLabel(33),
862 VppMplsLabel(34),
863 VppMplsLabel(44),
864 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000865
Neale Ranns008dbe12018-09-07 09:32:36 -0700866 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
867
868 rx = self.send_and_expect(self.pg0, tx, self.pg0)
869 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
870 [VppMplsLabel(32),
871 VppMplsLabel(33),
872 VppMplsLabel(34),
873 VppMplsLabel(44),
874 VppMplsLabel(45)])
875
876 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
877
Neale Rannsad422ed2016-11-02 14:20:04 +0000878 #
879 # cleanup
880 #
881 route_11_0_0_2.remove_vpp_config()
882 route_11_0_0_1.remove_vpp_config()
883 route_10_0_0_2.remove_vpp_config()
884 route_10_0_0_1.remove_vpp_config()
885
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530886 def test_imposition_fragmentation(self):
887 """ MPLS label imposition fragmentation test """
888
889 #
890 # Add a ipv4 non-recursive route with a single out label
891 #
892 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
893 [VppRoutePath(self.pg0.remote_ip4,
894 self.pg0.sw_if_index,
895 labels=[VppMplsLabel(32)])])
896 route_10_0_0_1.add_vpp_config()
897
898 #
899 # a stream that matches the route for 10.0.0.1
900 # PG0 is in the default table
901 #
902 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
903 for i in range(0, 257):
904 self.extend_packet(tx[i], 10000)
905
906 #
907 # 5 fragments per packet (257*5=1285)
908 #
909 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
910 self.verify_capture_fragmented_labelled_ip4(self.pg0, rx, tx,
911 [VppMplsLabel(32)])
912
913 #
914 # cleanup
915 #
916 route_10_0_0_1.remove_vpp_config()
917
Neale Ranns31ed7442018-02-23 05:29:09 -0800918 def test_tunnel_pipe(self):
919 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000920
921 #
Ole Troaneb284a12019-10-09 13:33:19 +0200922 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +0000923 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800924 mpls_tun = VppMPLSTunnelInterface(
925 self,
926 [VppRoutePath(self.pg0.remote_ip4,
927 self.pg0.sw_if_index,
928 labels=[VppMplsLabel(44),
929 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800930 mpls_tun.add_vpp_config()
931 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000932
933 #
934 # add an unlabelled route through the new tunnel
935 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800936 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
937 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800938 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800939 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000940
941 self.vapi.cli("clear trace")
942 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
943 self.pg0.add_stream(tx)
944
945 self.pg_enable_capture(self.pg_interfaces)
946 self.pg_start()
947
948 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800949 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
950 [VppMplsLabel(44),
951 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000952
Neale Ranns8c4611b2017-05-23 03:43:47 -0700953 #
954 # add a labelled route through the new tunnel
955 #
956 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
957 [VppRoutePath("0.0.0.0",
958 mpls_tun._sw_if_index,
959 labels=[33])])
960 route_10_0_0_4.add_vpp_config()
961
962 self.vapi.cli("clear trace")
963 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
964 self.pg0.add_stream(tx)
965
966 self.pg_enable_capture(self.pg_interfaces)
967 self.pg_start()
968
969 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800970 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
971 [VppMplsLabel(44),
972 VppMplsLabel(46),
973 VppMplsLabel(33, ttl=255)])
974
Ole Troaneb284a12019-10-09 13:33:19 +0200975 #
976 # change tunnel's MTU to a low value
977 #
978 mpls_tun.set_l3_mtu(1200)
979
980 # send IP into the tunnel to be fragmented
981 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
982 payload_size=1500)
983 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
984
985 fake_tx = []
986 for p in tx:
987 fake_tx.append(p)
988 fake_tx.append(p)
989 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
990 [VppMplsLabel(44),
991 VppMplsLabel(46)])
992
993 # send MPLS into the tunnel to be fragmented
994 tx = self.create_stream_ip4(self.pg0, "10.0.0.4",
995 payload_size=1500)
996 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
997
998 fake_tx = []
999 for p in tx:
1000 fake_tx.append(p)
1001 fake_tx.append(p)
1002 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1003 [VppMplsLabel(44),
1004 VppMplsLabel(46),
1005 VppMplsLabel(33, ttl=255)])
1006
Neale Ranns31ed7442018-02-23 05:29:09 -08001007 def test_tunnel_uniform(self):
1008 """ MPLS Tunnel Tests - Uniform """
1009
1010 #
1011 # Create a tunnel with a single out label
1012 # The label stack is specified here from outer to inner
1013 #
1014 mpls_tun = VppMPLSTunnelInterface(
1015 self,
1016 [VppRoutePath(self.pg0.remote_ip4,
1017 self.pg0.sw_if_index,
1018 labels=[VppMplsLabel(44, ttl=32),
1019 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1020 mpls_tun.add_vpp_config()
1021 mpls_tun.admin_up()
1022
1023 #
1024 # add an unlabelled route through the new tunnel
1025 #
1026 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1027 [VppRoutePath("0.0.0.0",
1028 mpls_tun._sw_if_index)])
1029 route_10_0_0_3.add_vpp_config()
1030
1031 self.vapi.cli("clear trace")
1032 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1033 self.pg0.add_stream(tx)
1034
1035 self.pg_enable_capture(self.pg_interfaces)
1036 self.pg_start()
1037
1038 rx = self.pg0.get_capture()
1039 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1040 [VppMplsLabel(44, ttl=32),
1041 VppMplsLabel(46, ttl=23)])
1042
1043 #
1044 # add a labelled route through the new tunnel
1045 #
1046 route_10_0_0_4 = VppIpRoute(
1047 self, "10.0.0.4", 32,
1048 [VppRoutePath("0.0.0.0",
1049 mpls_tun._sw_if_index,
1050 labels=[VppMplsLabel(33, ttl=47)])])
1051 route_10_0_0_4.add_vpp_config()
1052
1053 self.vapi.cli("clear trace")
1054 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1055 self.pg0.add_stream(tx)
1056
1057 self.pg_enable_capture(self.pg_interfaces)
1058 self.pg_start()
1059
1060 rx = self.pg0.get_capture()
1061 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1062 [VppMplsLabel(44, ttl=32),
1063 VppMplsLabel(46, ttl=47),
1064 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001065
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001066 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001067 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001068
1069 for ii in range(10):
1070 mpls_tun = VppMPLSTunnelInterface(
1071 self,
1072 [VppRoutePath(self.pg0.remote_ip4,
1073 self.pg0.sw_if_index,
1074 labels=[VppMplsLabel(44, ttl=32),
1075 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1076 mpls_tun.add_vpp_config()
1077 mpls_tun.admin_up()
1078
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001079 def test_v4_exp_null(self):
1080 """ MPLS V4 Explicit NULL test """
1081
1082 #
1083 # The first test case has an MPLS TTL of 0
1084 # all packet should be dropped
1085 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001086 tx = self.create_stream_labelled_ip4(self.pg0,
1087 [VppMplsLabel(0, ttl=0)])
1088 self.send_and_assert_no_replies(self.pg0, tx,
1089 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001090
1091 #
1092 # a stream with a non-zero MPLS TTL
1093 # PG0 is in the default table
1094 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001095 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1096 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001097 self.verify_capture_ip4(self.pg0, rx, tx)
1098
1099 #
1100 # a stream with a non-zero MPLS TTL
1101 # PG1 is in table 1
1102 # we are ensuring the post-pop lookup occurs in the VRF table
1103 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001104 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1105 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1106 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001107
1108 def test_v6_exp_null(self):
1109 """ MPLS V6 Explicit NULL test """
1110
1111 #
1112 # a stream with a non-zero MPLS TTL
1113 # PG0 is in the default table
1114 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001115 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1116 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001117 self.verify_capture_ip6(self.pg0, rx, tx)
1118
1119 #
1120 # a stream with a non-zero MPLS TTL
1121 # PG1 is in table 1
1122 # we are ensuring the post-pop lookup occurs in the VRF table
1123 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001124 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1125 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001126 self.verify_capture_ip6(self.pg0, rx, tx)
1127
Neale Rannscb630ff2016-12-14 13:31:29 +01001128 def test_deag(self):
1129 """ MPLS Deagg """
1130
1131 #
1132 # A de-agg route - next-hop lookup in default table
1133 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001134 route_34_eos = VppMplsRoute(self, 34, 1,
1135 [VppRoutePath("0.0.0.0",
1136 0xffffffff,
1137 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001138 route_34_eos.add_vpp_config()
1139
1140 #
1141 # ping an interface in the default table
1142 # PG0 is in the default table
1143 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001144 tx = self.create_stream_labelled_ip4(self.pg0,
1145 [VppMplsLabel(34)],
1146 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001147 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001148 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001149 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1150
1151 #
1152 # A de-agg route - next-hop lookup in non-default table
1153 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001154 route_35_eos = VppMplsRoute(self, 35, 1,
1155 [VppRoutePath("0.0.0.0",
1156 0xffffffff,
1157 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001158 route_35_eos.add_vpp_config()
1159
1160 #
1161 # ping an interface in the non-default table
1162 # PG0 is in the default table. packet arrive labelled in the
1163 # default table and egress unlabelled in the non-default
1164 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001165 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001166 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1167 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001168 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1169
Neale Ranns6af1c042017-05-26 03:48:53 -07001170 #
1171 # Double pop
1172 #
1173 route_36_neos = VppMplsRoute(self, 36, 0,
1174 [VppRoutePath("0.0.0.0",
1175 0xffffffff)])
1176 route_36_neos.add_vpp_config()
1177
Neale Ranns31ed7442018-02-23 05:29:09 -08001178 tx = self.create_stream_labelled_ip4(self.pg0,
1179 [VppMplsLabel(36),
1180 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001181 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001182 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001183 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1184
1185 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001186 route_35_eos.remove_vpp_config()
1187 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001188
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001189 def test_interface_rx(self):
1190 """ MPLS Interface Receive """
1191
1192 #
1193 # Add a non-recursive route that will forward the traffic
1194 # post-interface-rx
1195 #
1196 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1197 table_id=1,
1198 paths=[VppRoutePath(self.pg1.remote_ip4,
1199 self.pg1.sw_if_index)])
1200 route_10_0_0_1.add_vpp_config()
1201
1202 #
1203 # An interface receive label that maps traffic to RX on interface
1204 # pg1
1205 # by injecting the packet in on pg0, which is in table 0
1206 # doing an interface-rx on pg1 and matching a route in table 1
1207 # if the packet egresses, then we must have swapped to pg1
1208 # so as to have matched the route in table 1
1209 #
Neale Ranns097fa662018-05-01 05:17:55 -07001210 route_34_eos = VppMplsRoute(
1211 self, 34, 1,
1212 [VppRoutePath("0.0.0.0",
1213 self.pg1.sw_if_index,
1214 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001215 route_34_eos.add_vpp_config()
1216
1217 #
1218 # ping an interface in the default table
1219 # PG0 is in the default table
1220 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001221 tx = self.create_stream_labelled_ip4(self.pg0,
1222 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001223 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001224 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001225 self.verify_capture_ip4(self.pg1, rx, tx)
1226
1227 def test_mcast_mid_point(self):
1228 """ MPLS Multicast Mid Point """
1229
1230 #
1231 # Add a non-recursive route that will forward the traffic
1232 # post-interface-rx
1233 #
1234 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1235 table_id=1,
1236 paths=[VppRoutePath(self.pg1.remote_ip4,
1237 self.pg1.sw_if_index)])
1238 route_10_0_0_1.add_vpp_config()
1239
1240 #
1241 # Add a mcast entry that replicate to pg2 and pg3
1242 # and replicate to a interface-rx (like a bud node would)
1243 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001244 route_3400_eos = VppMplsRoute(
1245 self, 3400, 1,
1246 [VppRoutePath(self.pg2.remote_ip4,
1247 self.pg2.sw_if_index,
1248 labels=[VppMplsLabel(3401)]),
1249 VppRoutePath(self.pg3.remote_ip4,
1250 self.pg3.sw_if_index,
1251 labels=[VppMplsLabel(3402)]),
1252 VppRoutePath("0.0.0.0",
1253 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001254 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001255 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001256 route_3400_eos.add_vpp_config()
1257
1258 #
1259 # ping an interface in the default table
1260 # PG0 is in the default table
1261 #
1262 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001263 tx = self.create_stream_labelled_ip4(self.pg0,
1264 [VppMplsLabel(3400, ttl=64)],
1265 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001266 dst_ip="10.0.0.1")
1267 self.pg0.add_stream(tx)
1268
1269 self.pg_enable_capture(self.pg_interfaces)
1270 self.pg_start()
1271
1272 rx = self.pg1.get_capture(257)
1273 self.verify_capture_ip4(self.pg1, rx, tx)
1274
1275 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001276 self.verify_capture_labelled(self.pg2, rx, tx,
1277 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001278 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001279 self.verify_capture_labelled(self.pg3, rx, tx,
1280 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001281
1282 def test_mcast_head(self):
1283 """ MPLS Multicast Head-end """
1284
1285 #
1286 # Create a multicast tunnel with two replications
1287 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001288 mpls_tun = VppMPLSTunnelInterface(
1289 self,
1290 [VppRoutePath(self.pg2.remote_ip4,
1291 self.pg2.sw_if_index,
1292 labels=[VppMplsLabel(42)]),
1293 VppRoutePath(self.pg3.remote_ip4,
1294 self.pg3.sw_if_index,
1295 labels=[VppMplsLabel(43)])],
1296 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001297 mpls_tun.add_vpp_config()
1298 mpls_tun.admin_up()
1299
1300 #
1301 # add an unlabelled route through the new tunnel
1302 #
1303 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1304 [VppRoutePath("0.0.0.0",
1305 mpls_tun._sw_if_index)])
1306 route_10_0_0_3.add_vpp_config()
1307
1308 self.vapi.cli("clear trace")
1309 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1310 self.pg0.add_stream(tx)
1311
1312 self.pg_enable_capture(self.pg_interfaces)
1313 self.pg_start()
1314
1315 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001316 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001317 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001318 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001319
1320 #
1321 # An an IP multicast route via the tunnel
1322 # A (*,G).
1323 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1324 #
1325 route_232_1_1_1 = VppIpMRoute(
1326 self,
1327 "0.0.0.0",
1328 "232.1.1.1", 32,
1329 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1330 [VppMRoutePath(self.pg0.sw_if_index,
1331 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1332 VppMRoutePath(mpls_tun._sw_if_index,
1333 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1334 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001335 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001336
1337 self.vapi.cli("clear trace")
1338 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1339 self.pg0.add_stream(tx)
1340
1341 self.pg_enable_capture(self.pg_interfaces)
1342 self.pg_start()
1343
1344 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001345 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001346 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001347 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001348
Neale Ranns31426c62017-05-24 10:32:58 -07001349 def test_mcast_ip4_tail(self):
1350 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001351
1352 #
1353 # Add a multicast route that will forward the traffic
1354 # post-disposition
1355 #
1356 route_232_1_1_1 = VppIpMRoute(
1357 self,
1358 "0.0.0.0",
1359 "232.1.1.1", 32,
1360 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1361 table_id=1,
1362 paths=[VppMRoutePath(self.pg1.sw_if_index,
1363 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1364 route_232_1_1_1.add_vpp_config()
1365
1366 #
1367 # An interface receive label that maps traffic to RX on interface
1368 # pg1
1369 # by injecting the packet in on pg0, which is in table 0
1370 # doing an rpf-id and matching a route in table 1
1371 # if the packet egresses, then we must have matched the route in
1372 # table 1
1373 #
Neale Ranns097fa662018-05-01 05:17:55 -07001374 route_34_eos = VppMplsRoute(
1375 self, 34, 1,
1376 [VppRoutePath("0.0.0.0",
1377 0xffffffff,
1378 nh_table_id=1,
1379 rpf_id=55)],
1380 is_multicast=1,
1381 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001382
1383 route_34_eos.add_vpp_config()
1384
1385 #
1386 # Drop due to interface lookup miss
1387 #
1388 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001389 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001390 dst_ip="232.1.1.1", n=1)
1391 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1392
1393 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001394 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001395 #
1396 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001397 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001398
Neale Ranns31ed7442018-02-23 05:29:09 -08001399 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1400 dst_ip="232.1.1.1")
1401 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001402 self.verify_capture_ip4(self.pg1, rx, tx)
1403
1404 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001405 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001406 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001407 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001408 dst_ip="232.1.1.1", n=65,
1409 chksum=1)
1410 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1411
1412 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001413 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001414 #
1415 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001416 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001417 dst_ip="232.1.1.1")
1418 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1419
Neale Ranns31426c62017-05-24 10:32:58 -07001420 def test_mcast_ip6_tail(self):
1421 """ MPLS IPv6 Multicast Tail """
1422
1423 #
1424 # Add a multicast route that will forward the traffic
1425 # post-disposition
1426 #
1427 route_ff = VppIpMRoute(
1428 self,
1429 "::",
1430 "ff01::1", 32,
1431 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1432 table_id=1,
1433 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001434 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
1435 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001436 route_ff.add_vpp_config()
1437
1438 #
1439 # An interface receive label that maps traffic to RX on interface
1440 # pg1
1441 # by injecting the packet in on pg0, which is in table 0
1442 # doing an rpf-id and matching a route in table 1
1443 # if the packet egresses, then we must have matched the route in
1444 # table 1
1445 #
1446 route_34_eos = VppMplsRoute(
1447 self, 34, 1,
1448 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001449 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001450 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001451 rpf_id=55)],
1452 is_multicast=1,
1453 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001454
1455 route_34_eos.add_vpp_config()
1456
1457 #
1458 # Drop due to interface lookup miss
1459 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001460 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001461 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001462 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001463
1464 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001465 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001466 #
1467 route_ff.update_rpf_id(55)
1468
Neale Ranns31ed7442018-02-23 05:29:09 -08001469 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001470 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001471 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001472 self.verify_capture_ip6(self.pg1, rx, tx)
1473
1474 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001475 # disposed packets have hop-limit = 1
1476 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001477 tx = self.create_stream_labelled_ip6(self.pg0,
1478 [VppMplsLabel(34)],
1479 dst_ip="ff01::1",
1480 hlim=1)
1481 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001482 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001483
1484 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001485 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001486 #
1487 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001488 tx = self.create_stream_labelled_ip6(self.pg0,
1489 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001490 dst_ip="ff01::1")
1491 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1492
Neale Rannsd5d7b962019-08-04 03:30:56 -07001493 def test_6pe(self):
1494 """ MPLS 6PE """
1495
1496 #
1497 # Add a non-recursive route with a single out label
1498 #
1499 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1500 [VppRoutePath(self.pg0.remote_ip4,
1501 self.pg0.sw_if_index,
1502 labels=[VppMplsLabel(45)])])
1503 route_10_0_0_1.add_vpp_config()
1504
1505 # bind a local label to the route
1506 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1507 binding.add_vpp_config()
1508
1509 #
1510 # a labelled v6 route that resolves through the v4
1511 #
1512 route_2001_3 = VppIpRoute(
1513 self, "2001::3", 128,
1514 [VppRoutePath("10.0.0.1",
1515 INVALID_INDEX,
1516 labels=[VppMplsLabel(32)])])
1517 route_2001_3.add_vpp_config()
1518
1519 tx = self.create_stream_ip6(self.pg0, "2001::3")
1520 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1521
1522 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1523 [VppMplsLabel(45),
1524 VppMplsLabel(32)])
1525
1526 #
1527 # and a v4 recursive via the v6
1528 #
1529 route_20_3 = VppIpRoute(
1530 self, "20.0.0.3", 32,
1531 [VppRoutePath("2001::3",
1532 INVALID_INDEX,
1533 labels=[VppMplsLabel(99)])])
1534 route_20_3.add_vpp_config()
1535
1536 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1537 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1538
1539 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1540 [VppMplsLabel(45),
1541 VppMplsLabel(32),
1542 VppMplsLabel(99)])
1543
Neale Ranns180279b2017-03-16 15:49:09 -04001544
1545class TestMPLSDisabled(VppTestCase):
1546 """ MPLS disabled """
1547
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001548 @classmethod
1549 def setUpClass(cls):
1550 super(TestMPLSDisabled, cls).setUpClass()
1551
1552 @classmethod
1553 def tearDownClass(cls):
1554 super(TestMPLSDisabled, cls).tearDownClass()
1555
Neale Ranns180279b2017-03-16 15:49:09 -04001556 def setUp(self):
1557 super(TestMPLSDisabled, self).setUp()
1558
1559 # create 2 pg interfaces
1560 self.create_pg_interfaces(range(2))
1561
Neale Ranns15002542017-09-10 04:39:11 -07001562 self.tbl = VppMplsTable(self, 0)
1563 self.tbl.add_vpp_config()
1564
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001565 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001566 self.pg0.admin_up()
1567 self.pg0.config_ip4()
1568 self.pg0.resolve_arp()
1569 self.pg0.enable_mpls()
1570
1571 # PG 1 is not MPLS enabled
1572 self.pg1.admin_up()
1573
1574 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001575 for i in self.pg_interfaces:
1576 i.unconfig_ip4()
1577 i.admin_down()
1578
Neale Ranns15002542017-09-10 04:39:11 -07001579 self.pg0.disable_mpls()
1580 super(TestMPLSDisabled, self).tearDown()
1581
Neale Ranns180279b2017-03-16 15:49:09 -04001582 def test_mpls_disabled(self):
1583 """ MPLS Disabled """
1584
1585 tx = (Ether(src=self.pg1.remote_mac,
1586 dst=self.pg1.local_mac) /
1587 MPLS(label=32, ttl=64) /
1588 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1589 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001590 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001591
1592 #
1593 # A simple MPLS xconnect - eos label in label out
1594 #
1595 route_32_eos = VppMplsRoute(self, 32, 1,
1596 [VppRoutePath(self.pg0.remote_ip4,
1597 self.pg0.sw_if_index,
1598 labels=[33])])
1599 route_32_eos.add_vpp_config()
1600
1601 #
1602 # PG1 does not forward IP traffic
1603 #
1604 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1605
1606 #
1607 # MPLS enable PG1
1608 #
1609 self.pg1.enable_mpls()
1610
1611 #
1612 # Now we get packets through
1613 #
1614 self.pg1.add_stream(tx)
1615 self.pg_enable_capture(self.pg_interfaces)
1616 self.pg_start()
1617
1618 rx = self.pg0.get_capture(1)
1619
1620 #
1621 # Disable PG1
1622 #
1623 self.pg1.disable_mpls()
1624
1625 #
1626 # PG1 does not forward IP traffic
1627 #
1628 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1629 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1630
1631
Neale Rannsf12a83f2017-04-18 09:09:40 -07001632class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001633 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001634
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001635 @classmethod
1636 def setUpClass(cls):
1637 super(TestMPLSPIC, cls).setUpClass()
1638
1639 @classmethod
1640 def tearDownClass(cls):
1641 super(TestMPLSPIC, cls).tearDownClass()
1642
Neale Rannsf12a83f2017-04-18 09:09:40 -07001643 def setUp(self):
1644 super(TestMPLSPIC, self).setUp()
1645
1646 # create 2 pg interfaces
1647 self.create_pg_interfaces(range(4))
1648
Neale Ranns15002542017-09-10 04:39:11 -07001649 mpls_tbl = VppMplsTable(self, 0)
1650 mpls_tbl.add_vpp_config()
1651 tbl4 = VppIpTable(self, 1)
1652 tbl4.add_vpp_config()
1653 tbl6 = VppIpTable(self, 1, is_ip6=1)
1654 tbl6.add_vpp_config()
1655
Neale Rannsf12a83f2017-04-18 09:09:40 -07001656 # core links
1657 self.pg0.admin_up()
1658 self.pg0.config_ip4()
1659 self.pg0.resolve_arp()
1660 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001661
Neale Rannsf12a83f2017-04-18 09:09:40 -07001662 self.pg1.admin_up()
1663 self.pg1.config_ip4()
1664 self.pg1.resolve_arp()
1665 self.pg1.enable_mpls()
1666
1667 # VRF (customer facing) link
1668 self.pg2.admin_up()
1669 self.pg2.set_table_ip4(1)
1670 self.pg2.config_ip4()
1671 self.pg2.resolve_arp()
1672 self.pg2.set_table_ip6(1)
1673 self.pg2.config_ip6()
1674 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001675
Neale Rannsf12a83f2017-04-18 09:09:40 -07001676 self.pg3.admin_up()
1677 self.pg3.set_table_ip4(1)
1678 self.pg3.config_ip4()
1679 self.pg3.resolve_arp()
1680 self.pg3.set_table_ip6(1)
1681 self.pg3.config_ip6()
1682 self.pg3.resolve_ndp()
1683
1684 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001685 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001686 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001687 for i in self.pg_interfaces:
1688 i.unconfig_ip4()
1689 i.unconfig_ip6()
1690 i.set_table_ip4(0)
1691 i.set_table_ip6(0)
1692 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001693 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001694
1695 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001696 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001697
1698 1) setup many iBGP VPN routes via a pair of iBGP peers.
1699 2) Check EMCP forwarding to these peers
1700 3) withdraw the IGP route to one of these peers.
1701 4) check forwarding continues to the remaining peer
1702 """
1703
1704 #
1705 # IGP+LDP core routes
1706 #
1707 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1708 [VppRoutePath(self.pg0.remote_ip4,
1709 self.pg0.sw_if_index,
1710 labels=[45])])
1711 core_10_0_0_45.add_vpp_config()
1712
1713 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1714 [VppRoutePath(self.pg1.remote_ip4,
1715 self.pg1.sw_if_index,
1716 labels=[46])])
1717 core_10_0_0_46.add_vpp_config()
1718
1719 #
1720 # Lot's of VPN routes. We need more the 64 so VPP will build
1721 # the fast convergence indirection
1722 #
1723 vpn_routes = []
1724 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001725 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001726 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001727 vpn_routes.append(VppIpRoute(
1728 self, dst, 32,
1729 [VppRoutePath(
1730 "10.0.0.45",
1731 0xffffffff,
1732 labels=[145],
1733 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1734 VppRoutePath(
1735 "10.0.0.46",
1736 0xffffffff,
1737 labels=[146],
1738 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1739 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001740 vpn_routes[ii].add_vpp_config()
1741
1742 pkts.append(Ether(dst=self.pg2.local_mac,
1743 src=self.pg2.remote_mac) /
1744 IP(src=self.pg2.remote_ip4, dst=dst) /
1745 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001746 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001747
1748 #
1749 # Send the packet stream (one pkt to each VPN route)
1750 # - expect a 50-50 split of the traffic
1751 #
1752 self.pg2.add_stream(pkts)
1753 self.pg_enable_capture(self.pg_interfaces)
1754 self.pg_start()
1755
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001756 rx0 = self.pg0._get_capture(NUM_PKTS)
1757 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001758
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001759 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001760 # with the split ratio, just as long as neither is 0
1761 self.assertNotEqual(0, len(rx0))
1762 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001763 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1764 "Expected all (%s) packets across both ECMP paths. "
1765 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001766
1767 #
1768 # use a test CLI command to stop the FIB walk process, this
1769 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001770 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001771 #
1772 self.vapi.ppcli("test fib-walk-process disable")
1773
1774 #
1775 # Withdraw one of the IGP routes
1776 #
1777 core_10_0_0_46.remove_vpp_config()
1778
1779 #
1780 # now all packets should be forwarded through the remaining peer
1781 #
1782 self.vapi.ppcli("clear trace")
1783 self.pg2.add_stream(pkts)
1784 self.pg_enable_capture(self.pg_interfaces)
1785 self.pg_start()
1786
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001787 rx0 = self.pg0.get_capture(NUM_PKTS)
1788 self.assertEqual(len(pkts), len(rx0),
1789 "Expected all (%s) packets across single path. "
1790 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001791
1792 #
1793 # enable the FIB walk process to converge the FIB
1794 #
1795 self.vapi.ppcli("test fib-walk-process enable")
1796
1797 #
1798 # packets should still be forwarded through the remaining peer
1799 #
1800 self.pg2.add_stream(pkts)
1801 self.pg_enable_capture(self.pg_interfaces)
1802 self.pg_start()
1803
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001804 rx0 = self.pg0.get_capture(NUM_PKTS)
1805 self.assertEqual(len(pkts), len(rx0),
1806 "Expected all (%s) packets across single path. "
1807 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001808
1809 #
1810 # Add the IGP route back and we return to load-balancing
1811 #
1812 core_10_0_0_46.add_vpp_config()
1813
1814 self.pg2.add_stream(pkts)
1815 self.pg_enable_capture(self.pg_interfaces)
1816 self.pg_start()
1817
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001818 rx0 = self.pg0._get_capture(NUM_PKTS)
1819 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001820 self.assertNotEqual(0, len(rx0))
1821 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001822 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1823 "Expected all (%s) packets across both ECMP paths. "
1824 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001825
1826 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001827 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001828
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001829 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001830 2) Check EMCP forwarding to these peers
1831 3) withdraw one eBGP path - expect LB across remaining eBGP
1832 """
1833
1834 #
1835 # Lot's of VPN routes. We need more the 64 so VPP will build
1836 # the fast convergence indirection
1837 #
1838 vpn_routes = []
1839 vpn_bindings = []
1840 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001841 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001842 dst = "192.168.1.%d" % ii
1843 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001844 vpn_routes.append(VppIpRoute(
1845 self, dst, 32,
1846 [VppRoutePath(
1847 self.pg2.remote_ip4,
1848 0xffffffff,
1849 nh_table_id=1,
1850 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1851 VppRoutePath(
1852 self.pg3.remote_ip4,
1853 0xffffffff,
1854 nh_table_id=1,
1855 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1856 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001857 vpn_routes[ii].add_vpp_config()
1858
1859 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1860 ip_table_id=1))
1861 vpn_bindings[ii].add_vpp_config()
1862
1863 pkts.append(Ether(dst=self.pg0.local_mac,
1864 src=self.pg0.remote_mac) /
1865 MPLS(label=local_label, ttl=64) /
1866 IP(src=self.pg0.remote_ip4, dst=dst) /
1867 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001868 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001869
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001870 #
1871 # Send the packet stream (one pkt to each VPN route)
1872 # - expect a 50-50 split of the traffic
1873 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001874 self.pg0.add_stream(pkts)
1875 self.pg_enable_capture(self.pg_interfaces)
1876 self.pg_start()
1877
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001878 rx0 = self.pg2._get_capture(NUM_PKTS)
1879 rx1 = self.pg3._get_capture(NUM_PKTS)
1880
1881 # not testing the LB hashing algorithm so we're not concerned
1882 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001883 self.assertNotEqual(0, len(rx0))
1884 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001885 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1886 "Expected all (%s) packets across both ECMP paths. "
1887 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001888
1889 #
1890 # use a test CLI command to stop the FIB walk process, this
1891 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001892 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001893 #
1894 self.vapi.ppcli("test fib-walk-process disable")
1895
1896 #
1897 # withdraw the connected prefix on the interface.
1898 #
1899 self.pg2.unconfig_ip4()
1900
1901 #
1902 # now all packets should be forwarded through the remaining peer
1903 #
1904 self.pg0.add_stream(pkts)
1905 self.pg_enable_capture(self.pg_interfaces)
1906 self.pg_start()
1907
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001908 rx0 = self.pg3.get_capture(NUM_PKTS)
1909 self.assertEqual(len(pkts), len(rx0),
1910 "Expected all (%s) packets across single path. "
1911 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001912
1913 #
1914 # enable the FIB walk process to converge the FIB
1915 #
1916 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001917
1918 #
1919 # packets should still be forwarded through the remaining peer
1920 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001921 self.pg0.add_stream(pkts)
1922 self.pg_enable_capture(self.pg_interfaces)
1923 self.pg_start()
1924
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001925 rx0 = self.pg3.get_capture(NUM_PKTS)
1926 self.assertEqual(len(pkts), len(rx0),
1927 "Expected all (%s) packets across single path. "
1928 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001929
1930 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001931 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001932 #
1933 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001934 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001935
1936 self.pg0.add_stream(pkts)
1937 self.pg_enable_capture(self.pg_interfaces)
1938 self.pg_start()
1939
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001940 rx0 = self.pg2._get_capture(NUM_PKTS)
1941 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001942 self.assertNotEqual(0, len(rx0))
1943 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001944 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1945 "Expected all (%s) packets across both ECMP paths. "
1946 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001947
1948 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001949 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001950
1951 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1952 2) Check EMCP forwarding to these peers
1953 3) withdraw one eBGP path - expect LB across remaining eBGP
1954 """
1955
1956 #
1957 # Lot's of VPN routes. We need more the 64 so VPP will build
1958 # the fast convergence indirection
1959 #
1960 vpn_routes = []
1961 vpn_bindings = []
1962 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001963 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001964 dst = "3000::%d" % ii
1965 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001966 vpn_routes.append(VppIpRoute(
1967 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001968 [VppRoutePath(
1969 self.pg2.remote_ip6,
1970 0xffffffff,
1971 nh_table_id=1,
1972 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1973 VppRoutePath(
1974 self.pg3.remote_ip6,
1975 0xffffffff,
1976 nh_table_id=1,
1977 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1978 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001979 vpn_routes[ii].add_vpp_config()
1980
1981 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001982 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001983 vpn_bindings[ii].add_vpp_config()
1984
1985 pkts.append(Ether(dst=self.pg0.local_mac,
1986 src=self.pg0.remote_mac) /
1987 MPLS(label=local_label, ttl=64) /
1988 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1989 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001990 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07001991 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001992
1993 self.pg0.add_stream(pkts)
1994 self.pg_enable_capture(self.pg_interfaces)
1995 self.pg_start()
1996
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001997 rx0 = self.pg2._get_capture(NUM_PKTS)
1998 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001999 self.assertNotEqual(0, len(rx0))
2000 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002001 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2002 "Expected all (%s) packets across both ECMP paths. "
2003 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002004
2005 #
2006 # use a test CLI command to stop the FIB walk process, this
2007 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002008 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002009 #
2010 self.vapi.ppcli("test fib-walk-process disable")
2011
2012 #
2013 # withdraw the connected prefix on the interface.
2014 # and shutdown the interface so the ND cache is flushed.
2015 #
2016 self.pg2.unconfig_ip6()
2017 self.pg2.admin_down()
2018
2019 #
2020 # now all packets should be forwarded through the remaining peer
2021 #
2022 self.pg0.add_stream(pkts)
2023 self.pg_enable_capture(self.pg_interfaces)
2024 self.pg_start()
2025
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002026 rx0 = self.pg3.get_capture(NUM_PKTS)
2027 self.assertEqual(len(pkts), len(rx0),
2028 "Expected all (%s) packets across single path. "
2029 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002030
2031 #
2032 # enable the FIB walk process to converge the FIB
2033 #
2034 self.vapi.ppcli("test fib-walk-process enable")
2035 self.pg0.add_stream(pkts)
2036 self.pg_enable_capture(self.pg_interfaces)
2037 self.pg_start()
2038
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002039 rx0 = self.pg3.get_capture(NUM_PKTS)
2040 self.assertEqual(len(pkts), len(rx0),
2041 "Expected all (%s) packets across single path. "
2042 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002043
2044 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002045 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002046 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002047 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002048 self.pg2.admin_up()
2049 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002050 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002051
2052 self.pg0.add_stream(pkts)
2053 self.pg_enable_capture(self.pg_interfaces)
2054 self.pg_start()
2055
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002056 rx0 = self.pg2._get_capture(NUM_PKTS)
2057 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002058 self.assertNotEqual(0, len(rx0))
2059 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002060 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2061 "Expected all (%s) packets across both ECMP paths. "
2062 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002063
2064
Neale Rannsda78f952017-05-24 09:15:43 -07002065class TestMPLSL2(VppTestCase):
2066 """ MPLS-L2 """
2067
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002068 @classmethod
2069 def setUpClass(cls):
2070 super(TestMPLSL2, cls).setUpClass()
2071
2072 @classmethod
2073 def tearDownClass(cls):
2074 super(TestMPLSL2, cls).tearDownClass()
2075
Neale Rannsda78f952017-05-24 09:15:43 -07002076 def setUp(self):
2077 super(TestMPLSL2, self).setUp()
2078
2079 # create 2 pg interfaces
2080 self.create_pg_interfaces(range(2))
2081
Neale Ranns15002542017-09-10 04:39:11 -07002082 # create the default MPLS table
2083 self.tables = []
2084 tbl = VppMplsTable(self, 0)
2085 tbl.add_vpp_config()
2086 self.tables.append(tbl)
2087
Neale Ranns1976f362019-11-06 13:13:01 +00002088 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002089 self.pg0.admin_up()
2090 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002091 self.pg0.enable_mpls()
2092
Neale Ranns15002542017-09-10 04:39:11 -07002093 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002094 for i in self.pg_interfaces[1:]:
2095 i.admin_up()
2096
2097 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002098 for i in self.pg_interfaces[1:]:
2099 i.admin_down()
2100
2101 self.pg0.disable_mpls()
2102 self.pg0.unconfig_ip4()
2103 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002104 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002105
Neale Ranns31ed7442018-02-23 05:29:09 -08002106 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002107 capture = verify_filter(capture, sent)
2108
2109 self.assertEqual(len(capture), len(sent))
2110
2111 for i in range(len(capture)):
2112 tx = sent[i]
2113 rx = capture[i]
2114
2115 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002116 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002117
2118 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002119 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002120
2121 self.assertEqual(rx_eth.src, tx_eth.src)
2122 self.assertEqual(rx_eth.dst, tx_eth.dst)
2123
Neale Ranns1976f362019-11-06 13:13:01 +00002124 def verify_arp_req(self, rx, smac, sip, dip):
2125 ether = rx[Ether]
2126 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2127 self.assertEqual(ether.src, smac)
2128
2129 arp = rx[ARP]
2130 self.assertEqual(arp.hwtype, 1)
2131 self.assertEqual(arp.ptype, 0x800)
2132 self.assertEqual(arp.hwlen, 6)
2133 self.assertEqual(arp.plen, 4)
2134 self.assertEqual(arp.op, ARP.who_has)
2135 self.assertEqual(arp.hwsrc, smac)
2136 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2137 self.assertEqual(arp.psrc, sip)
2138 self.assertEqual(arp.pdst, dip)
2139
Neale Rannsda78f952017-05-24 09:15:43 -07002140 def test_vpws(self):
2141 """ Virtual Private Wire Service """
2142
2143 #
2144 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002145 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2146 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002147 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002148 mpls_tun_1 = VppMPLSTunnelInterface(
2149 self,
2150 [VppRoutePath(self.pg0.remote_ip4,
2151 self.pg0.sw_if_index,
2152 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2153 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002154 mpls_tun_1.add_vpp_config()
2155 mpls_tun_1.admin_up()
2156
2157 #
2158 # Create a label entry to for 55 that does L2 input to the tunnel
2159 #
2160 route_55_eos = VppMplsRoute(
2161 self, 55, 1,
2162 [VppRoutePath("0.0.0.0",
2163 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002164 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2165 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2166 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002167 route_55_eos.add_vpp_config()
2168
2169 #
2170 # Cross-connect the tunnel with one of the customers L2 interfaces
2171 #
2172 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2173 mpls_tun_1.sw_if_index,
2174 enable=1)
2175 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2176 self.pg1.sw_if_index,
2177 enable=1)
2178
2179 #
2180 # inject a packet from the core
2181 #
2182 pcore = (Ether(dst=self.pg0.local_mac,
2183 src=self.pg0.remote_mac) /
2184 MPLS(label=55, ttl=64) /
2185 Ether(dst="00:00:de:ad:ba:be",
2186 src="00:00:de:ad:be:ef") /
2187 IP(src="10.10.10.10", dst="11.11.11.11") /
2188 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002189 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002190
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002191 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002192 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2193 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002194
Neale Ranns31ed7442018-02-23 05:29:09 -08002195 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2196 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002197
2198 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002199 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002200 # there's no resolved ARP entry so the first packet we see should be
2201 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002202 #
Neale Ranns1976f362019-11-06 13:13:01 +00002203 tx1 = pcore[MPLS].payload
2204 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2205
2206 self.verify_arp_req(rx1[0],
2207 self.pg0.local_mac,
2208 self.pg0.local_ip4,
2209 self.pg0.remote_ip4)
2210
2211 #
2212 # resolve the ARP entries and send again
2213 #
2214 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002215 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002216 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002217
Neale Ranns31ed7442018-02-23 05:29:09 -08002218 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002219
2220 def test_vpls(self):
2221 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002222
2223 # we skipped this in the setup
2224 self.pg0.resolve_arp()
2225
Neale Rannsda78f952017-05-24 09:15:43 -07002226 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002227 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002228 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002229 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002230 self,
2231 [VppRoutePath(self.pg0.remote_ip4,
2232 self.pg0.sw_if_index,
2233 labels=[VppMplsLabel(42)])],
2234 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002235 mpls_tun1.add_vpp_config()
2236 mpls_tun1.admin_up()
2237
2238 mpls_tun2 = VppMPLSTunnelInterface(
2239 self,
2240 [VppRoutePath(self.pg0.remote_ip4,
2241 self.pg0.sw_if_index,
2242 labels=[VppMplsLabel(43)])],
2243 is_l2=1)
2244 mpls_tun2.add_vpp_config()
2245 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002246
2247 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002248 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2249 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002250 #
2251 route_55_eos = VppMplsRoute(
2252 self, 55, 1,
2253 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002254 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002255 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2256 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2257 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002258
2259 route_56_eos = VppMplsRoute(
2260 self, 56, 1,
2261 [VppRoutePath("0.0.0.0",
2262 mpls_tun2.sw_if_index,
2263 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2264 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2265 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2266 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2267
2268 # move me
2269 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002270 route_55_eos.add_vpp_config()
2271
Neale Ranns1dbcf302019-07-19 11:44:53 +00002272 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2273
Neale Rannsda78f952017-05-24 09:15:43 -07002274 #
2275 # add to tunnel to the customers bridge-domain
2276 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002277 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002278 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2279 self.vapi.sw_interface_set_l2_bridge(
2280 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002281 self.vapi.sw_interface_set_l2_bridge(
2282 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002283
2284 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002285 # Packet from host on the customer interface to each host
2286 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002287 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002288 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2289 src="00:00:de:ad:be:ef") /
2290 IP(src="10.10.10.10", dst="11.11.11.11") /
2291 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002292 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002293 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2294 src="00:00:de:ad:be:ef") /
2295 IP(src="10.10.10.10", dst="11.11.11.12") /
2296 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002297 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002298 p_core1 = (Ether(dst=self.pg0.local_mac,
2299 src=self.pg0.remote_mac) /
2300 MPLS(label=55, ttl=64) /
2301 Ether(src="00:00:de:ad:ba:b1",
2302 dst="00:00:de:ad:be:ef") /
2303 IP(dst="10.10.10.10", src="11.11.11.11") /
2304 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002305 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002306 p_core2 = (Ether(dst=self.pg0.local_mac,
2307 src=self.pg0.remote_mac) /
2308 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002309 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002310 Ether(src="00:00:de:ad:ba:b2",
2311 dst="00:00:de:ad:be:ef") /
2312 IP(dst="10.10.10.10", src="11.11.11.12") /
2313 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002314 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002315
2316 #
2317 # The BD is learning, so send in one of each packet to learn
2318 #
Neale Rannsda78f952017-05-24 09:15:43 -07002319
Neale Ranns1dbcf302019-07-19 11:44:53 +00002320 # 2 packets due to BD flooding
2321 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2322 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002323
Neale Ranns1dbcf302019-07-19 11:44:53 +00002324 # we've learnt this so expect it be be forwarded not flooded
2325 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2326 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2327 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002328
Neale Ranns1dbcf302019-07-19 11:44:53 +00002329 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2330 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2331 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002332
2333 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002334 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002335 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002336 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2337 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002338 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002339
Neale Ranns1dbcf302019-07-19 11:44:53 +00002340 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2341 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2342 [VppMplsLabel(43)])
2343
2344 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2345 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2346
Neale Rannsda78f952017-05-24 09:15:43 -07002347 #
2348 # remove interfaces from customers bridge-domain
2349 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002350 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002351 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2352 self.vapi.sw_interface_set_l2_bridge(
2353 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002354 self.vapi.sw_interface_set_l2_bridge(
2355 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002356
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002357
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002358if __name__ == '__main__':
2359 unittest.main(testRunner=VppTestRunner)