blob: 79f3204c53edf9a42a891cd6cdfb03bce673416e [file] [log] [blame]
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001#!/usr/bin/env python
2
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 Rannsc0a93142018-09-05 15:42:26 -07007from vpp_ip import DpoProto
Neale Ranns5a8123b2017-01-26 01:18:23 -08008from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -08009 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Rannsc0a93142018-09-05 15:42:26 -070010 MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \
Neale Ranns775f73c2018-12-20 03:01:49 -080011 VppMplsLabel, MplsLspMode, find_mpls_route
Neale Ranns0f26c5a2017-03-01 15:12:11 -080012from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns8fe8cc22016-11-01 10:05:08 +000013
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070014import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000015from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010016from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010017from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070018from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000019from scapy.contrib.mpls import MPLS
20
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040021NUM_PKTS = 67
22
Klement Sekeradab231a2016-12-21 08:50:14 +010023
Neale Rannsda78f952017-05-24 09:15:43 -070024def verify_filter(capture, sent):
25 if not len(capture) == len(sent):
26 # filter out any IPv6 RAs from the capture
27 for p in capture:
28 if p.haslayer(IPv6):
29 capture.remove(p)
30 return capture
31
32
Neale Ranns31ed7442018-02-23 05:29:09 -080033def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070034 # the rx'd packet has the MPLS label popped
35 eth = rx[Ether]
36 tst.assertEqual(eth.type, 0x8847)
37
38 rx_mpls = rx[MPLS]
39
40 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080041 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
42 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
43 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
44
Neale Rannsda78f952017-05-24 09:15:43 -070045 if ii == len(mpls_labels) - 1:
46 tst.assertEqual(rx_mpls.s, 1)
47 else:
48 # not end of stack
49 tst.assertEqual(rx_mpls.s, 0)
50 # pop the label to expose the next
51 rx_mpls = rx_mpls[MPLS].payload
52
53
Neale Ranns8fe8cc22016-11-01 10:05:08 +000054class TestMPLS(VppTestCase):
55 """ MPLS Test Case """
56
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070057 @classmethod
58 def setUpClass(cls):
59 super(TestMPLS, cls).setUpClass()
60
61 @classmethod
62 def tearDownClass(cls):
63 super(TestMPLS, cls).tearDownClass()
64
Neale Ranns8fe8cc22016-11-01 10:05:08 +000065 def setUp(self):
66 super(TestMPLS, self).setUp()
67
68 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080069 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000070
71 # setup both interfaces
72 # assign them different tables.
73 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070074 self.tables = []
75
76 tbl = VppMplsTable(self, 0)
77 tbl.add_vpp_config()
78 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000079
80 for i in self.pg_interfaces:
81 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070082
83 if table_id != 0:
84 tbl = VppIpTable(self, table_id)
85 tbl.add_vpp_config()
86 self.tables.append(tbl)
87 tbl = VppIpTable(self, table_id, is_ip6=1)
88 tbl.add_vpp_config()
89 self.tables.append(tbl)
90
Neale Ranns8fe8cc22016-11-01 10:05:08 +000091 i.set_table_ip4(table_id)
92 i.set_table_ip6(table_id)
93 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000094 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000095 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000096 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000097 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000098 table_id += 1
99
100 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800101 for i in self.pg_interfaces:
102 i.unconfig_ip4()
103 i.unconfig_ip6()
104 i.ip6_disable()
Neale Ranns15002542017-09-10 04:39:11 -0700105 i.set_table_ip4(0)
106 i.set_table_ip6(0)
107 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800108 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700109 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000110
Neale Rannsad422ed2016-11-02 14:20:04 +0000111 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100112 def create_stream_labelled_ip4(
113 self,
114 src_if,
115 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100116 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800117 ip_itf=None,
118 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700119 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800120 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800121 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100122 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000123 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800124 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100125 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000126 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000127 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
128
129 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800130 p = p / MPLS(label=mpls_labels[ii].value,
131 ttl=mpls_labels[ii].ttl,
132 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100133 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800134 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800135 p = (p / IP(src=src_if.local_ip4,
136 dst=src_if.remote_ip4,
137 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800138 UDP(sport=1234, dport=1234) /
139 Raw(payload))
140 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800141 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800142 UDP(sport=1234, dport=1234) /
143 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100144 else:
145 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800146 dst=ip_itf.local_ip4,
147 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100148 ICMP())
149
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700150 if chksum:
151 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000152 info.data = p.copy()
153 pkts.append(p)
154 return pkts
155
Neale Ranns31ed7442018-02-23 05:29:09 -0800156 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
Klement Sekeradab231a2016-12-21 08:50:14 +0100157 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000158 pkts = []
159 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100160 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000161 payload = self.info_to_payload(info)
162 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800163 IP(src=src_if.remote_ip4, dst=dst_ip,
164 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000165 UDP(sport=1234, dport=1234) /
166 Raw(payload))
167 info.data = p.copy()
168 pkts.append(p)
169 return pkts
170
Neale Ranns31ed7442018-02-23 05:29:09 -0800171 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
172 self.reset_packet_infos()
173 pkts = []
174 for i in range(0, 257):
175 info = self.create_packet_info(src_if, src_if)
176 payload = self.info_to_payload(info)
177 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
178 IPv6(src=src_if.remote_ip6, dst=dst_ip,
179 hlim=ip_ttl, tc=ip_dscp) /
180 UDP(sport=1234, dport=1234) /
181 Raw(payload))
182 info.data = p.copy()
183 pkts.append(p)
184 return pkts
185
186 def create_stream_labelled_ip6(self, src_if, mpls_labels,
187 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700188 if dst_ip is None:
189 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100190 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000191 pkts = []
192 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100193 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000194 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800195 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
196 for l in mpls_labels:
197 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
198
199 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
200 UDP(sport=1234, dport=1234) /
201 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000202 info.data = p.copy()
203 pkts.append(p)
204 return pkts
205
Neale Ranns31ed7442018-02-23 05:29:09 -0800206 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
207 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000208 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700209 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000210
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000211 self.assertEqual(len(capture), len(sent))
212
213 for i in range(len(capture)):
214 tx = sent[i]
215 rx = capture[i]
216
217 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000218 eth = rx[Ether]
219 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000220
221 tx_ip = tx[IP]
222 rx_ip = rx[IP]
223
Neale Rannscb630ff2016-12-14 13:31:29 +0100224 if not ping_resp:
225 self.assertEqual(rx_ip.src, tx_ip.src)
226 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800227 self.assertEqual(rx_ip.tos, ip_dscp)
228 if not ip_ttl:
229 # IP processing post pop has decremented the TTL
230 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
231 else:
232 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100233 else:
234 self.assertEqual(rx_ip.src, tx_ip.dst)
235 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000236
237 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000238 raise
239
Neale Rannsad422ed2016-11-02 14:20:04 +0000240 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800241 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000242 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700243 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000244
245 self.assertEqual(len(capture), len(sent))
246
247 for i in range(len(capture)):
248 tx = sent[i]
249 rx = capture[i]
250 tx_ip = tx[IP]
251 rx_ip = rx[IP]
252
Neale Ranns31ed7442018-02-23 05:29:09 -0800253 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000254
255 self.assertEqual(rx_ip.src, tx_ip.src)
256 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800257 if not ip_ttl:
258 # IP processing post pop has decremented the TTL
259 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
260 else:
261 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000262
263 except:
264 raise
265
Neale Ranns31ed7442018-02-23 05:29:09 -0800266 def verify_capture_labelled_ip6(self, src_if, capture, sent,
267 mpls_labels, ip_ttl=None):
268 try:
269 capture = verify_filter(capture, sent)
270
271 self.assertEqual(len(capture), len(sent))
272
273 for i in range(len(capture)):
274 tx = sent[i]
275 rx = capture[i]
276 tx_ip = tx[IPv6]
277 rx_ip = rx[IPv6]
278
279 verify_mpls_stack(self, rx, mpls_labels)
280
281 self.assertEqual(rx_ip.src, tx_ip.src)
282 self.assertEqual(rx_ip.dst, tx_ip.dst)
283 if not ip_ttl:
284 # IP processing post pop has decremented the TTL
285 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
286 else:
287 self.assertEqual(rx_ip.hlim, ip_ttl)
288
289 except:
290 raise
291
292 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000293 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700294 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000295
296 self.assertEqual(len(capture), len(sent))
297
298 for i in range(len(capture)):
299 tx = sent[i]
300 rx = capture[i]
301 tx_ip = tx[IP]
302 rx_ip = rx[IP]
303
Neale Ranns31ed7442018-02-23 05:29:09 -0800304 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000305
306 self.assertEqual(rx_ip.src, tx_ip.src)
307 self.assertEqual(rx_ip.dst, tx_ip.dst)
308 # IP processing post pop has decremented the TTL
309 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
310
311 except:
312 raise
313
314 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800315 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000316 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700317 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000318
319 self.assertEqual(len(capture), len(sent))
320
321 for i in range(len(capture)):
322 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800323 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000324 except:
325 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000326
Neale Ranns31ed7442018-02-23 05:29:09 -0800327 def verify_capture_ip6(self, src_if, capture, sent,
328 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000329 try:
330 self.assertEqual(len(capture), len(sent))
331
332 for i in range(len(capture)):
333 tx = sent[i]
334 rx = capture[i]
335
336 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000337 eth = rx[Ether]
338 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000339
340 tx_ip = tx[IPv6]
341 rx_ip = rx[IPv6]
342
343 self.assertEqual(rx_ip.src, tx_ip.src)
344 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800345 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000346 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800347 if not ip_hlim:
348 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
349 else:
350 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000351
352 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000353 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000354
Neale Ranns62fe07c2017-10-31 12:28:22 -0700355 def verify_capture_ip6_icmp(self, src_if, capture, sent):
356 try:
357 self.assertEqual(len(capture), len(sent))
358
359 for i in range(len(capture)):
360 tx = sent[i]
361 rx = capture[i]
362
363 # the rx'd packet has the MPLS label popped
364 eth = rx[Ether]
365 self.assertEqual(eth.type, 0x86DD)
366
367 tx_ip = tx[IPv6]
368 rx_ip = rx[IPv6]
369
370 self.assertEqual(rx_ip.dst, tx_ip.src)
371 # ICMP sourced from the interface's address
372 self.assertEqual(rx_ip.src, src_if.local_ip6)
373 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200374 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700375
376 icmp = rx[ICMPv6TimeExceeded]
377
378 except:
379 raise
380
Neale Rannsad422ed2016-11-02 14:20:04 +0000381 def test_swap(self):
382 """ MPLS label swap tests """
383
384 #
385 # A simple MPLS xconnect - eos label in label out
386 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800387 route_32_eos = VppMplsRoute(self, 32, 1,
388 [VppRoutePath(self.pg0.remote_ip4,
389 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800390 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000391 route_32_eos.add_vpp_config()
392
Neale Ranns775f73c2018-12-20 03:01:49 -0800393 self.assertTrue(
394 find_mpls_route(self, 0, 32, 1,
395 [VppRoutePath(self.pg0.remote_ip4,
396 self.pg0.sw_if_index,
397 labels=[VppMplsLabel(33)])]))
398
Neale Rannsad422ed2016-11-02 14:20:04 +0000399 #
400 # a stream that matches the route for 10.0.0.1
401 # PG0 is in the default table
402 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800403 tx = self.create_stream_labelled_ip4(self.pg0,
404 [VppMplsLabel(32, ttl=32, exp=1)])
405 rx = self.send_and_expect(self.pg0, tx, self.pg0)
406 self.verify_capture_labelled(self.pg0, rx, tx,
407 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000408
Neale Ranns008dbe12018-09-07 09:32:36 -0700409 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
410
Neale Rannsad422ed2016-11-02 14:20:04 +0000411 #
412 # A simple MPLS xconnect - non-eos label in label out
413 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800414 route_32_neos = VppMplsRoute(self, 32, 0,
415 [VppRoutePath(self.pg0.remote_ip4,
416 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800417 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000418 route_32_neos.add_vpp_config()
419
420 #
421 # a stream that matches the route for 10.0.0.1
422 # PG0 is in the default table
423 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800424 tx = self.create_stream_labelled_ip4(self.pg0,
425 [VppMplsLabel(32, ttl=21, exp=7),
426 VppMplsLabel(99)])
427 rx = self.send_and_expect(self.pg0, tx, self.pg0)
428 self.verify_capture_labelled(self.pg0, rx, tx,
429 [VppMplsLabel(33, ttl=20, exp=7),
430 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700431 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000432
Neale Ranns31ed7442018-02-23 05:29:09 -0800433 #
434 # A simple MPLS xconnect - non-eos label in label out, uniform mode
435 #
436 route_42_neos = VppMplsRoute(
437 self, 42, 0,
438 [VppRoutePath(self.pg0.remote_ip4,
439 self.pg0.sw_if_index,
440 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
441 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000442
Neale Ranns31ed7442018-02-23 05:29:09 -0800443 tx = self.create_stream_labelled_ip4(self.pg0,
444 [VppMplsLabel(42, ttl=21, exp=7),
445 VppMplsLabel(99)])
446 rx = self.send_and_expect(self.pg0, tx, self.pg0)
447 self.verify_capture_labelled(self.pg0, rx, tx,
448 [VppMplsLabel(43, ttl=20, exp=7),
449 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000450
451 #
452 # An MPLS xconnect - EOS label in IP out
453 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800454 route_33_eos = VppMplsRoute(self, 33, 1,
455 [VppRoutePath(self.pg0.remote_ip4,
456 self.pg0.sw_if_index,
457 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000458 route_33_eos.add_vpp_config()
459
Neale Ranns31ed7442018-02-23 05:29:09 -0800460 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
461 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000462 self.verify_capture_ip4(self.pg0, rx, tx)
463
464 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700465 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700466 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800467 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700468 dst_ip=self.pg0.remote_ip4,
469 n=65,
470 chksum=1)
471 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
472
473 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800474 # An MPLS xconnect - EOS label in IP out, uniform mode
475 #
476 route_3333_eos = VppMplsRoute(
477 self, 3333, 1,
478 [VppRoutePath(self.pg0.remote_ip4,
479 self.pg0.sw_if_index,
480 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
481 route_3333_eos.add_vpp_config()
482
483 tx = self.create_stream_labelled_ip4(
484 self.pg0,
485 [VppMplsLabel(3333, ttl=55, exp=3)])
486 rx = self.send_and_expect(self.pg0, tx, self.pg0)
487 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
488 tx = self.create_stream_labelled_ip4(
489 self.pg0,
490 [VppMplsLabel(3333, ttl=66, exp=4)])
491 rx = self.send_and_expect(self.pg0, tx, self.pg0)
492 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
493
494 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700495 # An MPLS xconnect - EOS label in IPv6 out
496 #
497 route_333_eos = VppMplsRoute(
498 self, 333, 1,
499 [VppRoutePath(self.pg0.remote_ip6,
500 self.pg0.sw_if_index,
501 labels=[],
502 proto=DpoProto.DPO_PROTO_IP6)])
503 route_333_eos.add_vpp_config()
504
Neale Ranns31ed7442018-02-23 05:29:09 -0800505 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
506 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700507 self.verify_capture_ip6(self.pg0, rx, tx)
508
509 #
510 # disposed packets have an TTL expired
511 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800512 tx = self.create_stream_labelled_ip6(self.pg0,
513 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700514 dst_ip=self.pg1.remote_ip6,
515 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800516 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700517 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
518
519 #
520 # An MPLS xconnect - EOS label in IPv6 out w imp-null
521 #
522 route_334_eos = VppMplsRoute(
523 self, 334, 1,
524 [VppRoutePath(self.pg0.remote_ip6,
525 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800526 labels=[VppMplsLabel(3)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700527 proto=DpoProto.DPO_PROTO_IP6)])
528 route_334_eos.add_vpp_config()
529
Neale Ranns31ed7442018-02-23 05:29:09 -0800530 tx = self.create_stream_labelled_ip6(self.pg0,
531 [VppMplsLabel(334, ttl=64)])
532 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700533 self.verify_capture_ip6(self.pg0, rx, tx)
534
535 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800536 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
537 #
538 route_335_eos = VppMplsRoute(
539 self, 335, 1,
540 [VppRoutePath(self.pg0.remote_ip6,
541 self.pg0.sw_if_index,
542 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)],
543 proto=DpoProto.DPO_PROTO_IP6)])
544 route_335_eos.add_vpp_config()
545
546 tx = self.create_stream_labelled_ip6(
547 self.pg0,
548 [VppMplsLabel(335, ttl=27, exp=4)])
549 rx = self.send_and_expect(self.pg0, tx, self.pg0)
550 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
551
552 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700553 # disposed packets have an TTL expired
554 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800555 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700556 dst_ip=self.pg1.remote_ip6,
557 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800558 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700559 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
560
561 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000562 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
563 # so this traffic should be dropped.
564 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800565 route_33_neos = VppMplsRoute(self, 33, 0,
566 [VppRoutePath(self.pg0.remote_ip4,
567 self.pg0.sw_if_index,
568 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000569 route_33_neos.add_vpp_config()
570
Neale Ranns31ed7442018-02-23 05:29:09 -0800571 tx = self.create_stream_labelled_ip4(self.pg0,
572 [VppMplsLabel(33),
573 VppMplsLabel(99)])
574 self.send_and_assert_no_replies(
575 self.pg0, tx,
576 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000577
578 #
579 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000581 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800582 route_34_eos = VppMplsRoute(self, 34, 1,
583 [VppRoutePath("0.0.0.0",
584 0xffffffff,
585 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800586 labels=[VppMplsLabel(44),
587 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000588 route_34_eos.add_vpp_config()
589
Neale Ranns31ed7442018-02-23 05:29:09 -0800590 tx = self.create_stream_labelled_ip4(self.pg0,
591 [VppMplsLabel(34, ttl=3)])
592 rx = self.send_and_expect(self.pg0, tx, self.pg0)
593 self.verify_capture_labelled(self.pg0, rx, tx,
594 [VppMplsLabel(33),
595 VppMplsLabel(44),
596 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000597
Neale Ranns008dbe12018-09-07 09:32:36 -0700598 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
599 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
600
Neale Ranns31ed7442018-02-23 05:29:09 -0800601 #
602 # A recursive EOS x-connect, which resolves through another x-connect
603 # in uniform mode
604 #
605 route_35_eos = VppMplsRoute(
606 self, 35, 1,
607 [VppRoutePath("0.0.0.0",
608 0xffffffff,
609 nh_via_label=42,
610 labels=[VppMplsLabel(44)])])
611 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000612
Neale Ranns31ed7442018-02-23 05:29:09 -0800613 tx = self.create_stream_labelled_ip4(self.pg0,
614 [VppMplsLabel(35, ttl=3)])
615 rx = self.send_and_expect(self.pg0, tx, self.pg0)
616 self.verify_capture_labelled(self.pg0, rx, tx,
617 [VppMplsLabel(43, ttl=2),
618 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000619
620 #
Matej Klottondeb69842016-12-09 15:05:46 +0100621 # A recursive non-EOS x-connect, which resolves through another
622 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000623 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800624 route_34_neos = VppMplsRoute(self, 34, 0,
625 [VppRoutePath("0.0.0.0",
626 0xffffffff,
627 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800628 labels=[VppMplsLabel(44),
629 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000630 route_34_neos.add_vpp_config()
631
Neale Ranns31ed7442018-02-23 05:29:09 -0800632 tx = self.create_stream_labelled_ip4(self.pg0,
633 [VppMplsLabel(34, ttl=45),
634 VppMplsLabel(99)])
635 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100636 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800637 self.verify_capture_labelled(self.pg0, rx, tx,
638 [VppMplsLabel(33),
639 VppMplsLabel(44),
640 VppMplsLabel(46, ttl=44),
641 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000642
643 #
Matej Klottondeb69842016-12-09 15:05:46 +0100644 # an recursive IP route that resolves through the recursive non-eos
645 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000646 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800647 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
648 [VppRoutePath("0.0.0.0",
649 0xffffffff,
650 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800651 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000652 ip_10_0_0_1.add_vpp_config()
653
Neale Rannsad422ed2016-11-02 14:20:04 +0000654 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800655 rx = self.send_and_expect(self.pg0, tx, self.pg0)
656 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
657 [VppMplsLabel(33),
658 VppMplsLabel(44),
659 VppMplsLabel(46),
660 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700661 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000662
663 ip_10_0_0_1.remove_vpp_config()
664 route_34_neos.remove_vpp_config()
665 route_34_eos.remove_vpp_config()
666 route_33_neos.remove_vpp_config()
667 route_33_eos.remove_vpp_config()
668 route_32_neos.remove_vpp_config()
669 route_32_eos.remove_vpp_config()
670
671 def test_bind(self):
672 """ MPLS Local Label Binding test """
673
674 #
675 # Add a non-recursive route with a single out label
676 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800677 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
678 [VppRoutePath(self.pg0.remote_ip4,
679 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800680 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000681 route_10_0_0_1.add_vpp_config()
682
683 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800684 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000685 binding.add_vpp_config()
686
687 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800688 tx = self.create_stream_labelled_ip4(self.pg0,
689 [VppMplsLabel(44),
690 VppMplsLabel(99)])
691 rx = self.send_and_expect(self.pg0, tx, self.pg0)
692 self.verify_capture_labelled(self.pg0, rx, tx,
693 [VppMplsLabel(45, ttl=63),
694 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000695
696 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800697 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
698 rx = self.send_and_expect(self.pg0, tx, self.pg0)
699 self.verify_capture_labelled(self.pg0, rx, tx,
700 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000701
702 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000703 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800704 rx = self.send_and_expect(self.pg0, tx, self.pg0)
705 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000706
707 #
708 # cleanup
709 #
710 binding.remove_vpp_config()
711 route_10_0_0_1.remove_vpp_config()
712
713 def test_imposition(self):
714 """ MPLS label imposition test """
715
716 #
717 # Add a non-recursive route with a single out label
718 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800719 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
720 [VppRoutePath(self.pg0.remote_ip4,
721 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800722 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000723 route_10_0_0_1.add_vpp_config()
724
725 #
726 # a stream that matches the route for 10.0.0.1
727 # PG0 is in the default table
728 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000729 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800730 rx = self.send_and_expect(self.pg0, tx, self.pg0)
731 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000732
733 #
734 # Add a non-recursive route with a 3 out labels
735 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800736 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
737 [VppRoutePath(self.pg0.remote_ip4,
738 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800739 labels=[VppMplsLabel(32),
740 VppMplsLabel(33),
741 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000742 route_10_0_0_2.add_vpp_config()
743
Neale Ranns31ed7442018-02-23 05:29:09 -0800744 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
745 ip_ttl=44, ip_dscp=0xff)
746 rx = self.send_and_expect(self.pg0, tx, self.pg0)
747 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
748 [VppMplsLabel(32),
749 VppMplsLabel(33),
750 VppMplsLabel(34)],
751 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000752
Neale Ranns31ed7442018-02-23 05:29:09 -0800753 #
754 # Add a non-recursive route with a single out label in uniform mode
755 #
756 route_10_0_0_3 = VppIpRoute(
757 self, "10.0.0.3", 32,
758 [VppRoutePath(self.pg0.remote_ip4,
759 self.pg0.sw_if_index,
760 labels=[VppMplsLabel(32,
761 mode=MplsLspMode.UNIFORM)])])
762 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000763
Neale Ranns31ed7442018-02-23 05:29:09 -0800764 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
765 ip_ttl=54, ip_dscp=0xbe)
766 rx = self.send_and_expect(self.pg0, tx, self.pg0)
767 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
768 [VppMplsLabel(32, ttl=53, exp=5)])
769
770 #
771 # Add a IPv6 non-recursive route with a single out label in
772 # uniform mode
773 #
774 route_2001_3 = VppIpRoute(
775 self, "2001::3", 128,
776 [VppRoutePath(self.pg0.remote_ip6,
777 self.pg0.sw_if_index,
778 proto=DpoProto.DPO_PROTO_IP6,
779 labels=[VppMplsLabel(32,
780 mode=MplsLspMode.UNIFORM)])],
781 is_ip6=1)
782 route_2001_3.add_vpp_config()
783
784 tx = self.create_stream_ip6(self.pg0, "2001::3",
785 ip_ttl=54, ip_dscp=0xbe)
786 rx = self.send_and_expect(self.pg0, tx, self.pg0)
787 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
788 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000789
790 #
Matej Klottondeb69842016-12-09 15:05:46 +0100791 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000792 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800793 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
794 [VppRoutePath("10.0.0.1",
795 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800796 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000797 route_11_0_0_1.add_vpp_config()
798
799 #
800 # a stream that matches the route for 11.0.0.1, should pick up
801 # the label stack for 11.0.0.1 and 10.0.0.1
802 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000803 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800804 rx = self.send_and_expect(self.pg0, tx, self.pg0)
805 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
806 [VppMplsLabel(32),
807 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000808
Neale Ranns008dbe12018-09-07 09:32:36 -0700809 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
810
Neale Rannsad422ed2016-11-02 14:20:04 +0000811 #
812 # add a recursive path, with 2 labels, via the 3 label route
813 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800814 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
815 [VppRoutePath("10.0.0.2",
816 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800817 labels=[VppMplsLabel(44),
818 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000819 route_11_0_0_2.add_vpp_config()
820
821 #
822 # a stream that matches the route for 11.0.0.1, should pick up
823 # the label stack for 11.0.0.1 and 10.0.0.1
824 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000825 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800826 rx = self.send_and_expect(self.pg0, tx, self.pg0)
827 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
828 [VppMplsLabel(32),
829 VppMplsLabel(33),
830 VppMplsLabel(34),
831 VppMplsLabel(44),
832 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000833
Neale Ranns008dbe12018-09-07 09:32:36 -0700834 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
835
836 rx = self.send_and_expect(self.pg0, tx, self.pg0)
837 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
838 [VppMplsLabel(32),
839 VppMplsLabel(33),
840 VppMplsLabel(34),
841 VppMplsLabel(44),
842 VppMplsLabel(45)])
843
844 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
845
Neale Rannsad422ed2016-11-02 14:20:04 +0000846 #
847 # cleanup
848 #
849 route_11_0_0_2.remove_vpp_config()
850 route_11_0_0_1.remove_vpp_config()
851 route_10_0_0_2.remove_vpp_config()
852 route_10_0_0_1.remove_vpp_config()
853
Neale Ranns31ed7442018-02-23 05:29:09 -0800854 def test_tunnel_pipe(self):
855 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000856
857 #
858 # Create a tunnel with a single out label
859 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800860 mpls_tun = VppMPLSTunnelInterface(
861 self,
862 [VppRoutePath(self.pg0.remote_ip4,
863 self.pg0.sw_if_index,
864 labels=[VppMplsLabel(44),
865 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800866 mpls_tun.add_vpp_config()
867 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000868
869 #
870 # add an unlabelled route through the new tunnel
871 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800872 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
873 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800874 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800875 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000876
877 self.vapi.cli("clear trace")
878 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
879 self.pg0.add_stream(tx)
880
881 self.pg_enable_capture(self.pg_interfaces)
882 self.pg_start()
883
884 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800885 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
886 [VppMplsLabel(44),
887 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000888
Neale Ranns8c4611b2017-05-23 03:43:47 -0700889 #
890 # add a labelled route through the new tunnel
891 #
892 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
893 [VppRoutePath("0.0.0.0",
894 mpls_tun._sw_if_index,
895 labels=[33])])
896 route_10_0_0_4.add_vpp_config()
897
898 self.vapi.cli("clear trace")
899 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
900 self.pg0.add_stream(tx)
901
902 self.pg_enable_capture(self.pg_interfaces)
903 self.pg_start()
904
905 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800906 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
907 [VppMplsLabel(44),
908 VppMplsLabel(46),
909 VppMplsLabel(33, ttl=255)])
910
911 def test_tunnel_uniform(self):
912 """ MPLS Tunnel Tests - Uniform """
913
914 #
915 # Create a tunnel with a single out label
916 # The label stack is specified here from outer to inner
917 #
918 mpls_tun = VppMPLSTunnelInterface(
919 self,
920 [VppRoutePath(self.pg0.remote_ip4,
921 self.pg0.sw_if_index,
922 labels=[VppMplsLabel(44, ttl=32),
923 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
924 mpls_tun.add_vpp_config()
925 mpls_tun.admin_up()
926
927 #
928 # add an unlabelled route through the new tunnel
929 #
930 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
931 [VppRoutePath("0.0.0.0",
932 mpls_tun._sw_if_index)])
933 route_10_0_0_3.add_vpp_config()
934
935 self.vapi.cli("clear trace")
936 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
937 self.pg0.add_stream(tx)
938
939 self.pg_enable_capture(self.pg_interfaces)
940 self.pg_start()
941
942 rx = self.pg0.get_capture()
943 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
944 [VppMplsLabel(44, ttl=32),
945 VppMplsLabel(46, ttl=23)])
946
947 #
948 # add a labelled route through the new tunnel
949 #
950 route_10_0_0_4 = VppIpRoute(
951 self, "10.0.0.4", 32,
952 [VppRoutePath("0.0.0.0",
953 mpls_tun._sw_if_index,
954 labels=[VppMplsLabel(33, ttl=47)])])
955 route_10_0_0_4.add_vpp_config()
956
957 self.vapi.cli("clear trace")
958 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
959 self.pg0.add_stream(tx)
960
961 self.pg_enable_capture(self.pg_interfaces)
962 self.pg_start()
963
964 rx = self.pg0.get_capture()
965 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
966 [VppMplsLabel(44, ttl=32),
967 VppMplsLabel(46, ttl=47),
968 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -0700969
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700970 def test_mpls_tunnel_many(self):
971 """ Multiple Tunnels """
972
973 for ii in range(10):
974 mpls_tun = VppMPLSTunnelInterface(
975 self,
976 [VppRoutePath(self.pg0.remote_ip4,
977 self.pg0.sw_if_index,
978 labels=[VppMplsLabel(44, ttl=32),
979 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
980 mpls_tun.add_vpp_config()
981 mpls_tun.admin_up()
982
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000983 def test_v4_exp_null(self):
984 """ MPLS V4 Explicit NULL test """
985
986 #
987 # The first test case has an MPLS TTL of 0
988 # all packet should be dropped
989 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800990 tx = self.create_stream_labelled_ip4(self.pg0,
991 [VppMplsLabel(0, ttl=0)])
992 self.send_and_assert_no_replies(self.pg0, tx,
993 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000994
995 #
996 # a stream with a non-zero MPLS TTL
997 # PG0 is in the default table
998 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800999 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1000 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001001 self.verify_capture_ip4(self.pg0, rx, tx)
1002
1003 #
1004 # a stream with a non-zero MPLS TTL
1005 # PG1 is in table 1
1006 # we are ensuring the post-pop lookup occurs in the VRF table
1007 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001008 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1009 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1010 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001011
1012 def test_v6_exp_null(self):
1013 """ MPLS V6 Explicit NULL test """
1014
1015 #
1016 # a stream with a non-zero MPLS TTL
1017 # PG0 is in the default table
1018 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001019 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1020 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001021 self.verify_capture_ip6(self.pg0, rx, tx)
1022
1023 #
1024 # a stream with a non-zero MPLS TTL
1025 # PG1 is in table 1
1026 # we are ensuring the post-pop lookup occurs in the VRF table
1027 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001028 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1029 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001030 self.verify_capture_ip6(self.pg0, rx, tx)
1031
Neale Rannscb630ff2016-12-14 13:31:29 +01001032 def test_deag(self):
1033 """ MPLS Deagg """
1034
1035 #
1036 # A de-agg route - next-hop lookup in default table
1037 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001038 route_34_eos = VppMplsRoute(self, 34, 1,
1039 [VppRoutePath("0.0.0.0",
1040 0xffffffff,
1041 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001042 route_34_eos.add_vpp_config()
1043
1044 #
1045 # ping an interface in the default table
1046 # PG0 is in the default table
1047 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001048 tx = self.create_stream_labelled_ip4(self.pg0,
1049 [VppMplsLabel(34)],
1050 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001051 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001052 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001053 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1054
1055 #
1056 # A de-agg route - next-hop lookup in non-default table
1057 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001058 route_35_eos = VppMplsRoute(self, 35, 1,
1059 [VppRoutePath("0.0.0.0",
1060 0xffffffff,
1061 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001062 route_35_eos.add_vpp_config()
1063
1064 #
1065 # ping an interface in the non-default table
1066 # PG0 is in the default table. packet arrive labelled in the
1067 # default table and egress unlabelled in the non-default
1068 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001069 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001070 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1071 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001072 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1073
Neale Ranns6af1c042017-05-26 03:48:53 -07001074 #
1075 # Double pop
1076 #
1077 route_36_neos = VppMplsRoute(self, 36, 0,
1078 [VppRoutePath("0.0.0.0",
1079 0xffffffff)])
1080 route_36_neos.add_vpp_config()
1081
Neale Ranns31ed7442018-02-23 05:29:09 -08001082 tx = self.create_stream_labelled_ip4(self.pg0,
1083 [VppMplsLabel(36),
1084 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001085 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001086 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001087 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1088
1089 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001090 route_35_eos.remove_vpp_config()
1091 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001092
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001093 def test_interface_rx(self):
1094 """ MPLS Interface Receive """
1095
1096 #
1097 # Add a non-recursive route that will forward the traffic
1098 # post-interface-rx
1099 #
1100 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1101 table_id=1,
1102 paths=[VppRoutePath(self.pg1.remote_ip4,
1103 self.pg1.sw_if_index)])
1104 route_10_0_0_1.add_vpp_config()
1105
1106 #
1107 # An interface receive label that maps traffic to RX on interface
1108 # pg1
1109 # by injecting the packet in on pg0, which is in table 0
1110 # doing an interface-rx on pg1 and matching a route in table 1
1111 # if the packet egresses, then we must have swapped to pg1
1112 # so as to have matched the route in table 1
1113 #
1114 route_34_eos = VppMplsRoute(self, 34, 1,
1115 [VppRoutePath("0.0.0.0",
1116 self.pg1.sw_if_index,
1117 is_interface_rx=1)])
1118 route_34_eos.add_vpp_config()
1119
1120 #
1121 # ping an interface in the default table
1122 # PG0 is in the default table
1123 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001124 tx = self.create_stream_labelled_ip4(self.pg0,
1125 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001126 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001127 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001128 self.verify_capture_ip4(self.pg1, rx, tx)
1129
1130 def test_mcast_mid_point(self):
1131 """ MPLS Multicast Mid Point """
1132
1133 #
1134 # Add a non-recursive route that will forward the traffic
1135 # post-interface-rx
1136 #
1137 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1138 table_id=1,
1139 paths=[VppRoutePath(self.pg1.remote_ip4,
1140 self.pg1.sw_if_index)])
1141 route_10_0_0_1.add_vpp_config()
1142
1143 #
1144 # Add a mcast entry that replicate to pg2 and pg3
1145 # and replicate to a interface-rx (like a bud node would)
1146 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001147 route_3400_eos = VppMplsRoute(
1148 self, 3400, 1,
1149 [VppRoutePath(self.pg2.remote_ip4,
1150 self.pg2.sw_if_index,
1151 labels=[VppMplsLabel(3401)]),
1152 VppRoutePath(self.pg3.remote_ip4,
1153 self.pg3.sw_if_index,
1154 labels=[VppMplsLabel(3402)]),
1155 VppRoutePath("0.0.0.0",
1156 self.pg1.sw_if_index,
1157 is_interface_rx=1)],
1158 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001159 route_3400_eos.add_vpp_config()
1160
1161 #
1162 # ping an interface in the default table
1163 # PG0 is in the default table
1164 #
1165 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001166 tx = self.create_stream_labelled_ip4(self.pg0,
1167 [VppMplsLabel(3400, ttl=64)],
1168 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001169 dst_ip="10.0.0.1")
1170 self.pg0.add_stream(tx)
1171
1172 self.pg_enable_capture(self.pg_interfaces)
1173 self.pg_start()
1174
1175 rx = self.pg1.get_capture(257)
1176 self.verify_capture_ip4(self.pg1, rx, tx)
1177
1178 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001179 self.verify_capture_labelled(self.pg2, rx, tx,
1180 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001181 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001182 self.verify_capture_labelled(self.pg3, rx, tx,
1183 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001184
1185 def test_mcast_head(self):
1186 """ MPLS Multicast Head-end """
1187
1188 #
1189 # Create a multicast tunnel with two replications
1190 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001191 mpls_tun = VppMPLSTunnelInterface(
1192 self,
1193 [VppRoutePath(self.pg2.remote_ip4,
1194 self.pg2.sw_if_index,
1195 labels=[VppMplsLabel(42)]),
1196 VppRoutePath(self.pg3.remote_ip4,
1197 self.pg3.sw_if_index,
1198 labels=[VppMplsLabel(43)])],
1199 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001200 mpls_tun.add_vpp_config()
1201 mpls_tun.admin_up()
1202
1203 #
1204 # add an unlabelled route through the new tunnel
1205 #
1206 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1207 [VppRoutePath("0.0.0.0",
1208 mpls_tun._sw_if_index)])
1209 route_10_0_0_3.add_vpp_config()
1210
1211 self.vapi.cli("clear trace")
1212 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1213 self.pg0.add_stream(tx)
1214
1215 self.pg_enable_capture(self.pg_interfaces)
1216 self.pg_start()
1217
1218 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001219 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001220 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001221 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001222
1223 #
1224 # An an IP multicast route via the tunnel
1225 # A (*,G).
1226 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1227 #
1228 route_232_1_1_1 = VppIpMRoute(
1229 self,
1230 "0.0.0.0",
1231 "232.1.1.1", 32,
1232 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1233 [VppMRoutePath(self.pg0.sw_if_index,
1234 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1235 VppMRoutePath(mpls_tun._sw_if_index,
1236 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1237 route_232_1_1_1.add_vpp_config()
1238
1239 self.vapi.cli("clear trace")
1240 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1241 self.pg0.add_stream(tx)
1242
1243 self.pg_enable_capture(self.pg_interfaces)
1244 self.pg_start()
1245
1246 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001247 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001248 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001249 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001250
Neale Ranns31426c62017-05-24 10:32:58 -07001251 def test_mcast_ip4_tail(self):
1252 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001253
1254 #
1255 # Add a multicast route that will forward the traffic
1256 # post-disposition
1257 #
1258 route_232_1_1_1 = VppIpMRoute(
1259 self,
1260 "0.0.0.0",
1261 "232.1.1.1", 32,
1262 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1263 table_id=1,
1264 paths=[VppMRoutePath(self.pg1.sw_if_index,
1265 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1266 route_232_1_1_1.add_vpp_config()
1267
1268 #
1269 # An interface receive label that maps traffic to RX on interface
1270 # pg1
1271 # by injecting the packet in on pg0, which is in table 0
1272 # doing an rpf-id and matching a route in table 1
1273 # if the packet egresses, then we must have matched the route in
1274 # table 1
1275 #
1276 route_34_eos = VppMplsRoute(self, 34, 1,
1277 [VppRoutePath("0.0.0.0",
1278 self.pg1.sw_if_index,
1279 nh_table_id=1,
1280 rpf_id=55)],
1281 is_multicast=1)
1282
1283 route_34_eos.add_vpp_config()
1284
1285 #
1286 # Drop due to interface lookup miss
1287 #
1288 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001289 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001290 dst_ip="232.1.1.1", n=1)
1291 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1292
1293 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001294 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001295 #
1296 route_232_1_1_1.update_rpf_id(55)
1297
Neale Ranns31ed7442018-02-23 05:29:09 -08001298 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1299 dst_ip="232.1.1.1")
1300 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001301 self.verify_capture_ip4(self.pg1, rx, tx)
1302
1303 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001304 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001305 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001306 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001307 dst_ip="232.1.1.1", n=65,
1308 chksum=1)
1309 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1310
1311 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001312 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001313 #
1314 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001315 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001316 dst_ip="232.1.1.1")
1317 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1318
Neale Ranns31426c62017-05-24 10:32:58 -07001319 def test_mcast_ip6_tail(self):
1320 """ MPLS IPv6 Multicast Tail """
1321
1322 #
1323 # Add a multicast route that will forward the traffic
1324 # post-disposition
1325 #
1326 route_ff = VppIpMRoute(
1327 self,
1328 "::",
1329 "ff01::1", 32,
1330 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1331 table_id=1,
1332 paths=[VppMRoutePath(self.pg1.sw_if_index,
1333 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1334 is_ip6=1)
1335 route_ff.add_vpp_config()
1336
1337 #
1338 # An interface receive label that maps traffic to RX on interface
1339 # pg1
1340 # by injecting the packet in on pg0, which is in table 0
1341 # doing an rpf-id and matching a route in table 1
1342 # if the packet egresses, then we must have matched the route in
1343 # table 1
1344 #
1345 route_34_eos = VppMplsRoute(
1346 self, 34, 1,
1347 [VppRoutePath("::",
1348 self.pg1.sw_if_index,
1349 nh_table_id=1,
1350 rpf_id=55,
Neale Rannsda78f952017-05-24 09:15:43 -07001351 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns31426c62017-05-24 10:32:58 -07001352 is_multicast=1)
1353
1354 route_34_eos.add_vpp_config()
1355
1356 #
1357 # Drop due to interface lookup miss
1358 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001359 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001360 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001361 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001362
1363 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001364 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001365 #
1366 route_ff.update_rpf_id(55)
1367
Neale Ranns31ed7442018-02-23 05:29:09 -08001368 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001369 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001370 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001371 self.verify_capture_ip6(self.pg1, rx, tx)
1372
1373 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001374 # disposed packets have hop-limit = 1
1375 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001376 tx = self.create_stream_labelled_ip6(self.pg0,
1377 [VppMplsLabel(34)],
1378 dst_ip="ff01::1",
1379 hlim=1)
1380 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001381 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001382
1383 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001384 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001385 #
1386 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001387 tx = self.create_stream_labelled_ip6(self.pg0,
1388 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001389 dst_ip="ff01::1")
1390 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1391
Neale Ranns180279b2017-03-16 15:49:09 -04001392
1393class TestMPLSDisabled(VppTestCase):
1394 """ MPLS disabled """
1395
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001396 @classmethod
1397 def setUpClass(cls):
1398 super(TestMPLSDisabled, cls).setUpClass()
1399
1400 @classmethod
1401 def tearDownClass(cls):
1402 super(TestMPLSDisabled, cls).tearDownClass()
1403
Neale Ranns180279b2017-03-16 15:49:09 -04001404 def setUp(self):
1405 super(TestMPLSDisabled, self).setUp()
1406
1407 # create 2 pg interfaces
1408 self.create_pg_interfaces(range(2))
1409
Neale Ranns15002542017-09-10 04:39:11 -07001410 self.tbl = VppMplsTable(self, 0)
1411 self.tbl.add_vpp_config()
1412
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001413 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001414 self.pg0.admin_up()
1415 self.pg0.config_ip4()
1416 self.pg0.resolve_arp()
1417 self.pg0.enable_mpls()
1418
1419 # PG 1 is not MPLS enabled
1420 self.pg1.admin_up()
1421
1422 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001423 for i in self.pg_interfaces:
1424 i.unconfig_ip4()
1425 i.admin_down()
1426
Neale Ranns15002542017-09-10 04:39:11 -07001427 self.pg0.disable_mpls()
1428 super(TestMPLSDisabled, self).tearDown()
1429
Neale Ranns180279b2017-03-16 15:49:09 -04001430 def test_mpls_disabled(self):
1431 """ MPLS Disabled """
1432
1433 tx = (Ether(src=self.pg1.remote_mac,
1434 dst=self.pg1.local_mac) /
1435 MPLS(label=32, ttl=64) /
1436 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1437 UDP(sport=1234, dport=1234) /
1438 Raw('\xa5' * 100))
1439
1440 #
1441 # A simple MPLS xconnect - eos label in label out
1442 #
1443 route_32_eos = VppMplsRoute(self, 32, 1,
1444 [VppRoutePath(self.pg0.remote_ip4,
1445 self.pg0.sw_if_index,
1446 labels=[33])])
1447 route_32_eos.add_vpp_config()
1448
1449 #
1450 # PG1 does not forward IP traffic
1451 #
1452 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1453
1454 #
1455 # MPLS enable PG1
1456 #
1457 self.pg1.enable_mpls()
1458
1459 #
1460 # Now we get packets through
1461 #
1462 self.pg1.add_stream(tx)
1463 self.pg_enable_capture(self.pg_interfaces)
1464 self.pg_start()
1465
1466 rx = self.pg0.get_capture(1)
1467
1468 #
1469 # Disable PG1
1470 #
1471 self.pg1.disable_mpls()
1472
1473 #
1474 # PG1 does not forward IP traffic
1475 #
1476 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1477 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1478
1479
Neale Rannsf12a83f2017-04-18 09:09:40 -07001480class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001481 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001482
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001483 @classmethod
1484 def setUpClass(cls):
1485 super(TestMPLSPIC, cls).setUpClass()
1486
1487 @classmethod
1488 def tearDownClass(cls):
1489 super(TestMPLSPIC, cls).tearDownClass()
1490
Neale Rannsf12a83f2017-04-18 09:09:40 -07001491 def setUp(self):
1492 super(TestMPLSPIC, self).setUp()
1493
1494 # create 2 pg interfaces
1495 self.create_pg_interfaces(range(4))
1496
Neale Ranns15002542017-09-10 04:39:11 -07001497 mpls_tbl = VppMplsTable(self, 0)
1498 mpls_tbl.add_vpp_config()
1499 tbl4 = VppIpTable(self, 1)
1500 tbl4.add_vpp_config()
1501 tbl6 = VppIpTable(self, 1, is_ip6=1)
1502 tbl6.add_vpp_config()
1503
Neale Rannsf12a83f2017-04-18 09:09:40 -07001504 # core links
1505 self.pg0.admin_up()
1506 self.pg0.config_ip4()
1507 self.pg0.resolve_arp()
1508 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001509
Neale Rannsf12a83f2017-04-18 09:09:40 -07001510 self.pg1.admin_up()
1511 self.pg1.config_ip4()
1512 self.pg1.resolve_arp()
1513 self.pg1.enable_mpls()
1514
1515 # VRF (customer facing) link
1516 self.pg2.admin_up()
1517 self.pg2.set_table_ip4(1)
1518 self.pg2.config_ip4()
1519 self.pg2.resolve_arp()
1520 self.pg2.set_table_ip6(1)
1521 self.pg2.config_ip6()
1522 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001523
Neale Rannsf12a83f2017-04-18 09:09:40 -07001524 self.pg3.admin_up()
1525 self.pg3.set_table_ip4(1)
1526 self.pg3.config_ip4()
1527 self.pg3.resolve_arp()
1528 self.pg3.set_table_ip6(1)
1529 self.pg3.config_ip6()
1530 self.pg3.resolve_ndp()
1531
1532 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001533 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001534 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001535 for i in self.pg_interfaces:
1536 i.unconfig_ip4()
1537 i.unconfig_ip6()
1538 i.set_table_ip4(0)
1539 i.set_table_ip6(0)
1540 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001541 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001542
1543 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001544 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001545
1546 1) setup many iBGP VPN routes via a pair of iBGP peers.
1547 2) Check EMCP forwarding to these peers
1548 3) withdraw the IGP route to one of these peers.
1549 4) check forwarding continues to the remaining peer
1550 """
1551
1552 #
1553 # IGP+LDP core routes
1554 #
1555 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1556 [VppRoutePath(self.pg0.remote_ip4,
1557 self.pg0.sw_if_index,
1558 labels=[45])])
1559 core_10_0_0_45.add_vpp_config()
1560
1561 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1562 [VppRoutePath(self.pg1.remote_ip4,
1563 self.pg1.sw_if_index,
1564 labels=[46])])
1565 core_10_0_0_46.add_vpp_config()
1566
1567 #
1568 # Lot's of VPN routes. We need more the 64 so VPP will build
1569 # the fast convergence indirection
1570 #
1571 vpn_routes = []
1572 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001573 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001574 dst = "192.168.1.%d" % ii
1575 vpn_routes.append(VppIpRoute(self, dst, 32,
1576 [VppRoutePath("10.0.0.45",
1577 0xffffffff,
1578 labels=[145],
1579 is_resolve_host=1),
1580 VppRoutePath("10.0.0.46",
1581 0xffffffff,
1582 labels=[146],
1583 is_resolve_host=1)],
1584 table_id=1))
1585 vpn_routes[ii].add_vpp_config()
1586
1587 pkts.append(Ether(dst=self.pg2.local_mac,
1588 src=self.pg2.remote_mac) /
1589 IP(src=self.pg2.remote_ip4, dst=dst) /
1590 UDP(sport=1234, dport=1234) /
1591 Raw('\xa5' * 100))
1592
1593 #
1594 # Send the packet stream (one pkt to each VPN route)
1595 # - expect a 50-50 split of the traffic
1596 #
1597 self.pg2.add_stream(pkts)
1598 self.pg_enable_capture(self.pg_interfaces)
1599 self.pg_start()
1600
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001601 rx0 = self.pg0._get_capture(NUM_PKTS)
1602 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001603
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001604 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001605 # with the split ratio, just as long as neither is 0
1606 self.assertNotEqual(0, len(rx0))
1607 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001608 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1609 "Expected all (%s) packets across both ECMP paths. "
1610 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001611
1612 #
1613 # use a test CLI command to stop the FIB walk process, this
1614 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001615 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001616 #
1617 self.vapi.ppcli("test fib-walk-process disable")
1618
1619 #
1620 # Withdraw one of the IGP routes
1621 #
1622 core_10_0_0_46.remove_vpp_config()
1623
1624 #
1625 # now all packets should be forwarded through the remaining peer
1626 #
1627 self.vapi.ppcli("clear trace")
1628 self.pg2.add_stream(pkts)
1629 self.pg_enable_capture(self.pg_interfaces)
1630 self.pg_start()
1631
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001632 rx0 = self.pg0.get_capture(NUM_PKTS)
1633 self.assertEqual(len(pkts), len(rx0),
1634 "Expected all (%s) packets across single path. "
1635 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001636
1637 #
1638 # enable the FIB walk process to converge the FIB
1639 #
1640 self.vapi.ppcli("test fib-walk-process enable")
1641
1642 #
1643 # packets should still be forwarded through the remaining peer
1644 #
1645 self.pg2.add_stream(pkts)
1646 self.pg_enable_capture(self.pg_interfaces)
1647 self.pg_start()
1648
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001649 rx0 = self.pg0.get_capture(NUM_PKTS)
1650 self.assertEqual(len(pkts), len(rx0),
1651 "Expected all (%s) packets across single path. "
1652 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001653
1654 #
1655 # Add the IGP route back and we return to load-balancing
1656 #
1657 core_10_0_0_46.add_vpp_config()
1658
1659 self.pg2.add_stream(pkts)
1660 self.pg_enable_capture(self.pg_interfaces)
1661 self.pg_start()
1662
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001663 rx0 = self.pg0._get_capture(NUM_PKTS)
1664 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001665 self.assertNotEqual(0, len(rx0))
1666 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001667 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1668 "Expected all (%s) packets across both ECMP paths. "
1669 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001670
1671 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001672 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001673
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001674 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001675 2) Check EMCP forwarding to these peers
1676 3) withdraw one eBGP path - expect LB across remaining eBGP
1677 """
1678
1679 #
1680 # Lot's of VPN routes. We need more the 64 so VPP will build
1681 # the fast convergence indirection
1682 #
1683 vpn_routes = []
1684 vpn_bindings = []
1685 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001686 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001687 dst = "192.168.1.%d" % ii
1688 local_label = 1600 + ii
1689 vpn_routes.append(VppIpRoute(self, dst, 32,
1690 [VppRoutePath(self.pg2.remote_ip4,
1691 0xffffffff,
1692 nh_table_id=1,
1693 is_resolve_attached=1),
1694 VppRoutePath(self.pg3.remote_ip4,
1695 0xffffffff,
1696 nh_table_id=1,
1697 is_resolve_attached=1)],
1698 table_id=1))
1699 vpn_routes[ii].add_vpp_config()
1700
1701 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1702 ip_table_id=1))
1703 vpn_bindings[ii].add_vpp_config()
1704
1705 pkts.append(Ether(dst=self.pg0.local_mac,
1706 src=self.pg0.remote_mac) /
1707 MPLS(label=local_label, ttl=64) /
1708 IP(src=self.pg0.remote_ip4, dst=dst) /
1709 UDP(sport=1234, dport=1234) /
1710 Raw('\xa5' * 100))
1711
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001712 #
1713 # Send the packet stream (one pkt to each VPN route)
1714 # - expect a 50-50 split of the traffic
1715 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001716 self.pg0.add_stream(pkts)
1717 self.pg_enable_capture(self.pg_interfaces)
1718 self.pg_start()
1719
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001720 rx0 = self.pg2._get_capture(NUM_PKTS)
1721 rx1 = self.pg3._get_capture(NUM_PKTS)
1722
1723 # not testing the LB hashing algorithm so we're not concerned
1724 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001725 self.assertNotEqual(0, len(rx0))
1726 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001727 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1728 "Expected all (%s) packets across both ECMP paths. "
1729 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001730
1731 #
1732 # use a test CLI command to stop the FIB walk process, this
1733 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001734 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001735 #
1736 self.vapi.ppcli("test fib-walk-process disable")
1737
1738 #
1739 # withdraw the connected prefix on the interface.
1740 #
1741 self.pg2.unconfig_ip4()
1742
1743 #
1744 # now all packets should be forwarded through the remaining peer
1745 #
1746 self.pg0.add_stream(pkts)
1747 self.pg_enable_capture(self.pg_interfaces)
1748 self.pg_start()
1749
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001750 rx0 = self.pg3.get_capture(NUM_PKTS)
1751 self.assertEqual(len(pkts), len(rx0),
1752 "Expected all (%s) packets across single path. "
1753 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001754
1755 #
1756 # enable the FIB walk process to converge the FIB
1757 #
1758 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001759
1760 #
1761 # packets should still be forwarded through the remaining peer
1762 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001763 self.pg0.add_stream(pkts)
1764 self.pg_enable_capture(self.pg_interfaces)
1765 self.pg_start()
1766
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001767 rx0 = self.pg3.get_capture(NUM_PKTS)
1768 self.assertEqual(len(pkts), len(rx0),
1769 "Expected all (%s) packets across single path. "
1770 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001771
1772 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001773 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001774 #
1775 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001776 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001777
1778 self.pg0.add_stream(pkts)
1779 self.pg_enable_capture(self.pg_interfaces)
1780 self.pg_start()
1781
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001782 rx0 = self.pg2._get_capture(NUM_PKTS)
1783 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001784 self.assertNotEqual(0, len(rx0))
1785 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001786 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1787 "Expected all (%s) packets across both ECMP paths. "
1788 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001789
1790 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001791 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001792
1793 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1794 2) Check EMCP forwarding to these peers
1795 3) withdraw one eBGP path - expect LB across remaining eBGP
1796 """
1797
1798 #
1799 # Lot's of VPN routes. We need more the 64 so VPP will build
1800 # the fast convergence indirection
1801 #
1802 vpn_routes = []
1803 vpn_bindings = []
1804 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001805 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001806 dst = "3000::%d" % ii
1807 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001808 vpn_routes.append(VppIpRoute(
1809 self, dst, 128,
1810 [VppRoutePath(self.pg2.remote_ip6,
1811 0xffffffff,
1812 nh_table_id=1,
1813 is_resolve_attached=1,
1814 proto=DpoProto.DPO_PROTO_IP6),
1815 VppRoutePath(self.pg3.remote_ip6,
1816 0xffffffff,
1817 nh_table_id=1,
1818 proto=DpoProto.DPO_PROTO_IP6,
1819 is_resolve_attached=1)],
1820 table_id=1,
1821 is_ip6=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001822 vpn_routes[ii].add_vpp_config()
1823
1824 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1825 ip_table_id=1,
1826 is_ip6=1))
1827 vpn_bindings[ii].add_vpp_config()
1828
1829 pkts.append(Ether(dst=self.pg0.local_mac,
1830 src=self.pg0.remote_mac) /
1831 MPLS(label=local_label, ttl=64) /
1832 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1833 UDP(sport=1234, dport=1234) /
1834 Raw('\xa5' * 100))
1835
1836 self.pg0.add_stream(pkts)
1837 self.pg_enable_capture(self.pg_interfaces)
1838 self.pg_start()
1839
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001840 rx0 = self.pg2._get_capture(NUM_PKTS)
1841 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001842 self.assertNotEqual(0, len(rx0))
1843 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001844 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1845 "Expected all (%s) packets across both ECMP paths. "
1846 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001847
1848 #
1849 # use a test CLI command to stop the FIB walk process, this
1850 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001851 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001852 #
1853 self.vapi.ppcli("test fib-walk-process disable")
1854
1855 #
1856 # withdraw the connected prefix on the interface.
1857 # and shutdown the interface so the ND cache is flushed.
1858 #
1859 self.pg2.unconfig_ip6()
1860 self.pg2.admin_down()
1861
1862 #
1863 # now all packets should be forwarded through the remaining peer
1864 #
1865 self.pg0.add_stream(pkts)
1866 self.pg_enable_capture(self.pg_interfaces)
1867 self.pg_start()
1868
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001869 rx0 = self.pg3.get_capture(NUM_PKTS)
1870 self.assertEqual(len(pkts), len(rx0),
1871 "Expected all (%s) packets across single path. "
1872 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001873
1874 #
1875 # enable the FIB walk process to converge the FIB
1876 #
1877 self.vapi.ppcli("test fib-walk-process enable")
1878 self.pg0.add_stream(pkts)
1879 self.pg_enable_capture(self.pg_interfaces)
1880 self.pg_start()
1881
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001882 rx0 = self.pg3.get_capture(NUM_PKTS)
1883 self.assertEqual(len(pkts), len(rx0),
1884 "Expected all (%s) packets across single path. "
1885 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001886
1887 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001888 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001889 #
1890 self.pg2.admin_up()
1891 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001892 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001893
1894 self.pg0.add_stream(pkts)
1895 self.pg_enable_capture(self.pg_interfaces)
1896 self.pg_start()
1897
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001898 rx0 = self.pg2._get_capture(NUM_PKTS)
1899 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001900 self.assertNotEqual(0, len(rx0))
1901 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001902 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1903 "Expected all (%s) packets across both ECMP paths. "
1904 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001905
1906
Neale Rannsda78f952017-05-24 09:15:43 -07001907class TestMPLSL2(VppTestCase):
1908 """ MPLS-L2 """
1909
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001910 @classmethod
1911 def setUpClass(cls):
1912 super(TestMPLSL2, cls).setUpClass()
1913
1914 @classmethod
1915 def tearDownClass(cls):
1916 super(TestMPLSL2, cls).tearDownClass()
1917
Neale Rannsda78f952017-05-24 09:15:43 -07001918 def setUp(self):
1919 super(TestMPLSL2, self).setUp()
1920
1921 # create 2 pg interfaces
1922 self.create_pg_interfaces(range(2))
1923
Neale Ranns15002542017-09-10 04:39:11 -07001924 # create the default MPLS table
1925 self.tables = []
1926 tbl = VppMplsTable(self, 0)
1927 tbl.add_vpp_config()
1928 self.tables.append(tbl)
1929
Neale Rannsda78f952017-05-24 09:15:43 -07001930 # use pg0 as the core facing interface
1931 self.pg0.admin_up()
1932 self.pg0.config_ip4()
1933 self.pg0.resolve_arp()
1934 self.pg0.enable_mpls()
1935
Neale Ranns15002542017-09-10 04:39:11 -07001936 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07001937 for i in self.pg_interfaces[1:]:
1938 i.admin_up()
1939
1940 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07001941 for i in self.pg_interfaces[1:]:
1942 i.admin_down()
1943
1944 self.pg0.disable_mpls()
1945 self.pg0.unconfig_ip4()
1946 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001947 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07001948
Neale Ranns31ed7442018-02-23 05:29:09 -08001949 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07001950 capture = verify_filter(capture, sent)
1951
1952 self.assertEqual(len(capture), len(sent))
1953
1954 for i in range(len(capture)):
1955 tx = sent[i]
1956 rx = capture[i]
1957
1958 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08001959 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07001960
1961 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001962 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07001963
1964 self.assertEqual(rx_eth.src, tx_eth.src)
1965 self.assertEqual(rx_eth.dst, tx_eth.dst)
1966
1967 def test_vpws(self):
1968 """ Virtual Private Wire Service """
1969
1970 #
1971 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08001972 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
1973 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07001974 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001975 mpls_tun_1 = VppMPLSTunnelInterface(
1976 self,
1977 [VppRoutePath(self.pg0.remote_ip4,
1978 self.pg0.sw_if_index,
1979 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
1980 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07001981 mpls_tun_1.add_vpp_config()
1982 mpls_tun_1.admin_up()
1983
1984 #
1985 # Create a label entry to for 55 that does L2 input to the tunnel
1986 #
1987 route_55_eos = VppMplsRoute(
1988 self, 55, 1,
1989 [VppRoutePath("0.0.0.0",
1990 mpls_tun_1.sw_if_index,
1991 is_interface_rx=1,
1992 proto=DpoProto.DPO_PROTO_ETHERNET)])
1993 route_55_eos.add_vpp_config()
1994
1995 #
1996 # Cross-connect the tunnel with one of the customers L2 interfaces
1997 #
1998 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1999 mpls_tun_1.sw_if_index,
2000 enable=1)
2001 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2002 self.pg1.sw_if_index,
2003 enable=1)
2004
2005 #
2006 # inject a packet from the core
2007 #
2008 pcore = (Ether(dst=self.pg0.local_mac,
2009 src=self.pg0.remote_mac) /
2010 MPLS(label=55, ttl=64) /
2011 Ether(dst="00:00:de:ad:ba:be",
2012 src="00:00:de:ad:be:ef") /
2013 IP(src="10.10.10.10", dst="11.11.11.11") /
2014 UDP(sport=1234, dport=1234) /
2015 Raw('\xa5' * 100))
2016
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002017 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002018 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2019 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002020
Neale Ranns31ed7442018-02-23 05:29:09 -08002021 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2022 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002023
2024 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002025 # Inject a packet from the customer/L2 side
Neale Rannsda78f952017-05-24 09:15:43 -07002026 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002027 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002028 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002029
Neale Ranns31ed7442018-02-23 05:29:09 -08002030 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002031
2032 def test_vpls(self):
2033 """ Virtual Private LAN Service """
2034 #
2035 # Create an L2 MPLS tunnel
2036 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002037 mpls_tun = VppMPLSTunnelInterface(
2038 self,
2039 [VppRoutePath(self.pg0.remote_ip4,
2040 self.pg0.sw_if_index,
2041 labels=[VppMplsLabel(42)])],
2042 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002043 mpls_tun.add_vpp_config()
2044 mpls_tun.admin_up()
2045
2046 #
2047 # Create a label entry to for 55 that does L2 input to the tunnel
2048 #
2049 route_55_eos = VppMplsRoute(
2050 self, 55, 1,
2051 [VppRoutePath("0.0.0.0",
2052 mpls_tun.sw_if_index,
2053 is_interface_rx=1,
2054 proto=DpoProto.DPO_PROTO_ETHERNET)])
2055 route_55_eos.add_vpp_config()
2056
2057 #
2058 # add to tunnel to the customers bridge-domain
2059 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002060 self.vapi.sw_interface_set_l2_bridge(
2061 rx_sw_if_index=mpls_tun.sw_if_index, bd_id=1)
2062 self.vapi.sw_interface_set_l2_bridge(
2063 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002064
2065 #
2066 # Packet from the customer interface and from the core
2067 #
2068 p_cust = (Ether(dst="00:00:de:ad:ba:be",
2069 src="00:00:de:ad:be:ef") /
2070 IP(src="10.10.10.10", dst="11.11.11.11") /
2071 UDP(sport=1234, dport=1234) /
2072 Raw('\xa5' * 100))
2073 p_core = (Ether(src="00:00:de:ad:ba:be",
2074 dst="00:00:de:ad:be:ef") /
2075 IP(dst="10.10.10.10", src="11.11.11.11") /
2076 UDP(sport=1234, dport=1234) /
2077 Raw('\xa5' * 100))
2078
2079 #
2080 # The BD is learning, so send in one of each packet to learn
2081 #
2082 p_core_encap = (Ether(dst=self.pg0.local_mac,
2083 src=self.pg0.remote_mac) /
2084 MPLS(label=55, ttl=64) /
2085 p_core)
2086
2087 self.pg1.add_stream(p_cust)
2088 self.pg_enable_capture(self.pg_interfaces)
2089 self.pg_start()
2090 self.pg0.add_stream(p_core_encap)
2091 self.pg_enable_capture(self.pg_interfaces)
2092 self.pg_start()
2093
2094 # we've learnt this so expect it be be forwarded
2095 rx0 = self.pg1.get_capture(1)
2096
2097 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
2098 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
2099
2100 #
2101 # now a stream in each direction
2102 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002103 self.pg1.add_stream(p_cust * NUM_PKTS)
Neale Rannsda78f952017-05-24 09:15:43 -07002104 self.pg_enable_capture(self.pg_interfaces)
2105 self.pg_start()
2106
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002107 rx0 = self.pg0.get_capture(NUM_PKTS)
Neale Rannsda78f952017-05-24 09:15:43 -07002108
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002109 self.verify_capture_tunneled_ethernet(rx0, p_cust*NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002110 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002111
2112 #
2113 # remove interfaces from customers bridge-domain
2114 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002115 self.vapi.sw_interface_set_l2_bridge(
2116 rx_sw_if_index=mpls_tun.sw_if_index, bd_id=1, enable=0)
2117 self.vapi.sw_interface_set_l2_bridge(
2118 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002119
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002120
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002121if __name__ == '__main__':
2122 unittest.main(testRunner=VppTestRunner)