blob: d068bc37ee231de539419cea6db0928ec7dcfa71 [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 Ranns097fa662018-05-01 05:17:55 -070011 VppMplsLabel, MplsLspMode, find_mpls_route, \
12 FibPathProto, FibPathType, FibPathFlags, VppMplsLabel, MplsLspMode
Neale Ranns0f26c5a2017-03-01 15:12:11 -080013from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns8fe8cc22016-11-01 10:05:08 +000014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010017from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010018from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070019from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000020from scapy.contrib.mpls import MPLS
21
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040022NUM_PKTS = 67
23
Klement Sekeradab231a2016-12-21 08:50:14 +010024
Neale Rannsda78f952017-05-24 09:15:43 -070025def verify_filter(capture, sent):
26 if not len(capture) == len(sent):
27 # filter out any IPv6 RAs from the capture
28 for p in capture:
29 if p.haslayer(IPv6):
30 capture.remove(p)
31 return capture
32
33
Neale Ranns31ed7442018-02-23 05:29:09 -080034def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070035 # the rx'd packet has the MPLS label popped
36 eth = rx[Ether]
37 tst.assertEqual(eth.type, 0x8847)
38
39 rx_mpls = rx[MPLS]
40
41 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080042 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
43 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
44 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
45
Neale Rannsda78f952017-05-24 09:15:43 -070046 if ii == len(mpls_labels) - 1:
47 tst.assertEqual(rx_mpls.s, 1)
48 else:
49 # not end of stack
50 tst.assertEqual(rx_mpls.s, 0)
51 # pop the label to expose the next
52 rx_mpls = rx_mpls[MPLS].payload
53
54
Neale Ranns8fe8cc22016-11-01 10:05:08 +000055class TestMPLS(VppTestCase):
56 """ MPLS Test Case """
57
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070058 @classmethod
59 def setUpClass(cls):
60 super(TestMPLS, cls).setUpClass()
61
62 @classmethod
63 def tearDownClass(cls):
64 super(TestMPLS, cls).tearDownClass()
65
Neale Ranns8fe8cc22016-11-01 10:05:08 +000066 def setUp(self):
67 super(TestMPLS, self).setUp()
68
69 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080070 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000071
72 # setup both interfaces
73 # assign them different tables.
74 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070075 self.tables = []
76
77 tbl = VppMplsTable(self, 0)
78 tbl.add_vpp_config()
79 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000080
81 for i in self.pg_interfaces:
82 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070083
84 if table_id != 0:
85 tbl = VppIpTable(self, table_id)
86 tbl.add_vpp_config()
87 self.tables.append(tbl)
88 tbl = VppIpTable(self, table_id, is_ip6=1)
89 tbl.add_vpp_config()
90 self.tables.append(tbl)
91
Neale Ranns8fe8cc22016-11-01 10:05:08 +000092 i.set_table_ip4(table_id)
93 i.set_table_ip6(table_id)
94 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000095 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000096 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000097 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000098 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000099 table_id += 1
100
101 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800102 for i in self.pg_interfaces:
103 i.unconfig_ip4()
104 i.unconfig_ip6()
105 i.ip6_disable()
Neale Ranns15002542017-09-10 04:39:11 -0700106 i.set_table_ip4(0)
107 i.set_table_ip6(0)
108 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800109 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700110 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000111
Neale Rannsad422ed2016-11-02 14:20:04 +0000112 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100113 def create_stream_labelled_ip4(
114 self,
115 src_if,
116 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100117 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800118 ip_itf=None,
119 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700120 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800121 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800122 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100123 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000124 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800125 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100126 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000127 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000128 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
129
130 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800131 p = p / MPLS(label=mpls_labels[ii].value,
132 ttl=mpls_labels[ii].ttl,
133 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100134 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800135 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800136 p = (p / IP(src=src_if.local_ip4,
137 dst=src_if.remote_ip4,
138 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800139 UDP(sport=1234, dport=1234) /
140 Raw(payload))
141 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800142 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800143 UDP(sport=1234, dport=1234) /
144 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100145 else:
146 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800147 dst=ip_itf.local_ip4,
148 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100149 ICMP())
150
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700151 if chksum:
152 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000153 info.data = p.copy()
154 pkts.append(p)
155 return pkts
156
Neale Ranns31ed7442018-02-23 05:29:09 -0800157 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
Klement Sekeradab231a2016-12-21 08:50:14 +0100158 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000159 pkts = []
160 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100161 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000162 payload = self.info_to_payload(info)
163 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800164 IP(src=src_if.remote_ip4, dst=dst_ip,
165 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000166 UDP(sport=1234, dport=1234) /
167 Raw(payload))
168 info.data = p.copy()
169 pkts.append(p)
170 return pkts
171
Neale Ranns31ed7442018-02-23 05:29:09 -0800172 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
173 self.reset_packet_infos()
174 pkts = []
175 for i in range(0, 257):
176 info = self.create_packet_info(src_if, src_if)
177 payload = self.info_to_payload(info)
178 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
179 IPv6(src=src_if.remote_ip6, dst=dst_ip,
180 hlim=ip_ttl, tc=ip_dscp) /
181 UDP(sport=1234, dport=1234) /
182 Raw(payload))
183 info.data = p.copy()
184 pkts.append(p)
185 return pkts
186
187 def create_stream_labelled_ip6(self, src_if, mpls_labels,
188 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700189 if dst_ip is None:
190 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100191 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000192 pkts = []
193 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100194 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000195 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800196 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
197 for l in mpls_labels:
198 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
199
200 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
201 UDP(sport=1234, dport=1234) /
202 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000203 info.data = p.copy()
204 pkts.append(p)
205 return pkts
206
Neale Ranns31ed7442018-02-23 05:29:09 -0800207 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
208 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000209 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700210 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000211
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000212 self.assertEqual(len(capture), len(sent))
213
214 for i in range(len(capture)):
215 tx = sent[i]
216 rx = capture[i]
217
218 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000219 eth = rx[Ether]
220 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000221
222 tx_ip = tx[IP]
223 rx_ip = rx[IP]
224
Neale Rannscb630ff2016-12-14 13:31:29 +0100225 if not ping_resp:
226 self.assertEqual(rx_ip.src, tx_ip.src)
227 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800228 self.assertEqual(rx_ip.tos, ip_dscp)
229 if not ip_ttl:
230 # IP processing post pop has decremented the TTL
231 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
232 else:
233 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100234 else:
235 self.assertEqual(rx_ip.src, tx_ip.dst)
236 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000237
238 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000239 raise
240
Neale Rannsad422ed2016-11-02 14:20:04 +0000241 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800242 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000243 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700244 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000245
246 self.assertEqual(len(capture), len(sent))
247
248 for i in range(len(capture)):
249 tx = sent[i]
250 rx = capture[i]
251 tx_ip = tx[IP]
252 rx_ip = rx[IP]
253
Neale Ranns31ed7442018-02-23 05:29:09 -0800254 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000255
256 self.assertEqual(rx_ip.src, tx_ip.src)
257 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800258 if not ip_ttl:
259 # IP processing post pop has decremented the TTL
260 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
261 else:
262 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000263
264 except:
265 raise
266
Neale Ranns31ed7442018-02-23 05:29:09 -0800267 def verify_capture_labelled_ip6(self, src_if, capture, sent,
268 mpls_labels, ip_ttl=None):
269 try:
270 capture = verify_filter(capture, sent)
271
272 self.assertEqual(len(capture), len(sent))
273
274 for i in range(len(capture)):
275 tx = sent[i]
276 rx = capture[i]
277 tx_ip = tx[IPv6]
278 rx_ip = rx[IPv6]
279
280 verify_mpls_stack(self, rx, mpls_labels)
281
282 self.assertEqual(rx_ip.src, tx_ip.src)
283 self.assertEqual(rx_ip.dst, tx_ip.dst)
284 if not ip_ttl:
285 # IP processing post pop has decremented the TTL
286 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
287 else:
288 self.assertEqual(rx_ip.hlim, ip_ttl)
289
290 except:
291 raise
292
293 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700295 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000296
297 self.assertEqual(len(capture), len(sent))
298
299 for i in range(len(capture)):
300 tx = sent[i]
301 rx = capture[i]
302 tx_ip = tx[IP]
303 rx_ip = rx[IP]
304
Neale Ranns31ed7442018-02-23 05:29:09 -0800305 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000306
307 self.assertEqual(rx_ip.src, tx_ip.src)
308 self.assertEqual(rx_ip.dst, tx_ip.dst)
309 # IP processing post pop has decremented the TTL
310 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
311
312 except:
313 raise
314
315 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800316 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000317 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700318 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000319
320 self.assertEqual(len(capture), len(sent))
321
322 for i in range(len(capture)):
323 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800324 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000325 except:
326 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000327
Neale Ranns31ed7442018-02-23 05:29:09 -0800328 def verify_capture_ip6(self, src_if, capture, sent,
329 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000330 try:
331 self.assertEqual(len(capture), len(sent))
332
333 for i in range(len(capture)):
334 tx = sent[i]
335 rx = capture[i]
336
337 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000338 eth = rx[Ether]
339 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000340
341 tx_ip = tx[IPv6]
342 rx_ip = rx[IPv6]
343
344 self.assertEqual(rx_ip.src, tx_ip.src)
345 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800346 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000347 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800348 if not ip_hlim:
349 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
350 else:
351 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000352
353 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000354 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000355
Neale Ranns62fe07c2017-10-31 12:28:22 -0700356 def verify_capture_ip6_icmp(self, src_if, capture, sent):
357 try:
358 self.assertEqual(len(capture), len(sent))
359
360 for i in range(len(capture)):
361 tx = sent[i]
362 rx = capture[i]
363
364 # the rx'd packet has the MPLS label popped
365 eth = rx[Ether]
366 self.assertEqual(eth.type, 0x86DD)
367
368 tx_ip = tx[IPv6]
369 rx_ip = rx[IPv6]
370
371 self.assertEqual(rx_ip.dst, tx_ip.src)
372 # ICMP sourced from the interface's address
373 self.assertEqual(rx_ip.src, src_if.local_ip6)
374 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200375 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700376
377 icmp = rx[ICMPv6TimeExceeded]
378
379 except:
380 raise
381
Neale Rannsad422ed2016-11-02 14:20:04 +0000382 def test_swap(self):
383 """ MPLS label swap tests """
384
385 #
386 # A simple MPLS xconnect - eos label in label out
387 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800388 route_32_eos = VppMplsRoute(self, 32, 1,
389 [VppRoutePath(self.pg0.remote_ip4,
390 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800391 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000392 route_32_eos.add_vpp_config()
393
Neale Ranns775f73c2018-12-20 03:01:49 -0800394 self.assertTrue(
395 find_mpls_route(self, 0, 32, 1,
396 [VppRoutePath(self.pg0.remote_ip4,
397 self.pg0.sw_if_index,
398 labels=[VppMplsLabel(33)])]))
399
Neale Rannsad422ed2016-11-02 14:20:04 +0000400 #
401 # a stream that matches the route for 10.0.0.1
402 # PG0 is in the default table
403 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800404 tx = self.create_stream_labelled_ip4(self.pg0,
405 [VppMplsLabel(32, ttl=32, exp=1)])
406 rx = self.send_and_expect(self.pg0, tx, self.pg0)
407 self.verify_capture_labelled(self.pg0, rx, tx,
408 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000409
Neale Ranns008dbe12018-09-07 09:32:36 -0700410 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
411
Neale Rannsad422ed2016-11-02 14:20:04 +0000412 #
413 # A simple MPLS xconnect - non-eos label in label out
414 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800415 route_32_neos = VppMplsRoute(self, 32, 0,
416 [VppRoutePath(self.pg0.remote_ip4,
417 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800418 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000419 route_32_neos.add_vpp_config()
420
421 #
422 # a stream that matches the route for 10.0.0.1
423 # PG0 is in the default table
424 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800425 tx = self.create_stream_labelled_ip4(self.pg0,
426 [VppMplsLabel(32, ttl=21, exp=7),
427 VppMplsLabel(99)])
428 rx = self.send_and_expect(self.pg0, tx, self.pg0)
429 self.verify_capture_labelled(self.pg0, rx, tx,
430 [VppMplsLabel(33, ttl=20, exp=7),
431 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700432 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000433
Neale Ranns31ed7442018-02-23 05:29:09 -0800434 #
435 # A simple MPLS xconnect - non-eos label in label out, uniform mode
436 #
437 route_42_neos = VppMplsRoute(
438 self, 42, 0,
439 [VppRoutePath(self.pg0.remote_ip4,
440 self.pg0.sw_if_index,
441 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
442 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000443
Neale Ranns31ed7442018-02-23 05:29:09 -0800444 tx = self.create_stream_labelled_ip4(self.pg0,
445 [VppMplsLabel(42, ttl=21, exp=7),
446 VppMplsLabel(99)])
447 rx = self.send_and_expect(self.pg0, tx, self.pg0)
448 self.verify_capture_labelled(self.pg0, rx, tx,
449 [VppMplsLabel(43, ttl=20, exp=7),
450 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000451
452 #
453 # An MPLS xconnect - EOS label in IP out
454 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800455 route_33_eos = VppMplsRoute(self, 33, 1,
456 [VppRoutePath(self.pg0.remote_ip4,
457 self.pg0.sw_if_index,
458 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000459 route_33_eos.add_vpp_config()
460
Neale Ranns31ed7442018-02-23 05:29:09 -0800461 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
462 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000463 self.verify_capture_ip4(self.pg0, rx, tx)
464
465 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700466 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700467 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800468 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700469 dst_ip=self.pg0.remote_ip4,
470 n=65,
471 chksum=1)
472 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
473
474 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800475 # An MPLS xconnect - EOS label in IP out, uniform mode
476 #
477 route_3333_eos = VppMplsRoute(
478 self, 3333, 1,
479 [VppRoutePath(self.pg0.remote_ip4,
480 self.pg0.sw_if_index,
481 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
482 route_3333_eos.add_vpp_config()
483
484 tx = self.create_stream_labelled_ip4(
485 self.pg0,
486 [VppMplsLabel(3333, ttl=55, exp=3)])
487 rx = self.send_and_expect(self.pg0, tx, self.pg0)
488 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
489 tx = self.create_stream_labelled_ip4(
490 self.pg0,
491 [VppMplsLabel(3333, ttl=66, exp=4)])
492 rx = self.send_and_expect(self.pg0, tx, self.pg0)
493 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
494
495 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700496 # An MPLS xconnect - EOS label in IPv6 out
497 #
498 route_333_eos = VppMplsRoute(
499 self, 333, 1,
500 [VppRoutePath(self.pg0.remote_ip6,
501 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700502 labels=[])],
503 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700504 route_333_eos.add_vpp_config()
505
Neale Ranns31ed7442018-02-23 05:29:09 -0800506 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
507 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700508 self.verify_capture_ip6(self.pg0, rx, tx)
509
510 #
511 # disposed packets have an TTL expired
512 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800513 tx = self.create_stream_labelled_ip6(self.pg0,
514 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700515 dst_ip=self.pg1.remote_ip6,
516 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800517 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700518 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
519
520 #
521 # An MPLS xconnect - EOS label in IPv6 out w imp-null
522 #
523 route_334_eos = VppMplsRoute(
524 self, 334, 1,
525 [VppRoutePath(self.pg0.remote_ip6,
526 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700527 labels=[VppMplsLabel(3)])],
528 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700529 route_334_eos.add_vpp_config()
530
Neale Ranns31ed7442018-02-23 05:29:09 -0800531 tx = self.create_stream_labelled_ip6(self.pg0,
532 [VppMplsLabel(334, ttl=64)])
533 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700534 self.verify_capture_ip6(self.pg0, rx, tx)
535
536 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800537 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
538 #
539 route_335_eos = VppMplsRoute(
540 self, 335, 1,
541 [VppRoutePath(self.pg0.remote_ip6,
542 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700543 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
544 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800545 route_335_eos.add_vpp_config()
546
547 tx = self.create_stream_labelled_ip6(
548 self.pg0,
549 [VppMplsLabel(335, ttl=27, exp=4)])
550 rx = self.send_and_expect(self.pg0, tx, self.pg0)
551 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
552
553 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700554 # disposed packets have an TTL expired
555 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800556 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700557 dst_ip=self.pg1.remote_ip6,
558 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800559 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700560 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
561
562 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000563 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
564 # so this traffic should be dropped.
565 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800566 route_33_neos = VppMplsRoute(self, 33, 0,
567 [VppRoutePath(self.pg0.remote_ip4,
568 self.pg0.sw_if_index,
569 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000570 route_33_neos.add_vpp_config()
571
Neale Ranns31ed7442018-02-23 05:29:09 -0800572 tx = self.create_stream_labelled_ip4(self.pg0,
573 [VppMplsLabel(33),
574 VppMplsLabel(99)])
575 self.send_and_assert_no_replies(
576 self.pg0, tx,
577 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000578
579 #
580 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800581 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000582 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800583 route_34_eos = VppMplsRoute(self, 34, 1,
584 [VppRoutePath("0.0.0.0",
585 0xffffffff,
586 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800587 labels=[VppMplsLabel(44),
588 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000589 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700590 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000591
Neale Ranns31ed7442018-02-23 05:29:09 -0800592 tx = self.create_stream_labelled_ip4(self.pg0,
593 [VppMplsLabel(34, ttl=3)])
594 rx = self.send_and_expect(self.pg0, tx, self.pg0)
595 self.verify_capture_labelled(self.pg0, rx, tx,
596 [VppMplsLabel(33),
597 VppMplsLabel(44),
598 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000599
Neale Ranns008dbe12018-09-07 09:32:36 -0700600 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
601 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
602
Neale Ranns31ed7442018-02-23 05:29:09 -0800603 #
604 # A recursive EOS x-connect, which resolves through another x-connect
605 # in uniform mode
606 #
607 route_35_eos = VppMplsRoute(
608 self, 35, 1,
609 [VppRoutePath("0.0.0.0",
610 0xffffffff,
611 nh_via_label=42,
612 labels=[VppMplsLabel(44)])])
613 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000614
Neale Ranns31ed7442018-02-23 05:29:09 -0800615 tx = self.create_stream_labelled_ip4(self.pg0,
616 [VppMplsLabel(35, ttl=3)])
617 rx = self.send_and_expect(self.pg0, tx, self.pg0)
618 self.verify_capture_labelled(self.pg0, rx, tx,
619 [VppMplsLabel(43, ttl=2),
620 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000621
622 #
Matej Klottondeb69842016-12-09 15:05:46 +0100623 # A recursive non-EOS x-connect, which resolves through another
624 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000625 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800626 route_34_neos = VppMplsRoute(self, 34, 0,
627 [VppRoutePath("0.0.0.0",
628 0xffffffff,
629 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800630 labels=[VppMplsLabel(44),
631 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000632 route_34_neos.add_vpp_config()
633
Neale Ranns31ed7442018-02-23 05:29:09 -0800634 tx = self.create_stream_labelled_ip4(self.pg0,
635 [VppMplsLabel(34, ttl=45),
636 VppMplsLabel(99)])
637 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100638 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800639 self.verify_capture_labelled(self.pg0, rx, tx,
640 [VppMplsLabel(33),
641 VppMplsLabel(44),
642 VppMplsLabel(46, ttl=44),
643 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000644
645 #
Matej Klottondeb69842016-12-09 15:05:46 +0100646 # an recursive IP route that resolves through the recursive non-eos
647 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000648 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800649 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
650 [VppRoutePath("0.0.0.0",
651 0xffffffff,
652 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800653 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000654 ip_10_0_0_1.add_vpp_config()
655
Neale Rannsad422ed2016-11-02 14:20:04 +0000656 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800657 rx = self.send_and_expect(self.pg0, tx, self.pg0)
658 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
659 [VppMplsLabel(33),
660 VppMplsLabel(44),
661 VppMplsLabel(46),
662 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700663 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000664
665 ip_10_0_0_1.remove_vpp_config()
666 route_34_neos.remove_vpp_config()
667 route_34_eos.remove_vpp_config()
668 route_33_neos.remove_vpp_config()
669 route_33_eos.remove_vpp_config()
670 route_32_neos.remove_vpp_config()
671 route_32_eos.remove_vpp_config()
672
673 def test_bind(self):
674 """ MPLS Local Label Binding test """
675
676 #
677 # Add a non-recursive route with a single out label
678 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800679 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
680 [VppRoutePath(self.pg0.remote_ip4,
681 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800682 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000683 route_10_0_0_1.add_vpp_config()
684
685 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800686 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000687 binding.add_vpp_config()
688
689 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800690 tx = self.create_stream_labelled_ip4(self.pg0,
691 [VppMplsLabel(44),
692 VppMplsLabel(99)])
693 rx = self.send_and_expect(self.pg0, tx, self.pg0)
694 self.verify_capture_labelled(self.pg0, rx, tx,
695 [VppMplsLabel(45, ttl=63),
696 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000697
698 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800699 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
700 rx = self.send_and_expect(self.pg0, tx, self.pg0)
701 self.verify_capture_labelled(self.pg0, rx, tx,
702 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000703
704 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000705 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800706 rx = self.send_and_expect(self.pg0, tx, self.pg0)
707 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000708
709 #
710 # cleanup
711 #
712 binding.remove_vpp_config()
713 route_10_0_0_1.remove_vpp_config()
714
715 def test_imposition(self):
716 """ MPLS label imposition test """
717
718 #
719 # Add a non-recursive route with a single out label
720 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800721 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
722 [VppRoutePath(self.pg0.remote_ip4,
723 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800724 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000725 route_10_0_0_1.add_vpp_config()
726
727 #
728 # a stream that matches the route for 10.0.0.1
729 # PG0 is in the default table
730 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000731 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800732 rx = self.send_and_expect(self.pg0, tx, self.pg0)
733 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000734
735 #
736 # Add a non-recursive route with a 3 out labels
737 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800738 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
739 [VppRoutePath(self.pg0.remote_ip4,
740 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800741 labels=[VppMplsLabel(32),
742 VppMplsLabel(33),
743 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000744 route_10_0_0_2.add_vpp_config()
745
Neale Ranns31ed7442018-02-23 05:29:09 -0800746 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
747 ip_ttl=44, ip_dscp=0xff)
748 rx = self.send_and_expect(self.pg0, tx, self.pg0)
749 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
750 [VppMplsLabel(32),
751 VppMplsLabel(33),
752 VppMplsLabel(34)],
753 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000754
Neale Ranns31ed7442018-02-23 05:29:09 -0800755 #
756 # Add a non-recursive route with a single out label in uniform mode
757 #
758 route_10_0_0_3 = VppIpRoute(
759 self, "10.0.0.3", 32,
760 [VppRoutePath(self.pg0.remote_ip4,
761 self.pg0.sw_if_index,
762 labels=[VppMplsLabel(32,
763 mode=MplsLspMode.UNIFORM)])])
764 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000765
Neale Ranns31ed7442018-02-23 05:29:09 -0800766 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
767 ip_ttl=54, ip_dscp=0xbe)
768 rx = self.send_and_expect(self.pg0, tx, self.pg0)
769 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
770 [VppMplsLabel(32, ttl=53, exp=5)])
771
772 #
773 # Add a IPv6 non-recursive route with a single out label in
774 # uniform mode
775 #
776 route_2001_3 = VppIpRoute(
777 self, "2001::3", 128,
778 [VppRoutePath(self.pg0.remote_ip6,
779 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800780 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700781 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800782 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):
Neale Ranns097fa662018-05-01 05:17:55 -0700971 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -0700972
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 #
Neale Ranns097fa662018-05-01 05:17:55 -07001114 route_34_eos = VppMplsRoute(
1115 self, 34, 1,
1116 [VppRoutePath("0.0.0.0",
1117 self.pg1.sw_if_index,
1118 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001119 route_34_eos.add_vpp_config()
1120
1121 #
1122 # ping an interface in the default table
1123 # PG0 is in the default table
1124 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001125 tx = self.create_stream_labelled_ip4(self.pg0,
1126 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001127 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001128 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001129 self.verify_capture_ip4(self.pg1, rx, tx)
1130
1131 def test_mcast_mid_point(self):
1132 """ MPLS Multicast Mid Point """
1133
1134 #
1135 # Add a non-recursive route that will forward the traffic
1136 # post-interface-rx
1137 #
1138 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1139 table_id=1,
1140 paths=[VppRoutePath(self.pg1.remote_ip4,
1141 self.pg1.sw_if_index)])
1142 route_10_0_0_1.add_vpp_config()
1143
1144 #
1145 # Add a mcast entry that replicate to pg2 and pg3
1146 # and replicate to a interface-rx (like a bud node would)
1147 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001148 route_3400_eos = VppMplsRoute(
1149 self, 3400, 1,
1150 [VppRoutePath(self.pg2.remote_ip4,
1151 self.pg2.sw_if_index,
1152 labels=[VppMplsLabel(3401)]),
1153 VppRoutePath(self.pg3.remote_ip4,
1154 self.pg3.sw_if_index,
1155 labels=[VppMplsLabel(3402)]),
1156 VppRoutePath("0.0.0.0",
1157 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001158 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001159 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001160 route_3400_eos.add_vpp_config()
1161
1162 #
1163 # ping an interface in the default table
1164 # PG0 is in the default table
1165 #
1166 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001167 tx = self.create_stream_labelled_ip4(self.pg0,
1168 [VppMplsLabel(3400, ttl=64)],
1169 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001170 dst_ip="10.0.0.1")
1171 self.pg0.add_stream(tx)
1172
1173 self.pg_enable_capture(self.pg_interfaces)
1174 self.pg_start()
1175
1176 rx = self.pg1.get_capture(257)
1177 self.verify_capture_ip4(self.pg1, rx, tx)
1178
1179 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001180 self.verify_capture_labelled(self.pg2, rx, tx,
1181 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001182 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001183 self.verify_capture_labelled(self.pg3, rx, tx,
1184 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001185
1186 def test_mcast_head(self):
1187 """ MPLS Multicast Head-end """
1188
1189 #
1190 # Create a multicast tunnel with two replications
1191 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001192 mpls_tun = VppMPLSTunnelInterface(
1193 self,
1194 [VppRoutePath(self.pg2.remote_ip4,
1195 self.pg2.sw_if_index,
1196 labels=[VppMplsLabel(42)]),
1197 VppRoutePath(self.pg3.remote_ip4,
1198 self.pg3.sw_if_index,
1199 labels=[VppMplsLabel(43)])],
1200 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001201 mpls_tun.add_vpp_config()
1202 mpls_tun.admin_up()
1203
1204 #
1205 # add an unlabelled route through the new tunnel
1206 #
1207 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1208 [VppRoutePath("0.0.0.0",
1209 mpls_tun._sw_if_index)])
1210 route_10_0_0_3.add_vpp_config()
1211
1212 self.vapi.cli("clear trace")
1213 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1214 self.pg0.add_stream(tx)
1215
1216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218
1219 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001220 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001221 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001222 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001223
1224 #
1225 # An an IP multicast route via the tunnel
1226 # A (*,G).
1227 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1228 #
1229 route_232_1_1_1 = VppIpMRoute(
1230 self,
1231 "0.0.0.0",
1232 "232.1.1.1", 32,
1233 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1234 [VppMRoutePath(self.pg0.sw_if_index,
1235 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1236 VppMRoutePath(mpls_tun._sw_if_index,
1237 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1238 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001239 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001240
1241 self.vapi.cli("clear trace")
1242 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1243 self.pg0.add_stream(tx)
1244
1245 self.pg_enable_capture(self.pg_interfaces)
1246 self.pg_start()
1247
1248 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001249 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001250 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001251 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001252
Neale Ranns31426c62017-05-24 10:32:58 -07001253 def test_mcast_ip4_tail(self):
1254 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001255
1256 #
1257 # Add a multicast route that will forward the traffic
1258 # post-disposition
1259 #
1260 route_232_1_1_1 = VppIpMRoute(
1261 self,
1262 "0.0.0.0",
1263 "232.1.1.1", 32,
1264 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1265 table_id=1,
1266 paths=[VppMRoutePath(self.pg1.sw_if_index,
1267 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1268 route_232_1_1_1.add_vpp_config()
1269
1270 #
1271 # An interface receive label that maps traffic to RX on interface
1272 # pg1
1273 # by injecting the packet in on pg0, which is in table 0
1274 # doing an rpf-id and matching a route in table 1
1275 # if the packet egresses, then we must have matched the route in
1276 # table 1
1277 #
Neale Ranns097fa662018-05-01 05:17:55 -07001278 route_34_eos = VppMplsRoute(
1279 self, 34, 1,
1280 [VppRoutePath("0.0.0.0",
1281 0xffffffff,
1282 nh_table_id=1,
1283 rpf_id=55)],
1284 is_multicast=1,
1285 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001286
1287 route_34_eos.add_vpp_config()
1288
1289 #
1290 # Drop due to interface lookup miss
1291 #
1292 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001293 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001294 dst_ip="232.1.1.1", n=1)
1295 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1296
1297 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001298 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001299 #
1300 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001301 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001302
Neale Ranns31ed7442018-02-23 05:29:09 -08001303 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1304 dst_ip="232.1.1.1")
1305 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001306 self.verify_capture_ip4(self.pg1, rx, tx)
1307
1308 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001309 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001310 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001311 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001312 dst_ip="232.1.1.1", n=65,
1313 chksum=1)
1314 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1315
1316 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001317 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001318 #
1319 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001320 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001321 dst_ip="232.1.1.1")
1322 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1323
Neale Ranns31426c62017-05-24 10:32:58 -07001324 def test_mcast_ip6_tail(self):
1325 """ MPLS IPv6 Multicast Tail """
1326
1327 #
1328 # Add a multicast route that will forward the traffic
1329 # post-disposition
1330 #
1331 route_ff = VppIpMRoute(
1332 self,
1333 "::",
1334 "ff01::1", 32,
1335 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1336 table_id=1,
1337 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001338 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
1339 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001340 route_ff.add_vpp_config()
1341
1342 #
1343 # An interface receive label that maps traffic to RX on interface
1344 # pg1
1345 # by injecting the packet in on pg0, which is in table 0
1346 # doing an rpf-id and matching a route in table 1
1347 # if the packet egresses, then we must have matched the route in
1348 # table 1
1349 #
1350 route_34_eos = VppMplsRoute(
1351 self, 34, 1,
1352 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001353 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001354 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001355 rpf_id=55)],
1356 is_multicast=1,
1357 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001358
1359 route_34_eos.add_vpp_config()
1360
1361 #
1362 # Drop due to interface lookup miss
1363 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001364 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001365 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001366 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001367
1368 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001369 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001370 #
1371 route_ff.update_rpf_id(55)
1372
Neale Ranns31ed7442018-02-23 05:29:09 -08001373 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001374 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001375 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001376 self.verify_capture_ip6(self.pg1, rx, tx)
1377
1378 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001379 # disposed packets have hop-limit = 1
1380 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001381 tx = self.create_stream_labelled_ip6(self.pg0,
1382 [VppMplsLabel(34)],
1383 dst_ip="ff01::1",
1384 hlim=1)
1385 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001386 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001387
1388 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001389 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001390 #
1391 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001392 tx = self.create_stream_labelled_ip6(self.pg0,
1393 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001394 dst_ip="ff01::1")
1395 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1396
Neale Ranns180279b2017-03-16 15:49:09 -04001397
1398class TestMPLSDisabled(VppTestCase):
1399 """ MPLS disabled """
1400
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001401 @classmethod
1402 def setUpClass(cls):
1403 super(TestMPLSDisabled, cls).setUpClass()
1404
1405 @classmethod
1406 def tearDownClass(cls):
1407 super(TestMPLSDisabled, cls).tearDownClass()
1408
Neale Ranns180279b2017-03-16 15:49:09 -04001409 def setUp(self):
1410 super(TestMPLSDisabled, self).setUp()
1411
1412 # create 2 pg interfaces
1413 self.create_pg_interfaces(range(2))
1414
Neale Ranns15002542017-09-10 04:39:11 -07001415 self.tbl = VppMplsTable(self, 0)
1416 self.tbl.add_vpp_config()
1417
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001418 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001419 self.pg0.admin_up()
1420 self.pg0.config_ip4()
1421 self.pg0.resolve_arp()
1422 self.pg0.enable_mpls()
1423
1424 # PG 1 is not MPLS enabled
1425 self.pg1.admin_up()
1426
1427 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001428 for i in self.pg_interfaces:
1429 i.unconfig_ip4()
1430 i.admin_down()
1431
Neale Ranns15002542017-09-10 04:39:11 -07001432 self.pg0.disable_mpls()
1433 super(TestMPLSDisabled, self).tearDown()
1434
Neale Ranns180279b2017-03-16 15:49:09 -04001435 def test_mpls_disabled(self):
1436 """ MPLS Disabled """
1437
1438 tx = (Ether(src=self.pg1.remote_mac,
1439 dst=self.pg1.local_mac) /
1440 MPLS(label=32, ttl=64) /
1441 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1442 UDP(sport=1234, dport=1234) /
1443 Raw('\xa5' * 100))
1444
1445 #
1446 # A simple MPLS xconnect - eos label in label out
1447 #
1448 route_32_eos = VppMplsRoute(self, 32, 1,
1449 [VppRoutePath(self.pg0.remote_ip4,
1450 self.pg0.sw_if_index,
1451 labels=[33])])
1452 route_32_eos.add_vpp_config()
1453
1454 #
1455 # PG1 does not forward IP traffic
1456 #
1457 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1458
1459 #
1460 # MPLS enable PG1
1461 #
1462 self.pg1.enable_mpls()
1463
1464 #
1465 # Now we get packets through
1466 #
1467 self.pg1.add_stream(tx)
1468 self.pg_enable_capture(self.pg_interfaces)
1469 self.pg_start()
1470
1471 rx = self.pg0.get_capture(1)
1472
1473 #
1474 # Disable PG1
1475 #
1476 self.pg1.disable_mpls()
1477
1478 #
1479 # PG1 does not forward IP traffic
1480 #
1481 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1482 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1483
1484
Neale Rannsf12a83f2017-04-18 09:09:40 -07001485class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001486 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001487
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001488 @classmethod
1489 def setUpClass(cls):
1490 super(TestMPLSPIC, cls).setUpClass()
1491
1492 @classmethod
1493 def tearDownClass(cls):
1494 super(TestMPLSPIC, cls).tearDownClass()
1495
Neale Rannsf12a83f2017-04-18 09:09:40 -07001496 def setUp(self):
1497 super(TestMPLSPIC, self).setUp()
1498
1499 # create 2 pg interfaces
1500 self.create_pg_interfaces(range(4))
1501
Neale Ranns15002542017-09-10 04:39:11 -07001502 mpls_tbl = VppMplsTable(self, 0)
1503 mpls_tbl.add_vpp_config()
1504 tbl4 = VppIpTable(self, 1)
1505 tbl4.add_vpp_config()
1506 tbl6 = VppIpTable(self, 1, is_ip6=1)
1507 tbl6.add_vpp_config()
1508
Neale Rannsf12a83f2017-04-18 09:09:40 -07001509 # core links
1510 self.pg0.admin_up()
1511 self.pg0.config_ip4()
1512 self.pg0.resolve_arp()
1513 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001514
Neale Rannsf12a83f2017-04-18 09:09:40 -07001515 self.pg1.admin_up()
1516 self.pg1.config_ip4()
1517 self.pg1.resolve_arp()
1518 self.pg1.enable_mpls()
1519
1520 # VRF (customer facing) link
1521 self.pg2.admin_up()
1522 self.pg2.set_table_ip4(1)
1523 self.pg2.config_ip4()
1524 self.pg2.resolve_arp()
1525 self.pg2.set_table_ip6(1)
1526 self.pg2.config_ip6()
1527 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001528
Neale Rannsf12a83f2017-04-18 09:09:40 -07001529 self.pg3.admin_up()
1530 self.pg3.set_table_ip4(1)
1531 self.pg3.config_ip4()
1532 self.pg3.resolve_arp()
1533 self.pg3.set_table_ip6(1)
1534 self.pg3.config_ip6()
1535 self.pg3.resolve_ndp()
1536
1537 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001538 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001539 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001540 for i in self.pg_interfaces:
1541 i.unconfig_ip4()
1542 i.unconfig_ip6()
1543 i.set_table_ip4(0)
1544 i.set_table_ip6(0)
1545 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001546 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001547
1548 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001549 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001550
1551 1) setup many iBGP VPN routes via a pair of iBGP peers.
1552 2) Check EMCP forwarding to these peers
1553 3) withdraw the IGP route to one of these peers.
1554 4) check forwarding continues to the remaining peer
1555 """
1556
1557 #
1558 # IGP+LDP core routes
1559 #
1560 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1561 [VppRoutePath(self.pg0.remote_ip4,
1562 self.pg0.sw_if_index,
1563 labels=[45])])
1564 core_10_0_0_45.add_vpp_config()
1565
1566 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1567 [VppRoutePath(self.pg1.remote_ip4,
1568 self.pg1.sw_if_index,
1569 labels=[46])])
1570 core_10_0_0_46.add_vpp_config()
1571
1572 #
1573 # Lot's of VPN routes. We need more the 64 so VPP will build
1574 # the fast convergence indirection
1575 #
1576 vpn_routes = []
1577 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001578 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001579 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001580 vpn_routes.append(VppIpRoute(
1581 self, dst, 32,
1582 [VppRoutePath(
1583 "10.0.0.45",
1584 0xffffffff,
1585 labels=[145],
1586 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1587 VppRoutePath(
1588 "10.0.0.46",
1589 0xffffffff,
1590 labels=[146],
1591 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1592 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001593 vpn_routes[ii].add_vpp_config()
1594
1595 pkts.append(Ether(dst=self.pg2.local_mac,
1596 src=self.pg2.remote_mac) /
1597 IP(src=self.pg2.remote_ip4, dst=dst) /
1598 UDP(sport=1234, dport=1234) /
1599 Raw('\xa5' * 100))
1600
1601 #
1602 # Send the packet stream (one pkt to each VPN route)
1603 # - expect a 50-50 split of the traffic
1604 #
1605 self.pg2.add_stream(pkts)
1606 self.pg_enable_capture(self.pg_interfaces)
1607 self.pg_start()
1608
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001609 rx0 = self.pg0._get_capture(NUM_PKTS)
1610 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001611
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001612 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001613 # with the split ratio, just as long as neither is 0
1614 self.assertNotEqual(0, len(rx0))
1615 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001616 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1617 "Expected all (%s) packets across both ECMP paths. "
1618 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001619
1620 #
1621 # use a test CLI command to stop the FIB walk process, this
1622 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001623 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001624 #
1625 self.vapi.ppcli("test fib-walk-process disable")
1626
1627 #
1628 # Withdraw one of the IGP routes
1629 #
1630 core_10_0_0_46.remove_vpp_config()
1631
1632 #
1633 # now all packets should be forwarded through the remaining peer
1634 #
1635 self.vapi.ppcli("clear trace")
1636 self.pg2.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1638 self.pg_start()
1639
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001640 rx0 = self.pg0.get_capture(NUM_PKTS)
1641 self.assertEqual(len(pkts), len(rx0),
1642 "Expected all (%s) packets across single path. "
1643 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001644
1645 #
1646 # enable the FIB walk process to converge the FIB
1647 #
1648 self.vapi.ppcli("test fib-walk-process enable")
1649
1650 #
1651 # packets should still be forwarded through the remaining peer
1652 #
1653 self.pg2.add_stream(pkts)
1654 self.pg_enable_capture(self.pg_interfaces)
1655 self.pg_start()
1656
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001657 rx0 = self.pg0.get_capture(NUM_PKTS)
1658 self.assertEqual(len(pkts), len(rx0),
1659 "Expected all (%s) packets across single path. "
1660 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001661
1662 #
1663 # Add the IGP route back and we return to load-balancing
1664 #
1665 core_10_0_0_46.add_vpp_config()
1666
1667 self.pg2.add_stream(pkts)
1668 self.pg_enable_capture(self.pg_interfaces)
1669 self.pg_start()
1670
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001671 rx0 = self.pg0._get_capture(NUM_PKTS)
1672 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001673 self.assertNotEqual(0, len(rx0))
1674 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001675 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1676 "Expected all (%s) packets across both ECMP paths. "
1677 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001678
1679 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001680 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001681
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001682 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001683 2) Check EMCP forwarding to these peers
1684 3) withdraw one eBGP path - expect LB across remaining eBGP
1685 """
1686
1687 #
1688 # Lot's of VPN routes. We need more the 64 so VPP will build
1689 # the fast convergence indirection
1690 #
1691 vpn_routes = []
1692 vpn_bindings = []
1693 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001694 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001695 dst = "192.168.1.%d" % ii
1696 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001697 vpn_routes.append(VppIpRoute(
1698 self, dst, 32,
1699 [VppRoutePath(
1700 self.pg2.remote_ip4,
1701 0xffffffff,
1702 nh_table_id=1,
1703 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1704 VppRoutePath(
1705 self.pg3.remote_ip4,
1706 0xffffffff,
1707 nh_table_id=1,
1708 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1709 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001710 vpn_routes[ii].add_vpp_config()
1711
1712 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1713 ip_table_id=1))
1714 vpn_bindings[ii].add_vpp_config()
1715
1716 pkts.append(Ether(dst=self.pg0.local_mac,
1717 src=self.pg0.remote_mac) /
1718 MPLS(label=local_label, ttl=64) /
1719 IP(src=self.pg0.remote_ip4, dst=dst) /
1720 UDP(sport=1234, dport=1234) /
1721 Raw('\xa5' * 100))
1722
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001723 #
1724 # Send the packet stream (one pkt to each VPN route)
1725 # - expect a 50-50 split of the traffic
1726 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001727 self.pg0.add_stream(pkts)
1728 self.pg_enable_capture(self.pg_interfaces)
1729 self.pg_start()
1730
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001731 rx0 = self.pg2._get_capture(NUM_PKTS)
1732 rx1 = self.pg3._get_capture(NUM_PKTS)
1733
1734 # not testing the LB hashing algorithm so we're not concerned
1735 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001736 self.assertNotEqual(0, len(rx0))
1737 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001738 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1739 "Expected all (%s) packets across both ECMP paths. "
1740 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001741
1742 #
1743 # use a test CLI command to stop the FIB walk process, this
1744 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001745 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001746 #
1747 self.vapi.ppcli("test fib-walk-process disable")
1748
1749 #
1750 # withdraw the connected prefix on the interface.
1751 #
1752 self.pg2.unconfig_ip4()
1753
1754 #
1755 # now all packets should be forwarded through the remaining peer
1756 #
1757 self.pg0.add_stream(pkts)
1758 self.pg_enable_capture(self.pg_interfaces)
1759 self.pg_start()
1760
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001761 rx0 = self.pg3.get_capture(NUM_PKTS)
1762 self.assertEqual(len(pkts), len(rx0),
1763 "Expected all (%s) packets across single path. "
1764 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001765
1766 #
1767 # enable the FIB walk process to converge the FIB
1768 #
1769 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001770
1771 #
1772 # packets should still be forwarded through the remaining peer
1773 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001774 self.pg0.add_stream(pkts)
1775 self.pg_enable_capture(self.pg_interfaces)
1776 self.pg_start()
1777
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001778 rx0 = self.pg3.get_capture(NUM_PKTS)
1779 self.assertEqual(len(pkts), len(rx0),
1780 "Expected all (%s) packets across single path. "
1781 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001782
1783 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001784 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001785 #
1786 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001787 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001788
1789 self.pg0.add_stream(pkts)
1790 self.pg_enable_capture(self.pg_interfaces)
1791 self.pg_start()
1792
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001793 rx0 = self.pg2._get_capture(NUM_PKTS)
1794 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001795 self.assertNotEqual(0, len(rx0))
1796 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001797 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1798 "Expected all (%s) packets across both ECMP paths. "
1799 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001800
1801 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001802 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001803
1804 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1805 2) Check EMCP forwarding to these peers
1806 3) withdraw one eBGP path - expect LB across remaining eBGP
1807 """
1808
1809 #
1810 # Lot's of VPN routes. We need more the 64 so VPP will build
1811 # the fast convergence indirection
1812 #
1813 vpn_routes = []
1814 vpn_bindings = []
1815 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001816 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001817 dst = "3000::%d" % ii
1818 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001819 vpn_routes.append(VppIpRoute(
1820 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001821 [VppRoutePath(
1822 self.pg2.remote_ip6,
1823 0xffffffff,
1824 nh_table_id=1,
1825 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1826 VppRoutePath(
1827 self.pg3.remote_ip6,
1828 0xffffffff,
1829 nh_table_id=1,
1830 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1831 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001832 vpn_routes[ii].add_vpp_config()
1833
1834 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001835 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001836 vpn_bindings[ii].add_vpp_config()
1837
1838 pkts.append(Ether(dst=self.pg0.local_mac,
1839 src=self.pg0.remote_mac) /
1840 MPLS(label=local_label, ttl=64) /
1841 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1842 UDP(sport=1234, dport=1234) /
1843 Raw('\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07001844 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001845
1846 self.pg0.add_stream(pkts)
1847 self.pg_enable_capture(self.pg_interfaces)
1848 self.pg_start()
1849
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001850 rx0 = self.pg2._get_capture(NUM_PKTS)
1851 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001852 self.assertNotEqual(0, len(rx0))
1853 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001854 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1855 "Expected all (%s) packets across both ECMP paths. "
1856 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001857
1858 #
1859 # use a test CLI command to stop the FIB walk process, this
1860 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001861 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001862 #
1863 self.vapi.ppcli("test fib-walk-process disable")
1864
1865 #
1866 # withdraw the connected prefix on the interface.
1867 # and shutdown the interface so the ND cache is flushed.
1868 #
1869 self.pg2.unconfig_ip6()
1870 self.pg2.admin_down()
1871
1872 #
1873 # now all packets should be forwarded through the remaining peer
1874 #
1875 self.pg0.add_stream(pkts)
1876 self.pg_enable_capture(self.pg_interfaces)
1877 self.pg_start()
1878
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001879 rx0 = self.pg3.get_capture(NUM_PKTS)
1880 self.assertEqual(len(pkts), len(rx0),
1881 "Expected all (%s) packets across single path. "
1882 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001883
1884 #
1885 # enable the FIB walk process to converge the FIB
1886 #
1887 self.vapi.ppcli("test fib-walk-process enable")
1888 self.pg0.add_stream(pkts)
1889 self.pg_enable_capture(self.pg_interfaces)
1890 self.pg_start()
1891
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001892 rx0 = self.pg3.get_capture(NUM_PKTS)
1893 self.assertEqual(len(pkts), len(rx0),
1894 "Expected all (%s) packets across single path. "
1895 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001896
1897 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001898 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001899 #
1900 self.pg2.admin_up()
1901 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001902 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001903
1904 self.pg0.add_stream(pkts)
1905 self.pg_enable_capture(self.pg_interfaces)
1906 self.pg_start()
1907
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001908 rx0 = self.pg2._get_capture(NUM_PKTS)
1909 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001910 self.assertNotEqual(0, len(rx0))
1911 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001912 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1913 "Expected all (%s) packets across both ECMP paths. "
1914 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001915
1916
Neale Rannsda78f952017-05-24 09:15:43 -07001917class TestMPLSL2(VppTestCase):
1918 """ MPLS-L2 """
1919
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001920 @classmethod
1921 def setUpClass(cls):
1922 super(TestMPLSL2, cls).setUpClass()
1923
1924 @classmethod
1925 def tearDownClass(cls):
1926 super(TestMPLSL2, cls).tearDownClass()
1927
Neale Rannsda78f952017-05-24 09:15:43 -07001928 def setUp(self):
1929 super(TestMPLSL2, self).setUp()
1930
1931 # create 2 pg interfaces
1932 self.create_pg_interfaces(range(2))
1933
Neale Ranns15002542017-09-10 04:39:11 -07001934 # create the default MPLS table
1935 self.tables = []
1936 tbl = VppMplsTable(self, 0)
1937 tbl.add_vpp_config()
1938 self.tables.append(tbl)
1939
Neale Rannsda78f952017-05-24 09:15:43 -07001940 # use pg0 as the core facing interface
1941 self.pg0.admin_up()
1942 self.pg0.config_ip4()
1943 self.pg0.resolve_arp()
1944 self.pg0.enable_mpls()
1945
Neale Ranns15002542017-09-10 04:39:11 -07001946 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07001947 for i in self.pg_interfaces[1:]:
1948 i.admin_up()
1949
1950 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07001951 for i in self.pg_interfaces[1:]:
1952 i.admin_down()
1953
1954 self.pg0.disable_mpls()
1955 self.pg0.unconfig_ip4()
1956 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001957 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07001958
Neale Ranns31ed7442018-02-23 05:29:09 -08001959 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07001960 capture = verify_filter(capture, sent)
1961
1962 self.assertEqual(len(capture), len(sent))
1963
1964 for i in range(len(capture)):
1965 tx = sent[i]
1966 rx = capture[i]
1967
1968 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08001969 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07001970
1971 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001972 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07001973
1974 self.assertEqual(rx_eth.src, tx_eth.src)
1975 self.assertEqual(rx_eth.dst, tx_eth.dst)
1976
1977 def test_vpws(self):
1978 """ Virtual Private Wire Service """
1979
1980 #
1981 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08001982 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
1983 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07001984 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001985 mpls_tun_1 = VppMPLSTunnelInterface(
1986 self,
1987 [VppRoutePath(self.pg0.remote_ip4,
1988 self.pg0.sw_if_index,
1989 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
1990 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07001991 mpls_tun_1.add_vpp_config()
1992 mpls_tun_1.admin_up()
1993
1994 #
1995 # Create a label entry to for 55 that does L2 input to the tunnel
1996 #
1997 route_55_eos = VppMplsRoute(
1998 self, 55, 1,
1999 [VppRoutePath("0.0.0.0",
2000 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002001 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2002 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2003 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002004 route_55_eos.add_vpp_config()
2005
2006 #
2007 # Cross-connect the tunnel with one of the customers L2 interfaces
2008 #
2009 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2010 mpls_tun_1.sw_if_index,
2011 enable=1)
2012 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2013 self.pg1.sw_if_index,
2014 enable=1)
2015
2016 #
2017 # inject a packet from the core
2018 #
2019 pcore = (Ether(dst=self.pg0.local_mac,
2020 src=self.pg0.remote_mac) /
2021 MPLS(label=55, ttl=64) /
2022 Ether(dst="00:00:de:ad:ba:be",
2023 src="00:00:de:ad:be:ef") /
2024 IP(src="10.10.10.10", dst="11.11.11.11") /
2025 UDP(sport=1234, dport=1234) /
2026 Raw('\xa5' * 100))
2027
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002028 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002029 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2030 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002031
Neale Ranns31ed7442018-02-23 05:29:09 -08002032 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2033 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002034
2035 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002036 # Inject a packet from the customer/L2 side
Neale Rannsda78f952017-05-24 09:15:43 -07002037 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002038 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002039 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002040
Neale Ranns31ed7442018-02-23 05:29:09 -08002041 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002042
2043 def test_vpls(self):
2044 """ Virtual Private LAN Service """
2045 #
2046 # Create an L2 MPLS tunnel
2047 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002048 mpls_tun = VppMPLSTunnelInterface(
2049 self,
2050 [VppRoutePath(self.pg0.remote_ip4,
2051 self.pg0.sw_if_index,
2052 labels=[VppMplsLabel(42)])],
2053 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002054 mpls_tun.add_vpp_config()
2055 mpls_tun.admin_up()
2056
2057 #
2058 # Create a label entry to for 55 that does L2 input to the tunnel
2059 #
2060 route_55_eos = VppMplsRoute(
2061 self, 55, 1,
2062 [VppRoutePath("0.0.0.0",
2063 mpls_tun.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002064 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2065 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2066 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002067 route_55_eos.add_vpp_config()
2068
2069 #
2070 # add to tunnel to the customers bridge-domain
2071 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002072 self.vapi.sw_interface_set_l2_bridge(
2073 rx_sw_if_index=mpls_tun.sw_if_index, bd_id=1)
2074 self.vapi.sw_interface_set_l2_bridge(
2075 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002076
2077 #
2078 # Packet from the customer interface and from the core
2079 #
2080 p_cust = (Ether(dst="00:00:de:ad:ba:be",
2081 src="00:00:de:ad:be:ef") /
2082 IP(src="10.10.10.10", dst="11.11.11.11") /
2083 UDP(sport=1234, dport=1234) /
2084 Raw('\xa5' * 100))
2085 p_core = (Ether(src="00:00:de:ad:ba:be",
2086 dst="00:00:de:ad:be:ef") /
2087 IP(dst="10.10.10.10", src="11.11.11.11") /
2088 UDP(sport=1234, dport=1234) /
2089 Raw('\xa5' * 100))
2090
2091 #
2092 # The BD is learning, so send in one of each packet to learn
2093 #
2094 p_core_encap = (Ether(dst=self.pg0.local_mac,
2095 src=self.pg0.remote_mac) /
2096 MPLS(label=55, ttl=64) /
2097 p_core)
2098
2099 self.pg1.add_stream(p_cust)
2100 self.pg_enable_capture(self.pg_interfaces)
2101 self.pg_start()
2102 self.pg0.add_stream(p_core_encap)
2103 self.pg_enable_capture(self.pg_interfaces)
2104 self.pg_start()
2105
2106 # we've learnt this so expect it be be forwarded
2107 rx0 = self.pg1.get_capture(1)
2108
2109 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
2110 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
2111
2112 #
2113 # now a stream in each direction
2114 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002115 self.pg1.add_stream(p_cust * NUM_PKTS)
Neale Rannsda78f952017-05-24 09:15:43 -07002116 self.pg_enable_capture(self.pg_interfaces)
2117 self.pg_start()
2118
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002119 rx0 = self.pg0.get_capture(NUM_PKTS)
Neale Rannsda78f952017-05-24 09:15:43 -07002120
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002121 self.verify_capture_tunneled_ethernet(rx0, p_cust*NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002122 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002123
2124 #
2125 # remove interfaces from customers bridge-domain
2126 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002127 self.vapi.sw_interface_set_l2_bridge(
2128 rx_sw_if_index=mpls_tun.sw_if_index, bd_id=1, enable=0)
2129 self.vapi.sw_interface_set_l2_bridge(
2130 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002131
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002132
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002133if __name__ == '__main__':
2134 unittest.main(testRunner=VppTestRunner)