blob: 0f3c617fcc7aa51301f801c239f5bcf6db62da1d [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 Ranns990f6942020-10-20 07:20:17 +000010 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 Ranns990f6942020-10-20 07:20:17 +000014from vpp_papi import VppEnum
Neale Ranns8fe8cc22016-11-01 10:05:08 +000015
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070016import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000017from scapy.packet import Raw
Neale Ranns1976f362019-11-06 13:13:01 +000018from scapy.layers.l2 import Ether, ARP
Neale Rannscb630ff2016-12-14 13:31:29 +010019from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070020from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000021from scapy.contrib.mpls import MPLS
22
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040023NUM_PKTS = 67
24
Neale Ranns1976f362019-11-06 13:13:01 +000025# scapy removed these attributes.
26# we asked that they be restored: https://github.com/secdev/scapy/pull/1878
27# semantic names have more meaning than numbers. so here they are.
28ARP.who_has = 1
29ARP.is_at = 2
30
Klement Sekeradab231a2016-12-21 08:50:14 +010031
Neale Rannsda78f952017-05-24 09:15:43 -070032def verify_filter(capture, sent):
33 if not len(capture) == len(sent):
34 # filter out any IPv6 RAs from the capture
35 for p in capture:
36 if p.haslayer(IPv6):
37 capture.remove(p)
38 return capture
39
40
Neale Ranns31ed7442018-02-23 05:29:09 -080041def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070042 # the rx'd packet has the MPLS label popped
43 eth = rx[Ether]
44 tst.assertEqual(eth.type, 0x8847)
45
46 rx_mpls = rx[MPLS]
47
48 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080049 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
50 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
51 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
52
Neale Rannsda78f952017-05-24 09:15:43 -070053 if ii == len(mpls_labels) - 1:
54 tst.assertEqual(rx_mpls.s, 1)
55 else:
56 # not end of stack
57 tst.assertEqual(rx_mpls.s, 0)
58 # pop the label to expose the next
59 rx_mpls = rx_mpls[MPLS].payload
60
61
Neale Ranns8fe8cc22016-11-01 10:05:08 +000062class TestMPLS(VppTestCase):
63 """ MPLS Test Case """
64
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070065 @classmethod
66 def setUpClass(cls):
67 super(TestMPLS, cls).setUpClass()
68
69 @classmethod
70 def tearDownClass(cls):
71 super(TestMPLS, cls).tearDownClass()
72
Neale Ranns8fe8cc22016-11-01 10:05:08 +000073 def setUp(self):
74 super(TestMPLS, self).setUp()
75
76 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080077 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000078
79 # setup both interfaces
80 # assign them different tables.
81 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070082 self.tables = []
83
84 tbl = VppMplsTable(self, 0)
85 tbl.add_vpp_config()
86 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000087
88 for i in self.pg_interfaces:
89 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070090
91 if table_id != 0:
92 tbl = VppIpTable(self, table_id)
93 tbl.add_vpp_config()
94 self.tables.append(tbl)
95 tbl = VppIpTable(self, table_id, is_ip6=1)
96 tbl.add_vpp_config()
97 self.tables.append(tbl)
98
Neale Ranns8fe8cc22016-11-01 10:05:08 +000099 i.set_table_ip4(table_id)
100 i.set_table_ip6(table_id)
101 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000102 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000103 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000104 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +0000105 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000106 table_id += 1
107
108 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800109 for i in self.pg_interfaces:
110 i.unconfig_ip4()
111 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -0700112 i.set_table_ip4(0)
113 i.set_table_ip6(0)
114 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800115 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700116 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000117
Neale Rannsad422ed2016-11-02 14:20:04 +0000118 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100119 def create_stream_labelled_ip4(
120 self,
121 src_if,
122 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100123 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800124 ip_itf=None,
125 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700126 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800127 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800128 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100129 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000130 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800131 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100132 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000133 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000134 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
135
136 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800137 p = p / MPLS(label=mpls_labels[ii].value,
138 ttl=mpls_labels[ii].ttl,
139 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100140 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800141 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800142 p = (p / IP(src=src_if.local_ip4,
143 dst=src_if.remote_ip4,
144 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800145 UDP(sport=1234, dport=1234) /
146 Raw(payload))
147 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800148 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800149 UDP(sport=1234, dport=1234) /
150 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100151 else:
152 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800153 dst=ip_itf.local_ip4,
154 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100155 ICMP())
156
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700157 if chksum:
158 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000159 info.data = p.copy()
160 pkts.append(p)
161 return pkts
162
Ole Troaneb284a12019-10-09 13:33:19 +0200163 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64,
164 ip_dscp=0, payload_size=None):
Klement Sekeradab231a2016-12-21 08:50:14 +0100165 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000166 pkts = []
167 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100168 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000169 payload = self.info_to_payload(info)
170 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800171 IP(src=src_if.remote_ip4, dst=dst_ip,
172 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000173 UDP(sport=1234, dport=1234) /
174 Raw(payload))
175 info.data = p.copy()
Ole Troaneb284a12019-10-09 13:33:19 +0200176 if payload_size:
177 self.extend_packet(p, payload_size)
Neale Rannsad422ed2016-11-02 14:20:04 +0000178 pkts.append(p)
179 return pkts
180
Neale Ranns31ed7442018-02-23 05:29:09 -0800181 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
182 self.reset_packet_infos()
183 pkts = []
184 for i in range(0, 257):
185 info = self.create_packet_info(src_if, src_if)
186 payload = self.info_to_payload(info)
187 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
188 IPv6(src=src_if.remote_ip6, dst=dst_ip,
189 hlim=ip_ttl, tc=ip_dscp) /
190 UDP(sport=1234, dport=1234) /
191 Raw(payload))
192 info.data = p.copy()
193 pkts.append(p)
194 return pkts
195
196 def create_stream_labelled_ip6(self, src_if, mpls_labels,
197 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700198 if dst_ip is None:
199 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100200 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000201 pkts = []
202 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100203 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000204 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800205 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
206 for l in mpls_labels:
207 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
208
209 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
210 UDP(sport=1234, dport=1234) /
211 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000212 info.data = p.copy()
213 pkts.append(p)
214 return pkts
215
Neale Ranns31ed7442018-02-23 05:29:09 -0800216 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
217 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000218 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700219 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000220
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000221 self.assertEqual(len(capture), len(sent))
222
223 for i in range(len(capture)):
224 tx = sent[i]
225 rx = capture[i]
226
227 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000228 eth = rx[Ether]
229 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000230
231 tx_ip = tx[IP]
232 rx_ip = rx[IP]
233
Neale Rannscb630ff2016-12-14 13:31:29 +0100234 if not ping_resp:
235 self.assertEqual(rx_ip.src, tx_ip.src)
236 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800237 self.assertEqual(rx_ip.tos, ip_dscp)
238 if not ip_ttl:
239 # IP processing post pop has decremented the TTL
240 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
241 else:
242 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100243 else:
244 self.assertEqual(rx_ip.src, tx_ip.dst)
245 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000246
247 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000248 raise
249
Neale Rannsad422ed2016-11-02 14:20:04 +0000250 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800251 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000252 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700253 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000254
255 self.assertEqual(len(capture), len(sent))
256
257 for i in range(len(capture)):
258 tx = sent[i]
259 rx = capture[i]
260 tx_ip = tx[IP]
261 rx_ip = rx[IP]
262
Neale Ranns31ed7442018-02-23 05:29:09 -0800263 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000264
265 self.assertEqual(rx_ip.src, tx_ip.src)
266 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800267 if not ip_ttl:
268 # IP processing post pop has decremented the TTL
269 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
270 else:
271 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000272
273 except:
274 raise
275
Neale Ranns31ed7442018-02-23 05:29:09 -0800276 def verify_capture_labelled_ip6(self, src_if, capture, sent,
277 mpls_labels, ip_ttl=None):
278 try:
279 capture = verify_filter(capture, sent)
280
281 self.assertEqual(len(capture), len(sent))
282
283 for i in range(len(capture)):
284 tx = sent[i]
285 rx = capture[i]
286 tx_ip = tx[IPv6]
287 rx_ip = rx[IPv6]
288
289 verify_mpls_stack(self, rx, mpls_labels)
290
291 self.assertEqual(rx_ip.src, tx_ip.src)
292 self.assertEqual(rx_ip.dst, tx_ip.dst)
293 if not ip_ttl:
294 # IP processing post pop has decremented the TTL
295 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
296 else:
297 self.assertEqual(rx_ip.hlim, ip_ttl)
298
299 except:
300 raise
301
302 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000303 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700304 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000305
306 self.assertEqual(len(capture), len(sent))
307
308 for i in range(len(capture)):
309 tx = sent[i]
310 rx = capture[i]
311 tx_ip = tx[IP]
312 rx_ip = rx[IP]
313
Neale Ranns31ed7442018-02-23 05:29:09 -0800314 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000315
316 self.assertEqual(rx_ip.src, tx_ip.src)
317 self.assertEqual(rx_ip.dst, tx_ip.dst)
318 # IP processing post pop has decremented the TTL
319 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
320
321 except:
322 raise
323
324 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800325 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000326 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700327 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000328
329 self.assertEqual(len(capture), len(sent))
330
331 for i in range(len(capture)):
332 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800333 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000334 except:
335 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000336
Neale Ranns31ed7442018-02-23 05:29:09 -0800337 def verify_capture_ip6(self, src_if, capture, sent,
338 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000339 try:
340 self.assertEqual(len(capture), len(sent))
341
342 for i in range(len(capture)):
343 tx = sent[i]
344 rx = capture[i]
345
346 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000347 eth = rx[Ether]
348 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000349
350 tx_ip = tx[IPv6]
351 rx_ip = rx[IPv6]
352
353 self.assertEqual(rx_ip.src, tx_ip.src)
354 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800355 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000356 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800357 if not ip_hlim:
358 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
359 else:
360 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000361
362 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000363 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000364
Neale Ranns62fe07c2017-10-31 12:28:22 -0700365 def verify_capture_ip6_icmp(self, src_if, capture, sent):
366 try:
367 self.assertEqual(len(capture), len(sent))
368
369 for i in range(len(capture)):
370 tx = sent[i]
371 rx = capture[i]
372
373 # the rx'd packet has the MPLS label popped
374 eth = rx[Ether]
375 self.assertEqual(eth.type, 0x86DD)
376
377 tx_ip = tx[IPv6]
378 rx_ip = rx[IPv6]
379
380 self.assertEqual(rx_ip.dst, tx_ip.src)
381 # ICMP sourced from the interface's address
382 self.assertEqual(rx_ip.src, src_if.local_ip6)
383 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200384 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700385
386 icmp = rx[ICMPv6TimeExceeded]
387
388 except:
389 raise
390
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530391 def verify_capture_fragmented_labelled_ip4(self, src_if, capture, sent,
392 mpls_labels, ip_ttl=None):
393 try:
394 capture = verify_filter(capture, sent)
395
396 for i in range(len(capture)):
397 tx = sent[0]
398 rx = capture[i]
399 tx_ip = tx[IP]
400 rx_ip = rx[IP]
401
402 verify_mpls_stack(self, rx, mpls_labels)
403
404 self.assertEqual(rx_ip.src, tx_ip.src)
405 self.assertEqual(rx_ip.dst, tx_ip.dst)
406 if not ip_ttl:
407 # IP processing post pop has decremented the TTL
408 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
409 else:
410 self.assertEqual(rx_ip.ttl, ip_ttl)
411
412 except:
413 raise
414
Neale Rannsad422ed2016-11-02 14:20:04 +0000415 def test_swap(self):
416 """ MPLS label swap tests """
417
418 #
419 # A simple MPLS xconnect - eos label in label out
420 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800421 route_32_eos = VppMplsRoute(self, 32, 1,
422 [VppRoutePath(self.pg0.remote_ip4,
423 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800424 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000425 route_32_eos.add_vpp_config()
426
Neale Ranns775f73c2018-12-20 03:01:49 -0800427 self.assertTrue(
428 find_mpls_route(self, 0, 32, 1,
429 [VppRoutePath(self.pg0.remote_ip4,
430 self.pg0.sw_if_index,
431 labels=[VppMplsLabel(33)])]))
432
Neale Rannsad422ed2016-11-02 14:20:04 +0000433 #
434 # a stream that matches the route for 10.0.0.1
435 # PG0 is in the default table
436 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800437 tx = self.create_stream_labelled_ip4(self.pg0,
438 [VppMplsLabel(32, ttl=32, exp=1)])
439 rx = self.send_and_expect(self.pg0, tx, self.pg0)
440 self.verify_capture_labelled(self.pg0, rx, tx,
441 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000442
Neale Ranns008dbe12018-09-07 09:32:36 -0700443 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
444
Neale Rannsad422ed2016-11-02 14:20:04 +0000445 #
446 # A simple MPLS xconnect - non-eos label in label out
447 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800448 route_32_neos = VppMplsRoute(self, 32, 0,
449 [VppRoutePath(self.pg0.remote_ip4,
450 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800451 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000452 route_32_neos.add_vpp_config()
453
454 #
455 # a stream that matches the route for 10.0.0.1
456 # PG0 is in the default table
457 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800458 tx = self.create_stream_labelled_ip4(self.pg0,
459 [VppMplsLabel(32, ttl=21, exp=7),
460 VppMplsLabel(99)])
461 rx = self.send_and_expect(self.pg0, tx, self.pg0)
462 self.verify_capture_labelled(self.pg0, rx, tx,
463 [VppMplsLabel(33, ttl=20, exp=7),
464 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700465 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000466
Neale Ranns31ed7442018-02-23 05:29:09 -0800467 #
468 # A simple MPLS xconnect - non-eos label in label out, uniform mode
469 #
470 route_42_neos = VppMplsRoute(
471 self, 42, 0,
472 [VppRoutePath(self.pg0.remote_ip4,
473 self.pg0.sw_if_index,
474 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
475 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000476
Neale Ranns31ed7442018-02-23 05:29:09 -0800477 tx = self.create_stream_labelled_ip4(self.pg0,
478 [VppMplsLabel(42, ttl=21, exp=7),
479 VppMplsLabel(99)])
480 rx = self.send_and_expect(self.pg0, tx, self.pg0)
481 self.verify_capture_labelled(self.pg0, rx, tx,
482 [VppMplsLabel(43, ttl=20, exp=7),
483 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000484
485 #
486 # An MPLS xconnect - EOS label in IP out
487 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800488 route_33_eos = VppMplsRoute(self, 33, 1,
489 [VppRoutePath(self.pg0.remote_ip4,
490 self.pg0.sw_if_index,
491 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000492 route_33_eos.add_vpp_config()
493
Neale Ranns31ed7442018-02-23 05:29:09 -0800494 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
495 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000496 self.verify_capture_ip4(self.pg0, rx, tx)
497
498 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700499 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700500 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800501 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700502 dst_ip=self.pg0.remote_ip4,
503 n=65,
504 chksum=1)
505 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
506
507 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800508 # An MPLS xconnect - EOS label in IP out, uniform mode
509 #
510 route_3333_eos = VppMplsRoute(
511 self, 3333, 1,
512 [VppRoutePath(self.pg0.remote_ip4,
513 self.pg0.sw_if_index,
514 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
515 route_3333_eos.add_vpp_config()
516
517 tx = self.create_stream_labelled_ip4(
518 self.pg0,
519 [VppMplsLabel(3333, ttl=55, exp=3)])
520 rx = self.send_and_expect(self.pg0, tx, self.pg0)
521 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
522 tx = self.create_stream_labelled_ip4(
523 self.pg0,
524 [VppMplsLabel(3333, ttl=66, exp=4)])
525 rx = self.send_and_expect(self.pg0, tx, self.pg0)
526 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
527
528 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700529 # An MPLS xconnect - EOS label in IPv6 out
530 #
531 route_333_eos = VppMplsRoute(
532 self, 333, 1,
533 [VppRoutePath(self.pg0.remote_ip6,
534 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700535 labels=[])],
536 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700537 route_333_eos.add_vpp_config()
538
Neale Ranns31ed7442018-02-23 05:29:09 -0800539 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
540 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700541 self.verify_capture_ip6(self.pg0, rx, tx)
542
543 #
544 # disposed packets have an TTL expired
545 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800546 tx = self.create_stream_labelled_ip6(self.pg0,
547 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700548 dst_ip=self.pg1.remote_ip6,
549 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800550 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700551 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
552
553 #
554 # An MPLS xconnect - EOS label in IPv6 out w imp-null
555 #
556 route_334_eos = VppMplsRoute(
557 self, 334, 1,
558 [VppRoutePath(self.pg0.remote_ip6,
559 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700560 labels=[VppMplsLabel(3)])],
561 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700562 route_334_eos.add_vpp_config()
563
Neale Ranns31ed7442018-02-23 05:29:09 -0800564 tx = self.create_stream_labelled_ip6(self.pg0,
565 [VppMplsLabel(334, ttl=64)])
566 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700567 self.verify_capture_ip6(self.pg0, rx, tx)
568
569 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800570 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
571 #
572 route_335_eos = VppMplsRoute(
573 self, 335, 1,
574 [VppRoutePath(self.pg0.remote_ip6,
575 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700576 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
577 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800578 route_335_eos.add_vpp_config()
579
580 tx = self.create_stream_labelled_ip6(
581 self.pg0,
582 [VppMplsLabel(335, ttl=27, exp=4)])
583 rx = self.send_and_expect(self.pg0, tx, self.pg0)
584 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
585
586 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700587 # disposed packets have an TTL expired
588 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800589 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700590 dst_ip=self.pg1.remote_ip6,
591 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800592 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700593 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
594
595 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000596 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
597 # so this traffic should be dropped.
598 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800599 route_33_neos = VppMplsRoute(self, 33, 0,
600 [VppRoutePath(self.pg0.remote_ip4,
601 self.pg0.sw_if_index,
602 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000603 route_33_neos.add_vpp_config()
604
Neale Ranns31ed7442018-02-23 05:29:09 -0800605 tx = self.create_stream_labelled_ip4(self.pg0,
606 [VppMplsLabel(33),
607 VppMplsLabel(99)])
608 self.send_and_assert_no_replies(
609 self.pg0, tx,
610 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000611
612 #
613 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800614 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000615 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800616 route_34_eos = VppMplsRoute(self, 34, 1,
617 [VppRoutePath("0.0.0.0",
618 0xffffffff,
619 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800620 labels=[VppMplsLabel(44),
621 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000622 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700623 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000624
Neale Ranns31ed7442018-02-23 05:29:09 -0800625 tx = self.create_stream_labelled_ip4(self.pg0,
626 [VppMplsLabel(34, ttl=3)])
627 rx = self.send_and_expect(self.pg0, tx, self.pg0)
628 self.verify_capture_labelled(self.pg0, rx, tx,
629 [VppMplsLabel(33),
630 VppMplsLabel(44),
631 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000632
Neale Ranns008dbe12018-09-07 09:32:36 -0700633 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
634 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
635
Neale Ranns31ed7442018-02-23 05:29:09 -0800636 #
637 # A recursive EOS x-connect, which resolves through another x-connect
638 # in uniform mode
639 #
640 route_35_eos = VppMplsRoute(
641 self, 35, 1,
642 [VppRoutePath("0.0.0.0",
643 0xffffffff,
644 nh_via_label=42,
645 labels=[VppMplsLabel(44)])])
646 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000647
Neale Ranns31ed7442018-02-23 05:29:09 -0800648 tx = self.create_stream_labelled_ip4(self.pg0,
649 [VppMplsLabel(35, ttl=3)])
650 rx = self.send_and_expect(self.pg0, tx, self.pg0)
651 self.verify_capture_labelled(self.pg0, rx, tx,
652 [VppMplsLabel(43, ttl=2),
653 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000654
655 #
Matej Klottondeb69842016-12-09 15:05:46 +0100656 # A recursive non-EOS x-connect, which resolves through another
657 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000658 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800659 route_34_neos = VppMplsRoute(self, 34, 0,
660 [VppRoutePath("0.0.0.0",
661 0xffffffff,
662 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800663 labels=[VppMplsLabel(44),
664 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000665 route_34_neos.add_vpp_config()
666
Neale Ranns31ed7442018-02-23 05:29:09 -0800667 tx = self.create_stream_labelled_ip4(self.pg0,
668 [VppMplsLabel(34, ttl=45),
669 VppMplsLabel(99)])
670 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100671 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800672 self.verify_capture_labelled(self.pg0, rx, tx,
673 [VppMplsLabel(33),
674 VppMplsLabel(44),
675 VppMplsLabel(46, ttl=44),
676 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000677
678 #
Matej Klottondeb69842016-12-09 15:05:46 +0100679 # an recursive IP route that resolves through the recursive non-eos
680 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000681 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800682 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
683 [VppRoutePath("0.0.0.0",
684 0xffffffff,
685 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800686 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000687 ip_10_0_0_1.add_vpp_config()
688
Neale Rannsad422ed2016-11-02 14:20:04 +0000689 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800690 rx = self.send_and_expect(self.pg0, tx, self.pg0)
691 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
692 [VppMplsLabel(33),
693 VppMplsLabel(44),
694 VppMplsLabel(46),
695 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700696 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000697
698 ip_10_0_0_1.remove_vpp_config()
699 route_34_neos.remove_vpp_config()
700 route_34_eos.remove_vpp_config()
701 route_33_neos.remove_vpp_config()
702 route_33_eos.remove_vpp_config()
703 route_32_neos.remove_vpp_config()
704 route_32_eos.remove_vpp_config()
705
706 def test_bind(self):
707 """ MPLS Local Label Binding test """
708
709 #
710 # Add a non-recursive route with a single out label
711 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800712 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
713 [VppRoutePath(self.pg0.remote_ip4,
714 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800715 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000716 route_10_0_0_1.add_vpp_config()
717
718 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800719 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000720 binding.add_vpp_config()
721
722 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800723 tx = self.create_stream_labelled_ip4(self.pg0,
724 [VppMplsLabel(44),
725 VppMplsLabel(99)])
726 rx = self.send_and_expect(self.pg0, tx, self.pg0)
727 self.verify_capture_labelled(self.pg0, rx, tx,
728 [VppMplsLabel(45, ttl=63),
729 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000730
731 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800732 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
733 rx = self.send_and_expect(self.pg0, tx, self.pg0)
734 self.verify_capture_labelled(self.pg0, rx, tx,
735 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000736
737 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000738 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800739 rx = self.send_and_expect(self.pg0, tx, self.pg0)
740 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000741
742 #
743 # cleanup
744 #
745 binding.remove_vpp_config()
746 route_10_0_0_1.remove_vpp_config()
747
748 def test_imposition(self):
749 """ MPLS label imposition test """
750
751 #
752 # Add a non-recursive route with a single out label
753 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800754 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
755 [VppRoutePath(self.pg0.remote_ip4,
756 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800757 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000758 route_10_0_0_1.add_vpp_config()
759
760 #
761 # a stream that matches the route for 10.0.0.1
762 # PG0 is in the default table
763 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000764 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800765 rx = self.send_and_expect(self.pg0, tx, self.pg0)
766 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000767
768 #
769 # Add a non-recursive route with a 3 out labels
770 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800771 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
772 [VppRoutePath(self.pg0.remote_ip4,
773 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800774 labels=[VppMplsLabel(32),
775 VppMplsLabel(33),
776 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000777 route_10_0_0_2.add_vpp_config()
778
Neale Ranns31ed7442018-02-23 05:29:09 -0800779 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
780 ip_ttl=44, ip_dscp=0xff)
781 rx = self.send_and_expect(self.pg0, tx, self.pg0)
782 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
783 [VppMplsLabel(32),
784 VppMplsLabel(33),
785 VppMplsLabel(34)],
786 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000787
Neale Ranns31ed7442018-02-23 05:29:09 -0800788 #
789 # Add a non-recursive route with a single out label in uniform mode
790 #
791 route_10_0_0_3 = VppIpRoute(
792 self, "10.0.0.3", 32,
793 [VppRoutePath(self.pg0.remote_ip4,
794 self.pg0.sw_if_index,
795 labels=[VppMplsLabel(32,
796 mode=MplsLspMode.UNIFORM)])])
797 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000798
Neale Ranns31ed7442018-02-23 05:29:09 -0800799 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
800 ip_ttl=54, ip_dscp=0xbe)
801 rx = self.send_and_expect(self.pg0, tx, self.pg0)
802 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
803 [VppMplsLabel(32, ttl=53, exp=5)])
804
805 #
806 # Add a IPv6 non-recursive route with a single out label in
807 # uniform mode
808 #
809 route_2001_3 = VppIpRoute(
810 self, "2001::3", 128,
811 [VppRoutePath(self.pg0.remote_ip6,
812 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800813 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700814 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800815 route_2001_3.add_vpp_config()
816
817 tx = self.create_stream_ip6(self.pg0, "2001::3",
818 ip_ttl=54, ip_dscp=0xbe)
819 rx = self.send_and_expect(self.pg0, tx, self.pg0)
820 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
821 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000822
823 #
Matej Klottondeb69842016-12-09 15:05:46 +0100824 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000825 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800826 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
827 [VppRoutePath("10.0.0.1",
828 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800829 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000830 route_11_0_0_1.add_vpp_config()
831
832 #
833 # a stream that matches the route for 11.0.0.1, should pick up
834 # the label stack for 11.0.0.1 and 10.0.0.1
835 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000836 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800837 rx = self.send_and_expect(self.pg0, tx, self.pg0)
838 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
839 [VppMplsLabel(32),
840 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000841
Neale Ranns008dbe12018-09-07 09:32:36 -0700842 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
843
Neale Rannsad422ed2016-11-02 14:20:04 +0000844 #
845 # add a recursive path, with 2 labels, via the 3 label route
846 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800847 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
848 [VppRoutePath("10.0.0.2",
849 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800850 labels=[VppMplsLabel(44),
851 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000852 route_11_0_0_2.add_vpp_config()
853
854 #
855 # a stream that matches the route for 11.0.0.1, should pick up
856 # the label stack for 11.0.0.1 and 10.0.0.1
857 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000858 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800859 rx = self.send_and_expect(self.pg0, tx, self.pg0)
860 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
861 [VppMplsLabel(32),
862 VppMplsLabel(33),
863 VppMplsLabel(34),
864 VppMplsLabel(44),
865 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000866
Neale Ranns008dbe12018-09-07 09:32:36 -0700867 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
868
869 rx = self.send_and_expect(self.pg0, tx, self.pg0)
870 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
871 [VppMplsLabel(32),
872 VppMplsLabel(33),
873 VppMplsLabel(34),
874 VppMplsLabel(44),
875 VppMplsLabel(45)])
876
877 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
878
Neale Rannsad422ed2016-11-02 14:20:04 +0000879 #
880 # cleanup
881 #
882 route_11_0_0_2.remove_vpp_config()
883 route_11_0_0_1.remove_vpp_config()
884 route_10_0_0_2.remove_vpp_config()
885 route_10_0_0_1.remove_vpp_config()
886
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530887 def test_imposition_fragmentation(self):
888 """ MPLS label imposition fragmentation test """
889
890 #
891 # Add a ipv4 non-recursive route with a single out label
892 #
893 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
894 [VppRoutePath(self.pg0.remote_ip4,
895 self.pg0.sw_if_index,
896 labels=[VppMplsLabel(32)])])
897 route_10_0_0_1.add_vpp_config()
898
899 #
900 # a stream that matches the route for 10.0.0.1
901 # PG0 is in the default table
902 #
903 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
904 for i in range(0, 257):
905 self.extend_packet(tx[i], 10000)
906
907 #
908 # 5 fragments per packet (257*5=1285)
909 #
910 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
911 self.verify_capture_fragmented_labelled_ip4(self.pg0, rx, tx,
912 [VppMplsLabel(32)])
913
914 #
915 # cleanup
916 #
917 route_10_0_0_1.remove_vpp_config()
918
Neale Ranns31ed7442018-02-23 05:29:09 -0800919 def test_tunnel_pipe(self):
920 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000921
922 #
Ole Troaneb284a12019-10-09 13:33:19 +0200923 # Create a tunnel with two out labels
Neale Rannsad422ed2016-11-02 14:20:04 +0000924 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800925 mpls_tun = VppMPLSTunnelInterface(
926 self,
927 [VppRoutePath(self.pg0.remote_ip4,
928 self.pg0.sw_if_index,
929 labels=[VppMplsLabel(44),
930 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800931 mpls_tun.add_vpp_config()
932 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000933
934 #
935 # add an unlabelled route through the new tunnel
936 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800937 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
938 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800939 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800940 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000941
942 self.vapi.cli("clear trace")
943 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
944 self.pg0.add_stream(tx)
945
946 self.pg_enable_capture(self.pg_interfaces)
947 self.pg_start()
948
949 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800950 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
951 [VppMplsLabel(44),
952 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000953
Neale Ranns8c4611b2017-05-23 03:43:47 -0700954 #
955 # add a labelled route through the new tunnel
956 #
957 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
958 [VppRoutePath("0.0.0.0",
959 mpls_tun._sw_if_index,
960 labels=[33])])
961 route_10_0_0_4.add_vpp_config()
962
963 self.vapi.cli("clear trace")
964 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
965 self.pg0.add_stream(tx)
966
967 self.pg_enable_capture(self.pg_interfaces)
968 self.pg_start()
969
970 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800971 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
972 [VppMplsLabel(44),
973 VppMplsLabel(46),
974 VppMplsLabel(33, ttl=255)])
975
Ole Troaneb284a12019-10-09 13:33:19 +0200976 #
977 # change tunnel's MTU to a low value
978 #
979 mpls_tun.set_l3_mtu(1200)
980
981 # send IP into the tunnel to be fragmented
982 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
983 payload_size=1500)
984 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
985
986 fake_tx = []
987 for p in tx:
988 fake_tx.append(p)
989 fake_tx.append(p)
990 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
991 [VppMplsLabel(44),
992 VppMplsLabel(46)])
993
994 # send MPLS into the tunnel to be fragmented
995 tx = self.create_stream_ip4(self.pg0, "10.0.0.4",
996 payload_size=1500)
997 rx = self.send_and_expect(self.pg0, tx, self.pg0, len(tx)*2)
998
999 fake_tx = []
1000 for p in tx:
1001 fake_tx.append(p)
1002 fake_tx.append(p)
1003 self.verify_capture_tunneled_ip4(self.pg0, rx, fake_tx,
1004 [VppMplsLabel(44),
1005 VppMplsLabel(46),
1006 VppMplsLabel(33, ttl=255)])
1007
Neale Ranns31ed7442018-02-23 05:29:09 -08001008 def test_tunnel_uniform(self):
1009 """ MPLS Tunnel Tests - Uniform """
1010
1011 #
1012 # Create a tunnel with a single out label
1013 # The label stack is specified here from outer to inner
1014 #
1015 mpls_tun = VppMPLSTunnelInterface(
1016 self,
1017 [VppRoutePath(self.pg0.remote_ip4,
1018 self.pg0.sw_if_index,
1019 labels=[VppMplsLabel(44, ttl=32),
1020 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1021 mpls_tun.add_vpp_config()
1022 mpls_tun.admin_up()
1023
1024 #
1025 # add an unlabelled route through the new tunnel
1026 #
1027 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1028 [VppRoutePath("0.0.0.0",
1029 mpls_tun._sw_if_index)])
1030 route_10_0_0_3.add_vpp_config()
1031
1032 self.vapi.cli("clear trace")
1033 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
1034 self.pg0.add_stream(tx)
1035
1036 self.pg_enable_capture(self.pg_interfaces)
1037 self.pg_start()
1038
1039 rx = self.pg0.get_capture()
1040 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1041 [VppMplsLabel(44, ttl=32),
1042 VppMplsLabel(46, ttl=23)])
1043
1044 #
1045 # add a labelled route through the new tunnel
1046 #
1047 route_10_0_0_4 = VppIpRoute(
1048 self, "10.0.0.4", 32,
1049 [VppRoutePath("0.0.0.0",
1050 mpls_tun._sw_if_index,
1051 labels=[VppMplsLabel(33, ttl=47)])])
1052 route_10_0_0_4.add_vpp_config()
1053
1054 self.vapi.cli("clear trace")
1055 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1056 self.pg0.add_stream(tx)
1057
1058 self.pg_enable_capture(self.pg_interfaces)
1059 self.pg_start()
1060
1061 rx = self.pg0.get_capture()
1062 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1063 [VppMplsLabel(44, ttl=32),
1064 VppMplsLabel(46, ttl=47),
1065 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001066
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001067 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001068 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001069
1070 for ii in range(10):
1071 mpls_tun = VppMPLSTunnelInterface(
1072 self,
1073 [VppRoutePath(self.pg0.remote_ip4,
1074 self.pg0.sw_if_index,
1075 labels=[VppMplsLabel(44, ttl=32),
1076 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1077 mpls_tun.add_vpp_config()
1078 mpls_tun.admin_up()
1079
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001080 def test_v4_exp_null(self):
1081 """ MPLS V4 Explicit NULL test """
1082
1083 #
1084 # The first test case has an MPLS TTL of 0
1085 # all packet should be dropped
1086 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001087 tx = self.create_stream_labelled_ip4(self.pg0,
1088 [VppMplsLabel(0, ttl=0)])
1089 self.send_and_assert_no_replies(self.pg0, tx,
1090 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001091
1092 #
1093 # a stream with a non-zero MPLS TTL
1094 # PG0 is in the default table
1095 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001096 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1097 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001098 self.verify_capture_ip4(self.pg0, rx, tx)
1099
1100 #
1101 # a stream with a non-zero MPLS TTL
1102 # PG1 is in table 1
1103 # we are ensuring the post-pop lookup occurs in the VRF table
1104 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001105 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1106 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1107 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001108
1109 def test_v6_exp_null(self):
1110 """ MPLS V6 Explicit NULL test """
1111
1112 #
1113 # a stream with a non-zero MPLS TTL
1114 # PG0 is in the default table
1115 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001116 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1117 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001118 self.verify_capture_ip6(self.pg0, rx, tx)
1119
1120 #
1121 # a stream with a non-zero MPLS TTL
1122 # PG1 is in table 1
1123 # we are ensuring the post-pop lookup occurs in the VRF table
1124 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001125 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1126 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001127 self.verify_capture_ip6(self.pg0, rx, tx)
1128
Neale Rannscb630ff2016-12-14 13:31:29 +01001129 def test_deag(self):
1130 """ MPLS Deagg """
1131
1132 #
1133 # A de-agg route - next-hop lookup in default table
1134 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001135 route_34_eos = VppMplsRoute(self, 34, 1,
1136 [VppRoutePath("0.0.0.0",
1137 0xffffffff,
1138 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001139 route_34_eos.add_vpp_config()
1140
1141 #
1142 # ping an interface in the default table
1143 # PG0 is in the default table
1144 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001145 tx = self.create_stream_labelled_ip4(self.pg0,
1146 [VppMplsLabel(34)],
1147 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001148 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001149 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001150 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1151
1152 #
1153 # A de-agg route - next-hop lookup in non-default table
1154 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001155 route_35_eos = VppMplsRoute(self, 35, 1,
1156 [VppRoutePath("0.0.0.0",
1157 0xffffffff,
1158 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001159 route_35_eos.add_vpp_config()
1160
1161 #
1162 # ping an interface in the non-default table
1163 # PG0 is in the default table. packet arrive labelled in the
1164 # default table and egress unlabelled in the non-default
1165 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001166 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001167 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1168 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001169 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1170
Neale Ranns6af1c042017-05-26 03:48:53 -07001171 #
1172 # Double pop
1173 #
1174 route_36_neos = VppMplsRoute(self, 36, 0,
1175 [VppRoutePath("0.0.0.0",
1176 0xffffffff)])
1177 route_36_neos.add_vpp_config()
1178
Neale Ranns31ed7442018-02-23 05:29:09 -08001179 tx = self.create_stream_labelled_ip4(self.pg0,
1180 [VppMplsLabel(36),
1181 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001182 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001183 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001184 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1185
1186 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001187 route_35_eos.remove_vpp_config()
1188 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001189
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001190 def test_interface_rx(self):
1191 """ MPLS Interface Receive """
1192
1193 #
1194 # Add a non-recursive route that will forward the traffic
1195 # post-interface-rx
1196 #
1197 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1198 table_id=1,
1199 paths=[VppRoutePath(self.pg1.remote_ip4,
1200 self.pg1.sw_if_index)])
1201 route_10_0_0_1.add_vpp_config()
1202
1203 #
1204 # An interface receive label that maps traffic to RX on interface
1205 # pg1
1206 # by injecting the packet in on pg0, which is in table 0
1207 # doing an interface-rx on pg1 and matching a route in table 1
1208 # if the packet egresses, then we must have swapped to pg1
1209 # so as to have matched the route in table 1
1210 #
Neale Ranns097fa662018-05-01 05:17:55 -07001211 route_34_eos = VppMplsRoute(
1212 self, 34, 1,
1213 [VppRoutePath("0.0.0.0",
1214 self.pg1.sw_if_index,
1215 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001216 route_34_eos.add_vpp_config()
1217
1218 #
1219 # ping an interface in the default table
1220 # PG0 is in the default table
1221 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001222 tx = self.create_stream_labelled_ip4(self.pg0,
1223 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001224 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001225 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001226 self.verify_capture_ip4(self.pg1, rx, tx)
1227
1228 def test_mcast_mid_point(self):
1229 """ MPLS Multicast Mid Point """
1230
1231 #
1232 # Add a non-recursive route that will forward the traffic
1233 # post-interface-rx
1234 #
1235 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1236 table_id=1,
1237 paths=[VppRoutePath(self.pg1.remote_ip4,
1238 self.pg1.sw_if_index)])
1239 route_10_0_0_1.add_vpp_config()
1240
1241 #
1242 # Add a mcast entry that replicate to pg2 and pg3
1243 # and replicate to a interface-rx (like a bud node would)
1244 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001245 route_3400_eos = VppMplsRoute(
1246 self, 3400, 1,
1247 [VppRoutePath(self.pg2.remote_ip4,
1248 self.pg2.sw_if_index,
1249 labels=[VppMplsLabel(3401)]),
1250 VppRoutePath(self.pg3.remote_ip4,
1251 self.pg3.sw_if_index,
1252 labels=[VppMplsLabel(3402)]),
1253 VppRoutePath("0.0.0.0",
1254 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001255 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001256 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001257 route_3400_eos.add_vpp_config()
1258
1259 #
1260 # ping an interface in the default table
1261 # PG0 is in the default table
1262 #
1263 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001264 tx = self.create_stream_labelled_ip4(self.pg0,
1265 [VppMplsLabel(3400, ttl=64)],
1266 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001267 dst_ip="10.0.0.1")
1268 self.pg0.add_stream(tx)
1269
1270 self.pg_enable_capture(self.pg_interfaces)
1271 self.pg_start()
1272
1273 rx = self.pg1.get_capture(257)
1274 self.verify_capture_ip4(self.pg1, rx, tx)
1275
1276 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001277 self.verify_capture_labelled(self.pg2, rx, tx,
1278 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001279 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001280 self.verify_capture_labelled(self.pg3, rx, tx,
1281 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001282
1283 def test_mcast_head(self):
1284 """ MPLS Multicast Head-end """
1285
Neale Ranns990f6942020-10-20 07:20:17 +00001286 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1287 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1288
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001289 #
1290 # Create a multicast tunnel with two replications
1291 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001292 mpls_tun = VppMPLSTunnelInterface(
1293 self,
1294 [VppRoutePath(self.pg2.remote_ip4,
1295 self.pg2.sw_if_index,
1296 labels=[VppMplsLabel(42)]),
1297 VppRoutePath(self.pg3.remote_ip4,
1298 self.pg3.sw_if_index,
1299 labels=[VppMplsLabel(43)])],
1300 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001301 mpls_tun.add_vpp_config()
1302 mpls_tun.admin_up()
1303
1304 #
1305 # add an unlabelled route through the new tunnel
1306 #
1307 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1308 [VppRoutePath("0.0.0.0",
1309 mpls_tun._sw_if_index)])
1310 route_10_0_0_3.add_vpp_config()
1311
1312 self.vapi.cli("clear trace")
1313 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1314 self.pg0.add_stream(tx)
1315
1316 self.pg_enable_capture(self.pg_interfaces)
1317 self.pg_start()
1318
1319 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001320 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001321 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001322 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001323
1324 #
1325 # An an IP multicast route via the tunnel
1326 # A (*,G).
1327 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1328 #
1329 route_232_1_1_1 = VppIpMRoute(
1330 self,
1331 "0.0.0.0",
1332 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001333 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001334 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001335 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001336 VppMRoutePath(mpls_tun._sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001337 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001338 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001339 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001340
1341 self.vapi.cli("clear trace")
1342 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1343 self.pg0.add_stream(tx)
1344
1345 self.pg_enable_capture(self.pg_interfaces)
1346 self.pg_start()
1347
1348 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001349 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001350 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001351 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001352
Neale Ranns31426c62017-05-24 10:32:58 -07001353 def test_mcast_ip4_tail(self):
1354 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001355
Neale Ranns990f6942020-10-20 07:20:17 +00001356 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1357 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1358
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001359 #
1360 # Add a multicast route that will forward the traffic
1361 # post-disposition
1362 #
1363 route_232_1_1_1 = VppIpMRoute(
1364 self,
1365 "0.0.0.0",
1366 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001367 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001368 table_id=1,
1369 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001370 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001371 route_232_1_1_1.add_vpp_config()
1372
1373 #
1374 # An interface receive label that maps traffic to RX on interface
1375 # pg1
1376 # by injecting the packet in on pg0, which is in table 0
1377 # doing an rpf-id and matching a route in table 1
1378 # if the packet egresses, then we must have matched the route in
1379 # table 1
1380 #
Neale Ranns097fa662018-05-01 05:17:55 -07001381 route_34_eos = VppMplsRoute(
1382 self, 34, 1,
1383 [VppRoutePath("0.0.0.0",
1384 0xffffffff,
1385 nh_table_id=1,
1386 rpf_id=55)],
1387 is_multicast=1,
1388 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001389
1390 route_34_eos.add_vpp_config()
1391
1392 #
1393 # Drop due to interface lookup miss
1394 #
1395 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001396 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001397 dst_ip="232.1.1.1", n=1)
1398 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1399
1400 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001401 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001402 #
1403 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001404 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001405
Neale Ranns31ed7442018-02-23 05:29:09 -08001406 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1407 dst_ip="232.1.1.1")
1408 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001409 self.verify_capture_ip4(self.pg1, rx, tx)
1410
1411 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001412 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001413 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001414 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001415 dst_ip="232.1.1.1", n=65,
1416 chksum=1)
1417 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1418
1419 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001420 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001421 #
1422 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001423 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001424 dst_ip="232.1.1.1")
1425 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1426
Neale Ranns31426c62017-05-24 10:32:58 -07001427 def test_mcast_ip6_tail(self):
1428 """ MPLS IPv6 Multicast Tail """
1429
Neale Ranns990f6942020-10-20 07:20:17 +00001430 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1431 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1432
Neale Ranns31426c62017-05-24 10:32:58 -07001433 #
1434 # Add a multicast route that will forward the traffic
1435 # post-disposition
1436 #
1437 route_ff = VppIpMRoute(
1438 self,
1439 "::",
1440 "ff01::1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001441 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns31426c62017-05-24 10:32:58 -07001442 table_id=1,
1443 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001444 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001445 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001446 route_ff.add_vpp_config()
1447
1448 #
1449 # An interface receive label that maps traffic to RX on interface
1450 # pg1
1451 # by injecting the packet in on pg0, which is in table 0
1452 # doing an rpf-id and matching a route in table 1
1453 # if the packet egresses, then we must have matched the route in
1454 # table 1
1455 #
1456 route_34_eos = VppMplsRoute(
1457 self, 34, 1,
1458 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001459 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001460 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001461 rpf_id=55)],
1462 is_multicast=1,
1463 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001464
1465 route_34_eos.add_vpp_config()
1466
1467 #
1468 # Drop due to interface lookup miss
1469 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001470 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001471 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001472 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001473
1474 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001475 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001476 #
1477 route_ff.update_rpf_id(55)
1478
Neale Ranns31ed7442018-02-23 05:29:09 -08001479 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001480 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001481 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001482 self.verify_capture_ip6(self.pg1, rx, tx)
1483
1484 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001485 # disposed packets have hop-limit = 1
1486 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001487 tx = self.create_stream_labelled_ip6(self.pg0,
1488 [VppMplsLabel(34)],
1489 dst_ip="ff01::1",
1490 hlim=1)
1491 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001492 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001493
1494 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001495 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001496 #
1497 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001498 tx = self.create_stream_labelled_ip6(self.pg0,
1499 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001500 dst_ip="ff01::1")
1501 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1502
Neale Rannsd5d7b962019-08-04 03:30:56 -07001503 def test_6pe(self):
1504 """ MPLS 6PE """
1505
1506 #
1507 # Add a non-recursive route with a single out label
1508 #
1509 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1510 [VppRoutePath(self.pg0.remote_ip4,
1511 self.pg0.sw_if_index,
1512 labels=[VppMplsLabel(45)])])
1513 route_10_0_0_1.add_vpp_config()
1514
1515 # bind a local label to the route
1516 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1517 binding.add_vpp_config()
1518
1519 #
1520 # a labelled v6 route that resolves through the v4
1521 #
1522 route_2001_3 = VppIpRoute(
1523 self, "2001::3", 128,
1524 [VppRoutePath("10.0.0.1",
1525 INVALID_INDEX,
1526 labels=[VppMplsLabel(32)])])
1527 route_2001_3.add_vpp_config()
1528
1529 tx = self.create_stream_ip6(self.pg0, "2001::3")
1530 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1531
1532 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1533 [VppMplsLabel(45),
1534 VppMplsLabel(32)])
1535
1536 #
1537 # and a v4 recursive via the v6
1538 #
1539 route_20_3 = VppIpRoute(
1540 self, "20.0.0.3", 32,
1541 [VppRoutePath("2001::3",
1542 INVALID_INDEX,
1543 labels=[VppMplsLabel(99)])])
1544 route_20_3.add_vpp_config()
1545
1546 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1547 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1548
1549 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1550 [VppMplsLabel(45),
1551 VppMplsLabel(32),
1552 VppMplsLabel(99)])
1553
Neale Ranns180279b2017-03-16 15:49:09 -04001554
1555class TestMPLSDisabled(VppTestCase):
1556 """ MPLS disabled """
1557
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001558 @classmethod
1559 def setUpClass(cls):
1560 super(TestMPLSDisabled, cls).setUpClass()
1561
1562 @classmethod
1563 def tearDownClass(cls):
1564 super(TestMPLSDisabled, cls).tearDownClass()
1565
Neale Ranns180279b2017-03-16 15:49:09 -04001566 def setUp(self):
1567 super(TestMPLSDisabled, self).setUp()
1568
1569 # create 2 pg interfaces
1570 self.create_pg_interfaces(range(2))
1571
Neale Ranns15002542017-09-10 04:39:11 -07001572 self.tbl = VppMplsTable(self, 0)
1573 self.tbl.add_vpp_config()
1574
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001575 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001576 self.pg0.admin_up()
1577 self.pg0.config_ip4()
1578 self.pg0.resolve_arp()
1579 self.pg0.enable_mpls()
1580
1581 # PG 1 is not MPLS enabled
1582 self.pg1.admin_up()
1583
1584 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001585 for i in self.pg_interfaces:
1586 i.unconfig_ip4()
1587 i.admin_down()
1588
Neale Ranns15002542017-09-10 04:39:11 -07001589 self.pg0.disable_mpls()
1590 super(TestMPLSDisabled, self).tearDown()
1591
Neale Ranns180279b2017-03-16 15:49:09 -04001592 def test_mpls_disabled(self):
1593 """ MPLS Disabled """
1594
1595 tx = (Ether(src=self.pg1.remote_mac,
1596 dst=self.pg1.local_mac) /
1597 MPLS(label=32, ttl=64) /
1598 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1599 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001600 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -04001601
1602 #
1603 # A simple MPLS xconnect - eos label in label out
1604 #
1605 route_32_eos = VppMplsRoute(self, 32, 1,
1606 [VppRoutePath(self.pg0.remote_ip4,
1607 self.pg0.sw_if_index,
1608 labels=[33])])
1609 route_32_eos.add_vpp_config()
1610
1611 #
1612 # PG1 does not forward IP traffic
1613 #
1614 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1615
1616 #
1617 # MPLS enable PG1
1618 #
1619 self.pg1.enable_mpls()
1620
1621 #
1622 # Now we get packets through
1623 #
1624 self.pg1.add_stream(tx)
1625 self.pg_enable_capture(self.pg_interfaces)
1626 self.pg_start()
1627
1628 rx = self.pg0.get_capture(1)
1629
1630 #
1631 # Disable PG1
1632 #
1633 self.pg1.disable_mpls()
1634
1635 #
1636 # PG1 does not forward IP traffic
1637 #
1638 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1639 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1640
1641
Neale Rannsf12a83f2017-04-18 09:09:40 -07001642class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001643 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001644
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001645 @classmethod
1646 def setUpClass(cls):
1647 super(TestMPLSPIC, cls).setUpClass()
1648
1649 @classmethod
1650 def tearDownClass(cls):
1651 super(TestMPLSPIC, cls).tearDownClass()
1652
Neale Rannsf12a83f2017-04-18 09:09:40 -07001653 def setUp(self):
1654 super(TestMPLSPIC, self).setUp()
1655
1656 # create 2 pg interfaces
1657 self.create_pg_interfaces(range(4))
1658
Neale Ranns15002542017-09-10 04:39:11 -07001659 mpls_tbl = VppMplsTable(self, 0)
1660 mpls_tbl.add_vpp_config()
1661 tbl4 = VppIpTable(self, 1)
1662 tbl4.add_vpp_config()
1663 tbl6 = VppIpTable(self, 1, is_ip6=1)
1664 tbl6.add_vpp_config()
1665
Neale Rannsf12a83f2017-04-18 09:09:40 -07001666 # core links
1667 self.pg0.admin_up()
1668 self.pg0.config_ip4()
1669 self.pg0.resolve_arp()
1670 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001671
Neale Rannsf12a83f2017-04-18 09:09:40 -07001672 self.pg1.admin_up()
1673 self.pg1.config_ip4()
1674 self.pg1.resolve_arp()
1675 self.pg1.enable_mpls()
1676
1677 # VRF (customer facing) link
1678 self.pg2.admin_up()
1679 self.pg2.set_table_ip4(1)
1680 self.pg2.config_ip4()
1681 self.pg2.resolve_arp()
1682 self.pg2.set_table_ip6(1)
1683 self.pg2.config_ip6()
1684 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001685
Neale Rannsf12a83f2017-04-18 09:09:40 -07001686 self.pg3.admin_up()
1687 self.pg3.set_table_ip4(1)
1688 self.pg3.config_ip4()
1689 self.pg3.resolve_arp()
1690 self.pg3.set_table_ip6(1)
1691 self.pg3.config_ip6()
1692 self.pg3.resolve_ndp()
1693
1694 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001695 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001696 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001697 for i in self.pg_interfaces:
1698 i.unconfig_ip4()
1699 i.unconfig_ip6()
1700 i.set_table_ip4(0)
1701 i.set_table_ip6(0)
1702 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001703 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001704
1705 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001706 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001707
1708 1) setup many iBGP VPN routes via a pair of iBGP peers.
1709 2) Check EMCP forwarding to these peers
1710 3) withdraw the IGP route to one of these peers.
1711 4) check forwarding continues to the remaining peer
1712 """
1713
1714 #
1715 # IGP+LDP core routes
1716 #
1717 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1718 [VppRoutePath(self.pg0.remote_ip4,
1719 self.pg0.sw_if_index,
1720 labels=[45])])
1721 core_10_0_0_45.add_vpp_config()
1722
1723 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1724 [VppRoutePath(self.pg1.remote_ip4,
1725 self.pg1.sw_if_index,
1726 labels=[46])])
1727 core_10_0_0_46.add_vpp_config()
1728
1729 #
1730 # Lot's of VPN routes. We need more the 64 so VPP will build
1731 # the fast convergence indirection
1732 #
1733 vpn_routes = []
1734 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001735 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001736 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001737 vpn_routes.append(VppIpRoute(
1738 self, dst, 32,
1739 [VppRoutePath(
1740 "10.0.0.45",
1741 0xffffffff,
1742 labels=[145],
1743 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1744 VppRoutePath(
1745 "10.0.0.46",
1746 0xffffffff,
1747 labels=[146],
1748 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1749 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001750 vpn_routes[ii].add_vpp_config()
1751
1752 pkts.append(Ether(dst=self.pg2.local_mac,
1753 src=self.pg2.remote_mac) /
1754 IP(src=self.pg2.remote_ip4, dst=dst) /
1755 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001756 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001757
1758 #
1759 # Send the packet stream (one pkt to each VPN route)
1760 # - expect a 50-50 split of the traffic
1761 #
1762 self.pg2.add_stream(pkts)
1763 self.pg_enable_capture(self.pg_interfaces)
1764 self.pg_start()
1765
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001766 rx0 = self.pg0._get_capture(NUM_PKTS)
1767 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001768
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001769 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001770 # with the split ratio, just as long as neither is 0
1771 self.assertNotEqual(0, len(rx0))
1772 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001773 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1774 "Expected all (%s) packets across both ECMP paths. "
1775 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001776
1777 #
1778 # use a test CLI command to stop the FIB walk process, this
1779 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001780 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001781 #
1782 self.vapi.ppcli("test fib-walk-process disable")
1783
1784 #
1785 # Withdraw one of the IGP routes
1786 #
1787 core_10_0_0_46.remove_vpp_config()
1788
1789 #
1790 # now all packets should be forwarded through the remaining peer
1791 #
1792 self.vapi.ppcli("clear trace")
1793 self.pg2.add_stream(pkts)
1794 self.pg_enable_capture(self.pg_interfaces)
1795 self.pg_start()
1796
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001797 rx0 = self.pg0.get_capture(NUM_PKTS)
1798 self.assertEqual(len(pkts), len(rx0),
1799 "Expected all (%s) packets across single path. "
1800 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001801
1802 #
1803 # enable the FIB walk process to converge the FIB
1804 #
1805 self.vapi.ppcli("test fib-walk-process enable")
1806
1807 #
1808 # packets should still be forwarded through the remaining peer
1809 #
1810 self.pg2.add_stream(pkts)
1811 self.pg_enable_capture(self.pg_interfaces)
1812 self.pg_start()
1813
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001814 rx0 = self.pg0.get_capture(NUM_PKTS)
1815 self.assertEqual(len(pkts), len(rx0),
1816 "Expected all (%s) packets across single path. "
1817 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001818
1819 #
1820 # Add the IGP route back and we return to load-balancing
1821 #
1822 core_10_0_0_46.add_vpp_config()
1823
1824 self.pg2.add_stream(pkts)
1825 self.pg_enable_capture(self.pg_interfaces)
1826 self.pg_start()
1827
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001828 rx0 = self.pg0._get_capture(NUM_PKTS)
1829 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001830 self.assertNotEqual(0, len(rx0))
1831 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001832 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1833 "Expected all (%s) packets across both ECMP paths. "
1834 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001835
1836 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001837 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001838
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001839 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001840 2) Check EMCP forwarding to these peers
1841 3) withdraw one eBGP path - expect LB across remaining eBGP
1842 """
1843
1844 #
1845 # Lot's of VPN routes. We need more the 64 so VPP will build
1846 # the fast convergence indirection
1847 #
1848 vpn_routes = []
1849 vpn_bindings = []
1850 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001851 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001852 dst = "192.168.1.%d" % ii
1853 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001854 vpn_routes.append(VppIpRoute(
1855 self, dst, 32,
1856 [VppRoutePath(
1857 self.pg2.remote_ip4,
1858 0xffffffff,
1859 nh_table_id=1,
1860 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1861 VppRoutePath(
1862 self.pg3.remote_ip4,
1863 0xffffffff,
1864 nh_table_id=1,
1865 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1866 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001867 vpn_routes[ii].add_vpp_config()
1868
1869 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1870 ip_table_id=1))
1871 vpn_bindings[ii].add_vpp_config()
1872
1873 pkts.append(Ether(dst=self.pg0.local_mac,
1874 src=self.pg0.remote_mac) /
1875 MPLS(label=local_label, ttl=64) /
1876 IP(src=self.pg0.remote_ip4, dst=dst) /
1877 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001878 Raw(b'\xa5' * 100))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001879
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001880 #
1881 # Send the packet stream (one pkt to each VPN route)
1882 # - expect a 50-50 split of the traffic
1883 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001884 self.pg0.add_stream(pkts)
1885 self.pg_enable_capture(self.pg_interfaces)
1886 self.pg_start()
1887
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001888 rx0 = self.pg2._get_capture(NUM_PKTS)
1889 rx1 = self.pg3._get_capture(NUM_PKTS)
1890
1891 # not testing the LB hashing algorithm so we're not concerned
1892 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001893 self.assertNotEqual(0, len(rx0))
1894 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001895 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1896 "Expected all (%s) packets across both ECMP paths. "
1897 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001898
1899 #
1900 # use a test CLI command to stop the FIB walk process, this
1901 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001902 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001903 #
1904 self.vapi.ppcli("test fib-walk-process disable")
1905
1906 #
1907 # withdraw the connected prefix on the interface.
1908 #
1909 self.pg2.unconfig_ip4()
1910
1911 #
1912 # now all packets should be forwarded through the remaining peer
1913 #
1914 self.pg0.add_stream(pkts)
1915 self.pg_enable_capture(self.pg_interfaces)
1916 self.pg_start()
1917
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001918 rx0 = self.pg3.get_capture(NUM_PKTS)
1919 self.assertEqual(len(pkts), len(rx0),
1920 "Expected all (%s) packets across single path. "
1921 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001922
1923 #
1924 # enable the FIB walk process to converge the FIB
1925 #
1926 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001927
1928 #
1929 # packets should still be forwarded through the remaining peer
1930 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001931 self.pg0.add_stream(pkts)
1932 self.pg_enable_capture(self.pg_interfaces)
1933 self.pg_start()
1934
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001935 rx0 = self.pg3.get_capture(NUM_PKTS)
1936 self.assertEqual(len(pkts), len(rx0),
1937 "Expected all (%s) packets across single path. "
1938 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001939
1940 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001941 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001942 #
1943 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001944 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001945
1946 self.pg0.add_stream(pkts)
1947 self.pg_enable_capture(self.pg_interfaces)
1948 self.pg_start()
1949
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001950 rx0 = self.pg2._get_capture(NUM_PKTS)
1951 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001952 self.assertNotEqual(0, len(rx0))
1953 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001954 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1955 "Expected all (%s) packets across both ECMP paths. "
1956 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001957
1958 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001959 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001960
1961 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1962 2) Check EMCP forwarding to these peers
1963 3) withdraw one eBGP path - expect LB across remaining eBGP
1964 """
1965
1966 #
1967 # Lot's of VPN routes. We need more the 64 so VPP will build
1968 # the fast convergence indirection
1969 #
1970 vpn_routes = []
1971 vpn_bindings = []
1972 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001973 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001974 dst = "3000::%d" % ii
1975 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001976 vpn_routes.append(VppIpRoute(
1977 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001978 [VppRoutePath(
1979 self.pg2.remote_ip6,
1980 0xffffffff,
1981 nh_table_id=1,
1982 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1983 VppRoutePath(
1984 self.pg3.remote_ip6,
1985 0xffffffff,
1986 nh_table_id=1,
1987 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1988 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001989 vpn_routes[ii].add_vpp_config()
1990
1991 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001992 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001993 vpn_bindings[ii].add_vpp_config()
1994
1995 pkts.append(Ether(dst=self.pg0.local_mac,
1996 src=self.pg0.remote_mac) /
1997 MPLS(label=local_label, ttl=64) /
1998 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1999 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002000 Raw(b'\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07002001 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002002
2003 self.pg0.add_stream(pkts)
2004 self.pg_enable_capture(self.pg_interfaces)
2005 self.pg_start()
2006
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002007 rx0 = self.pg2._get_capture(NUM_PKTS)
2008 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002009 self.assertNotEqual(0, len(rx0))
2010 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002011 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2012 "Expected all (%s) packets across both ECMP paths. "
2013 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002014
2015 #
2016 # use a test CLI command to stop the FIB walk process, this
2017 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002018 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07002019 #
2020 self.vapi.ppcli("test fib-walk-process disable")
2021
2022 #
2023 # withdraw the connected prefix on the interface.
2024 # and shutdown the interface so the ND cache is flushed.
2025 #
2026 self.pg2.unconfig_ip6()
2027 self.pg2.admin_down()
2028
2029 #
2030 # now all packets should be forwarded through the remaining peer
2031 #
2032 self.pg0.add_stream(pkts)
2033 self.pg_enable_capture(self.pg_interfaces)
2034 self.pg_start()
2035
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002036 rx0 = self.pg3.get_capture(NUM_PKTS)
2037 self.assertEqual(len(pkts), len(rx0),
2038 "Expected all (%s) packets across single path. "
2039 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002040
2041 #
2042 # enable the FIB walk process to converge the FIB
2043 #
2044 self.vapi.ppcli("test fib-walk-process enable")
2045 self.pg0.add_stream(pkts)
2046 self.pg_enable_capture(self.pg_interfaces)
2047 self.pg_start()
2048
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002049 rx0 = self.pg3.get_capture(NUM_PKTS)
2050 self.assertEqual(len(pkts), len(rx0),
2051 "Expected all (%s) packets across single path. "
2052 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002053
2054 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002055 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002056 #
Paul Vinciguerraa42c6ee2019-12-27 00:17:01 -05002057 self.logger.info(self.vapi.cli("sh log"))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002058 self.pg2.admin_up()
2059 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002060 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002061
2062 self.pg0.add_stream(pkts)
2063 self.pg_enable_capture(self.pg_interfaces)
2064 self.pg_start()
2065
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002066 rx0 = self.pg2._get_capture(NUM_PKTS)
2067 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002068 self.assertNotEqual(0, len(rx0))
2069 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002070 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2071 "Expected all (%s) packets across both ECMP paths. "
2072 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002073
2074
Neale Rannsda78f952017-05-24 09:15:43 -07002075class TestMPLSL2(VppTestCase):
2076 """ MPLS-L2 """
2077
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002078 @classmethod
2079 def setUpClass(cls):
2080 super(TestMPLSL2, cls).setUpClass()
2081
2082 @classmethod
2083 def tearDownClass(cls):
2084 super(TestMPLSL2, cls).tearDownClass()
2085
Neale Rannsda78f952017-05-24 09:15:43 -07002086 def setUp(self):
2087 super(TestMPLSL2, self).setUp()
2088
2089 # create 2 pg interfaces
2090 self.create_pg_interfaces(range(2))
2091
Neale Ranns15002542017-09-10 04:39:11 -07002092 # create the default MPLS table
2093 self.tables = []
2094 tbl = VppMplsTable(self, 0)
2095 tbl.add_vpp_config()
2096 self.tables.append(tbl)
2097
Neale Ranns1976f362019-11-06 13:13:01 +00002098 # use pg0 as the core facing interface, don't resolve ARP
Neale Rannsda78f952017-05-24 09:15:43 -07002099 self.pg0.admin_up()
2100 self.pg0.config_ip4()
Neale Rannsda78f952017-05-24 09:15:43 -07002101 self.pg0.enable_mpls()
2102
Neale Ranns15002542017-09-10 04:39:11 -07002103 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002104 for i in self.pg_interfaces[1:]:
2105 i.admin_up()
2106
2107 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002108 for i in self.pg_interfaces[1:]:
2109 i.admin_down()
2110
2111 self.pg0.disable_mpls()
2112 self.pg0.unconfig_ip4()
2113 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002114 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002115
Neale Ranns31ed7442018-02-23 05:29:09 -08002116 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002117 capture = verify_filter(capture, sent)
2118
2119 self.assertEqual(len(capture), len(sent))
2120
2121 for i in range(len(capture)):
2122 tx = sent[i]
2123 rx = capture[i]
2124
2125 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002126 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002127
2128 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002129 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002130
2131 self.assertEqual(rx_eth.src, tx_eth.src)
2132 self.assertEqual(rx_eth.dst, tx_eth.dst)
2133
Neale Ranns1976f362019-11-06 13:13:01 +00002134 def verify_arp_req(self, rx, smac, sip, dip):
2135 ether = rx[Ether]
2136 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
2137 self.assertEqual(ether.src, smac)
2138
2139 arp = rx[ARP]
2140 self.assertEqual(arp.hwtype, 1)
2141 self.assertEqual(arp.ptype, 0x800)
2142 self.assertEqual(arp.hwlen, 6)
2143 self.assertEqual(arp.plen, 4)
2144 self.assertEqual(arp.op, ARP.who_has)
2145 self.assertEqual(arp.hwsrc, smac)
2146 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2147 self.assertEqual(arp.psrc, sip)
2148 self.assertEqual(arp.pdst, dip)
2149
Neale Rannsda78f952017-05-24 09:15:43 -07002150 def test_vpws(self):
2151 """ Virtual Private Wire Service """
2152
2153 #
2154 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002155 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2156 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002157 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002158 mpls_tun_1 = VppMPLSTunnelInterface(
2159 self,
2160 [VppRoutePath(self.pg0.remote_ip4,
2161 self.pg0.sw_if_index,
2162 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2163 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002164 mpls_tun_1.add_vpp_config()
2165 mpls_tun_1.admin_up()
2166
2167 #
2168 # Create a label entry to for 55 that does L2 input to the tunnel
2169 #
2170 route_55_eos = VppMplsRoute(
2171 self, 55, 1,
2172 [VppRoutePath("0.0.0.0",
2173 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002174 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2175 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2176 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002177 route_55_eos.add_vpp_config()
2178
2179 #
2180 # Cross-connect the tunnel with one of the customers L2 interfaces
2181 #
2182 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2183 mpls_tun_1.sw_if_index,
2184 enable=1)
2185 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2186 self.pg1.sw_if_index,
2187 enable=1)
2188
2189 #
2190 # inject a packet from the core
2191 #
2192 pcore = (Ether(dst=self.pg0.local_mac,
2193 src=self.pg0.remote_mac) /
2194 MPLS(label=55, ttl=64) /
2195 Ether(dst="00:00:de:ad:ba:be",
2196 src="00:00:de:ad:be:ef") /
2197 IP(src="10.10.10.10", dst="11.11.11.11") /
2198 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002199 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002200
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002201 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002202 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2203 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002204
Neale Ranns31ed7442018-02-23 05:29:09 -08002205 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2206 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002207
2208 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002209 # Inject a packet from the customer/L2 side
Neale Ranns1976f362019-11-06 13:13:01 +00002210 # there's no resolved ARP entry so the first packet we see should be
2211 # an ARP request
Neale Rannsda78f952017-05-24 09:15:43 -07002212 #
Neale Ranns1976f362019-11-06 13:13:01 +00002213 tx1 = pcore[MPLS].payload
2214 rx1 = self.send_and_expect(self.pg1, [tx1], self.pg0)
2215
2216 self.verify_arp_req(rx1[0],
2217 self.pg0.local_mac,
2218 self.pg0.local_ip4,
2219 self.pg0.remote_ip4)
2220
2221 #
2222 # resolve the ARP entries and send again
2223 #
2224 self.pg0.resolve_arp()
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002225 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002226 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002227
Neale Ranns31ed7442018-02-23 05:29:09 -08002228 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002229
2230 def test_vpls(self):
2231 """ Virtual Private LAN Service """
Neale Ranns1976f362019-11-06 13:13:01 +00002232
2233 # we skipped this in the setup
2234 self.pg0.resolve_arp()
2235
Neale Rannsda78f952017-05-24 09:15:43 -07002236 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002237 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002238 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002239 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002240 self,
2241 [VppRoutePath(self.pg0.remote_ip4,
2242 self.pg0.sw_if_index,
2243 labels=[VppMplsLabel(42)])],
2244 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002245 mpls_tun1.add_vpp_config()
2246 mpls_tun1.admin_up()
2247
2248 mpls_tun2 = VppMPLSTunnelInterface(
2249 self,
2250 [VppRoutePath(self.pg0.remote_ip4,
2251 self.pg0.sw_if_index,
2252 labels=[VppMplsLabel(43)])],
2253 is_l2=1)
2254 mpls_tun2.add_vpp_config()
2255 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002256
2257 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002258 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2259 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002260 #
2261 route_55_eos = VppMplsRoute(
2262 self, 55, 1,
2263 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002264 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002265 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2266 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2267 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002268
2269 route_56_eos = VppMplsRoute(
2270 self, 56, 1,
2271 [VppRoutePath("0.0.0.0",
2272 mpls_tun2.sw_if_index,
2273 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2274 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2275 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2276 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2277
2278 # move me
2279 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002280 route_55_eos.add_vpp_config()
2281
Neale Ranns1dbcf302019-07-19 11:44:53 +00002282 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2283
Neale Rannsda78f952017-05-24 09:15:43 -07002284 #
2285 # add to tunnel to the customers bridge-domain
2286 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002287 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002288 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2289 self.vapi.sw_interface_set_l2_bridge(
2290 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002291 self.vapi.sw_interface_set_l2_bridge(
2292 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002293
2294 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002295 # Packet from host on the customer interface to each host
2296 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002297 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002298 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2299 src="00:00:de:ad:be:ef") /
2300 IP(src="10.10.10.10", dst="11.11.11.11") /
2301 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002302 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002303 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2304 src="00:00:de:ad:be:ef") /
2305 IP(src="10.10.10.10", dst="11.11.11.12") /
2306 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002307 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002308 p_core1 = (Ether(dst=self.pg0.local_mac,
2309 src=self.pg0.remote_mac) /
2310 MPLS(label=55, ttl=64) /
2311 Ether(src="00:00:de:ad:ba:b1",
2312 dst="00:00:de:ad:be:ef") /
2313 IP(dst="10.10.10.10", src="11.11.11.11") /
2314 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002315 Raw(b'\xa5' * 100))
Neale Ranns1dbcf302019-07-19 11:44:53 +00002316 p_core2 = (Ether(dst=self.pg0.local_mac,
2317 src=self.pg0.remote_mac) /
2318 MPLS(label=56, ttl=64) /
Ole Troan770a0de2019-11-07 13:52:21 +01002319 Raw(b'\x01' * 4) / # PW CW
Neale Ranns1dbcf302019-07-19 11:44:53 +00002320 Ether(src="00:00:de:ad:ba:b2",
2321 dst="00:00:de:ad:be:ef") /
2322 IP(dst="10.10.10.10", src="11.11.11.12") /
2323 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01002324 Raw(b'\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002325
2326 #
2327 # The BD is learning, so send in one of each packet to learn
2328 #
Neale Rannsda78f952017-05-24 09:15:43 -07002329
Neale Ranns1dbcf302019-07-19 11:44:53 +00002330 # 2 packets due to BD flooding
2331 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2332 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002333
Neale Ranns1dbcf302019-07-19 11:44:53 +00002334 # we've learnt this so expect it be be forwarded not flooded
2335 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2336 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2337 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002338
Neale Ranns1dbcf302019-07-19 11:44:53 +00002339 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2340 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2341 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002342
2343 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002344 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002345 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002346 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2347 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002348 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002349
Neale Ranns1dbcf302019-07-19 11:44:53 +00002350 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2351 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2352 [VppMplsLabel(43)])
2353
2354 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2355 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2356
Neale Rannsda78f952017-05-24 09:15:43 -07002357 #
2358 # remove interfaces from customers bridge-domain
2359 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002360 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002361 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2362 self.vapi.sw_interface_set_l2_bridge(
2363 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002364 self.vapi.sw_interface_set_l2_bridge(
2365 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002366
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002367
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002368if __name__ == '__main__':
2369 unittest.main(testRunner=VppTestRunner)