blob: 9590519e2378a38d5957b3525fdc2b1848bc0a5e [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 Ranns5a8123b2017-01-26 01:18:23 -08007from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Ranns15002542017-09-10 04:39:11 -07009 MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable
Neale Ranns0f26c5a2017-03-01 15:12:11 -080010from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns8fe8cc22016-11-01 10:05:08 +000011
12from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010013from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010014from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070015from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016from scapy.contrib.mpls import MPLS
17
Klement Sekeradab231a2016-12-21 08:50:14 +010018
Neale Rannsda78f952017-05-24 09:15:43 -070019def verify_filter(capture, sent):
20 if not len(capture) == len(sent):
21 # filter out any IPv6 RAs from the capture
22 for p in capture:
23 if p.haslayer(IPv6):
24 capture.remove(p)
25 return capture
26
27
28def verify_mpls_stack(tst, rx, mpls_labels, ttl=255, num=0):
29 # the rx'd packet has the MPLS label popped
30 eth = rx[Ether]
31 tst.assertEqual(eth.type, 0x8847)
32
33 rx_mpls = rx[MPLS]
34
35 for ii in range(len(mpls_labels)):
36 tst.assertEqual(rx_mpls.label, mpls_labels[ii])
37 tst.assertEqual(rx_mpls.cos, 0)
38 if ii == num:
39 tst.assertEqual(rx_mpls.ttl, ttl)
40 else:
41 tst.assertEqual(rx_mpls.ttl, 255)
42 if ii == len(mpls_labels) - 1:
43 tst.assertEqual(rx_mpls.s, 1)
44 else:
45 # not end of stack
46 tst.assertEqual(rx_mpls.s, 0)
47 # pop the label to expose the next
48 rx_mpls = rx_mpls[MPLS].payload
49
50
Neale Ranns8fe8cc22016-11-01 10:05:08 +000051class TestMPLS(VppTestCase):
52 """ MPLS Test Case """
53
Neale Ranns8fe8cc22016-11-01 10:05:08 +000054 def setUp(self):
55 super(TestMPLS, self).setUp()
56
57 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080058 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000059
60 # setup both interfaces
61 # assign them different tables.
62 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070063 self.tables = []
64
65 tbl = VppMplsTable(self, 0)
66 tbl.add_vpp_config()
67 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000068
69 for i in self.pg_interfaces:
70 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070071
72 if table_id != 0:
73 tbl = VppIpTable(self, table_id)
74 tbl.add_vpp_config()
75 self.tables.append(tbl)
76 tbl = VppIpTable(self, table_id, is_ip6=1)
77 tbl.add_vpp_config()
78 self.tables.append(tbl)
79
Neale Ranns8fe8cc22016-11-01 10:05:08 +000080 i.set_table_ip4(table_id)
81 i.set_table_ip6(table_id)
82 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000083 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000084 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000085 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000086 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000087 table_id += 1
88
89 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -080090 for i in self.pg_interfaces:
91 i.unconfig_ip4()
92 i.unconfig_ip6()
93 i.ip6_disable()
Neale Ranns15002542017-09-10 04:39:11 -070094 i.set_table_ip4(0)
95 i.set_table_ip6(0)
96 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -080097 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -070098 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000099
Neale Rannsad422ed2016-11-02 14:20:04 +0000100 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100101 def create_stream_labelled_ip4(
102 self,
103 src_if,
104 mpls_labels,
105 mpls_ttl=255,
106 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800107 ip_itf=None,
108 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700109 chksum=None,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800110 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100111 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000112 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800113 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100114 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000115 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000116 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
117
118 for ii in range(len(mpls_labels)):
119 if ii == len(mpls_labels) - 1:
120 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
121 else:
122 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
Neale Rannscb630ff2016-12-14 13:31:29 +0100123 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800124 if not dst_ip:
125 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
126 UDP(sport=1234, dport=1234) /
127 Raw(payload))
128 else:
129 p = (p / IP(src=src_if.local_ip4, dst=dst_ip) /
130 UDP(sport=1234, dport=1234) /
131 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100132 else:
133 p = (p / IP(src=ip_itf.remote_ip4,
134 dst=ip_itf.local_ip4) /
135 ICMP())
136
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700137 if chksum:
138 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000139 info.data = p.copy()
140 pkts.append(p)
141 return pkts
142
Neale Rannsad422ed2016-11-02 14:20:04 +0000143 def create_stream_ip4(self, src_if, dst_ip):
Klement Sekeradab231a2016-12-21 08:50:14 +0100144 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000145 pkts = []
146 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100147 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000148 payload = self.info_to_payload(info)
149 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
150 IP(src=src_if.remote_ip4, dst=dst_ip) /
151 UDP(sport=1234, dport=1234) /
152 Raw(payload))
153 info.data = p.copy()
154 pkts.append(p)
155 return pkts
156
Neale Ranns31426c62017-05-24 10:32:58 -0700157 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700158 dst_ip=None, hlim=64):
Neale Ranns31426c62017-05-24 10:32:58 -0700159 if dst_ip is None:
160 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100161 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000162 pkts = []
163 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100164 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000165 payload = self.info_to_payload(info)
166 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
167 MPLS(label=mpls_label, ttl=mpls_ttl) /
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700168 IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000169 UDP(sport=1234, dport=1234) /
170 Raw(payload))
171 info.data = p.copy()
172 pkts.append(p)
173 return pkts
174
Neale Rannscb630ff2016-12-14 13:31:29 +0100175 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000176 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700177 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000178
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000179 self.assertEqual(len(capture), len(sent))
180
181 for i in range(len(capture)):
182 tx = sent[i]
183 rx = capture[i]
184
185 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000186 eth = rx[Ether]
187 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000188
189 tx_ip = tx[IP]
190 rx_ip = rx[IP]
191
Neale Rannscb630ff2016-12-14 13:31:29 +0100192 if not ping_resp:
193 self.assertEqual(rx_ip.src, tx_ip.src)
194 self.assertEqual(rx_ip.dst, tx_ip.dst)
195 # IP processing post pop has decremented the TTL
196 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
197 else:
198 self.assertEqual(rx_ip.src, tx_ip.dst)
199 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000200
201 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000202 raise
203
Neale Rannsad422ed2016-11-02 14:20:04 +0000204 def verify_capture_labelled_ip4(self, src_if, capture, sent,
205 mpls_labels):
206 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700207 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000208
209 self.assertEqual(len(capture), len(sent))
210
211 for i in range(len(capture)):
212 tx = sent[i]
213 rx = capture[i]
214 tx_ip = tx[IP]
215 rx_ip = rx[IP]
216
217 # the MPLS TTL is copied from the IP
Neale Rannsda78f952017-05-24 09:15:43 -0700218 verify_mpls_stack(self, rx, mpls_labels, rx_ip.ttl,
219 len(mpls_labels) - 1)
Neale Rannsad422ed2016-11-02 14:20:04 +0000220
221 self.assertEqual(rx_ip.src, tx_ip.src)
222 self.assertEqual(rx_ip.dst, tx_ip.dst)
223 # IP processing post pop has decremented the TTL
224 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
225
226 except:
227 raise
228
Neale Ranns8c4611b2017-05-23 03:43:47 -0700229 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
230 ttl=255, top=None):
231 if top is None:
232 top = len(mpls_labels) - 1
Neale Rannsad422ed2016-11-02 14:20:04 +0000233 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700234 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000235
236 self.assertEqual(len(capture), len(sent))
237
238 for i in range(len(capture)):
239 tx = sent[i]
240 rx = capture[i]
241 tx_ip = tx[IP]
242 rx_ip = rx[IP]
243
244 # the MPLS TTL is 255 since it enters a new tunnel
Neale Rannsda78f952017-05-24 09:15:43 -0700245 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
Neale Rannsad422ed2016-11-02 14:20:04 +0000246
247 self.assertEqual(rx_ip.src, tx_ip.src)
248 self.assertEqual(rx_ip.dst, tx_ip.dst)
249 # IP processing post pop has decremented the TTL
250 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
251
252 except:
253 raise
254
255 def verify_capture_labelled(self, src_if, capture, sent,
256 mpls_labels, ttl=254, num=0):
257 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700258 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000259
260 self.assertEqual(len(capture), len(sent))
261
262 for i in range(len(capture)):
263 rx = capture[i]
Neale Rannsda78f952017-05-24 09:15:43 -0700264 verify_mpls_stack(self, rx, mpls_labels, ttl, num)
Neale Rannsad422ed2016-11-02 14:20:04 +0000265 except:
266 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000267
268 def verify_capture_ip6(self, src_if, capture, sent):
269 try:
270 self.assertEqual(len(capture), len(sent))
271
272 for i in range(len(capture)):
273 tx = sent[i]
274 rx = capture[i]
275
276 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000277 eth = rx[Ether]
278 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000279
280 tx_ip = tx[IPv6]
281 rx_ip = rx[IPv6]
282
283 self.assertEqual(rx_ip.src, tx_ip.src)
284 self.assertEqual(rx_ip.dst, tx_ip.dst)
285 # IP processing post pop has decremented the TTL
286 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
287
288 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000289 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000290
Neale Ranns62fe07c2017-10-31 12:28:22 -0700291 def verify_capture_ip6_icmp(self, src_if, capture, sent):
292 try:
293 self.assertEqual(len(capture), len(sent))
294
295 for i in range(len(capture)):
296 tx = sent[i]
297 rx = capture[i]
298
299 # the rx'd packet has the MPLS label popped
300 eth = rx[Ether]
301 self.assertEqual(eth.type, 0x86DD)
302
303 tx_ip = tx[IPv6]
304 rx_ip = rx[IPv6]
305
306 self.assertEqual(rx_ip.dst, tx_ip.src)
307 # ICMP sourced from the interface's address
308 self.assertEqual(rx_ip.src, src_if.local_ip6)
309 # hop-limit reset to 255 for IMCP packet
310 self.assertEqual(rx_ip.hlim, 254)
311
312 icmp = rx[ICMPv6TimeExceeded]
313
314 except:
315 raise
316
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800317 def send_and_assert_no_replies(self, intf, pkts, remark):
318 intf.add_stream(pkts)
319 self.pg_enable_capture(self.pg_interfaces)
320 self.pg_start()
321 for i in self.pg_interfaces:
322 i.assert_nothing_captured(remark=remark)
323
Neale Rannsad422ed2016-11-02 14:20:04 +0000324 def test_swap(self):
325 """ MPLS label swap tests """
326
327 #
328 # A simple MPLS xconnect - eos label in label out
329 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800330 route_32_eos = VppMplsRoute(self, 32, 1,
331 [VppRoutePath(self.pg0.remote_ip4,
332 self.pg0.sw_if_index,
333 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000334 route_32_eos.add_vpp_config()
335
336 #
337 # a stream that matches the route for 10.0.0.1
338 # PG0 is in the default table
339 #
340 self.vapi.cli("clear trace")
341 tx = self.create_stream_labelled_ip4(self.pg0, [32])
342 self.pg0.add_stream(tx)
343
344 self.pg_enable_capture(self.pg_interfaces)
345 self.pg_start()
346
347 rx = self.pg0.get_capture()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800348 self.verify_capture_labelled(self.pg0, rx, tx, [33])
Neale Rannsad422ed2016-11-02 14:20:04 +0000349
350 #
351 # A simple MPLS xconnect - non-eos label in label out
352 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800353 route_32_neos = VppMplsRoute(self, 32, 0,
354 [VppRoutePath(self.pg0.remote_ip4,
355 self.pg0.sw_if_index,
356 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000357 route_32_neos.add_vpp_config()
358
359 #
360 # a stream that matches the route for 10.0.0.1
361 # PG0 is in the default table
362 #
363 self.vapi.cli("clear trace")
364 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
365 self.pg0.add_stream(tx)
366
367 self.pg_enable_capture(self.pg_interfaces)
368 self.pg_start()
369
370 rx = self.pg0.get_capture()
371 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
372
373 #
374 # An MPLS xconnect - EOS label in IP out
375 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800376 route_33_eos = VppMplsRoute(self, 33, 1,
377 [VppRoutePath(self.pg0.remote_ip4,
378 self.pg0.sw_if_index,
379 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000380 route_33_eos.add_vpp_config()
381
382 self.vapi.cli("clear trace")
383 tx = self.create_stream_labelled_ip4(self.pg0, [33])
384 self.pg0.add_stream(tx)
385
386 self.pg_enable_capture(self.pg_interfaces)
387 self.pg_start()
388
389 rx = self.pg0.get_capture()
390 self.verify_capture_ip4(self.pg0, rx, tx)
391
392 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700393 # disposed packets have an invalid IPv4 checkusm
394 #
395 tx = self.create_stream_labelled_ip4(self.pg0, [33],
396 dst_ip=self.pg0.remote_ip4,
397 n=65,
398 chksum=1)
399 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
400
401 #
402 # An MPLS xconnect - EOS label in IPv6 out
403 #
404 route_333_eos = VppMplsRoute(
405 self, 333, 1,
406 [VppRoutePath(self.pg0.remote_ip6,
407 self.pg0.sw_if_index,
408 labels=[],
409 proto=DpoProto.DPO_PROTO_IP6)])
410 route_333_eos.add_vpp_config()
411
412 self.vapi.cli("clear trace")
413 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64)
414 self.pg0.add_stream(tx)
415
416 self.pg_enable_capture(self.pg_interfaces)
417 self.pg_start()
418
419 rx = self.pg0.get_capture()
420 self.verify_capture_ip6(self.pg0, rx, tx)
421
422 #
423 # disposed packets have an TTL expired
424 #
425 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64,
426 dst_ip=self.pg1.remote_ip6,
427 hlim=1)
428
429 self.vapi.cli("clear trace")
430 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64,
431 dst_ip=self.pg1.remote_ip6,
432 hlim=0)
433 self.pg0.add_stream(tx)
434
435 self.pg_enable_capture(self.pg_interfaces)
436 self.pg_start()
437
438 rx = self.pg0.get_capture()
439 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
440
441 #
442 # An MPLS xconnect - EOS label in IPv6 out w imp-null
443 #
444 route_334_eos = VppMplsRoute(
445 self, 334, 1,
446 [VppRoutePath(self.pg0.remote_ip6,
447 self.pg0.sw_if_index,
448 labels=[3],
449 proto=DpoProto.DPO_PROTO_IP6)])
450 route_334_eos.add_vpp_config()
451
452 self.vapi.cli("clear trace")
453 tx = self.create_stream_labelled_ip6(self.pg0, [334], 64)
454 self.pg0.add_stream(tx)
455
456 self.pg_enable_capture(self.pg_interfaces)
457 self.pg_start()
458
459 rx = self.pg0.get_capture()
460 self.verify_capture_ip6(self.pg0, rx, tx)
461
462 #
463 # disposed packets have an TTL expired
464 #
465 self.vapi.cli("clear trace")
466 tx = self.create_stream_labelled_ip6(self.pg0, [334], 64,
467 dst_ip=self.pg1.remote_ip6,
468 hlim=0)
469 self.pg0.add_stream(tx)
470
471 self.pg_enable_capture(self.pg_interfaces)
472 self.pg_start()
473
474 rx = self.pg0.get_capture()
475 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
476
477 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000478 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
479 # so this traffic should be dropped.
480 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800481 route_33_neos = VppMplsRoute(self, 33, 0,
482 [VppRoutePath(self.pg0.remote_ip4,
483 self.pg0.sw_if_index,
484 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000485 route_33_neos.add_vpp_config()
486
487 self.vapi.cli("clear trace")
488 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
489 self.pg0.add_stream(tx)
490
491 self.pg_enable_capture(self.pg_interfaces)
492 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100493 self.pg0.assert_nothing_captured(
494 remark="MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000495
496 #
497 # A recursive EOS x-connect, which resolves through another x-connect
498 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800499 route_34_eos = VppMplsRoute(self, 34, 1,
500 [VppRoutePath("0.0.0.0",
501 0xffffffff,
502 nh_via_label=32,
503 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000504 route_34_eos.add_vpp_config()
505
Neale Rannsad422ed2016-11-02 14:20:04 +0000506 tx = self.create_stream_labelled_ip4(self.pg0, [34])
507 self.pg0.add_stream(tx)
508
509 self.pg_enable_capture(self.pg_interfaces)
510 self.pg_start()
511
512 rx = self.pg0.get_capture()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800513 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
Neale Rannsad422ed2016-11-02 14:20:04 +0000514
515 #
Matej Klottondeb69842016-12-09 15:05:46 +0100516 # A recursive non-EOS x-connect, which resolves through another
517 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000518 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800519 route_34_neos = VppMplsRoute(self, 34, 0,
520 [VppRoutePath("0.0.0.0",
521 0xffffffff,
522 nh_via_label=32,
523 labels=[44, 46])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000524 route_34_neos.add_vpp_config()
525
526 self.vapi.cli("clear trace")
527 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
528 self.pg0.add_stream(tx)
529
530 self.pg_enable_capture(self.pg_interfaces)
531 self.pg_start()
532
533 rx = self.pg0.get_capture()
Matej Klottondeb69842016-12-09 15:05:46 +0100534 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Rannsad422ed2016-11-02 14:20:04 +0000535 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
536
537 #
Matej Klottondeb69842016-12-09 15:05:46 +0100538 # an recursive IP route that resolves through the recursive non-eos
539 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000540 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800541 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
542 [VppRoutePath("0.0.0.0",
543 0xffffffff,
544 nh_via_label=34,
545 labels=[55])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000546 ip_10_0_0_1.add_vpp_config()
547
548 self.vapi.cli("clear trace")
549 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
550 self.pg0.add_stream(tx)
551
552 self.pg_enable_capture(self.pg_interfaces)
553 self.pg_start()
554
555 rx = self.pg0.get_capture()
556 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
557
558 ip_10_0_0_1.remove_vpp_config()
559 route_34_neos.remove_vpp_config()
560 route_34_eos.remove_vpp_config()
561 route_33_neos.remove_vpp_config()
562 route_33_eos.remove_vpp_config()
563 route_32_neos.remove_vpp_config()
564 route_32_eos.remove_vpp_config()
565
566 def test_bind(self):
567 """ MPLS Local Label Binding test """
568
569 #
570 # Add a non-recursive route with a single out label
571 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800572 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
573 [VppRoutePath(self.pg0.remote_ip4,
574 self.pg0.sw_if_index,
575 labels=[45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000576 route_10_0_0_1.add_vpp_config()
577
578 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800579 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000580 binding.add_vpp_config()
581
582 # non-EOS stream
583 self.vapi.cli("clear trace")
584 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
585 self.pg0.add_stream(tx)
586
587 self.pg_enable_capture(self.pg_interfaces)
588 self.pg_start()
589
590 rx = self.pg0.get_capture()
591 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
592
593 # EOS stream
594 self.vapi.cli("clear trace")
595 tx = self.create_stream_labelled_ip4(self.pg0, [44])
596 self.pg0.add_stream(tx)
597
598 self.pg_enable_capture(self.pg_interfaces)
599 self.pg_start()
600
601 rx = self.pg0.get_capture()
602 self.verify_capture_labelled(self.pg0, rx, tx, [45])
603
604 # IP stream
605 self.vapi.cli("clear trace")
606 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
607 self.pg0.add_stream(tx)
608
609 self.pg_enable_capture(self.pg_interfaces)
610 self.pg_start()
611
612 rx = self.pg0.get_capture()
613 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
614
615 #
616 # cleanup
617 #
618 binding.remove_vpp_config()
619 route_10_0_0_1.remove_vpp_config()
620
621 def test_imposition(self):
622 """ MPLS label imposition test """
623
624 #
625 # Add a non-recursive route with a single out label
626 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800627 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
628 [VppRoutePath(self.pg0.remote_ip4,
629 self.pg0.sw_if_index,
630 labels=[32])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000631 route_10_0_0_1.add_vpp_config()
632
633 #
634 # a stream that matches the route for 10.0.0.1
635 # PG0 is in the default table
636 #
637 self.vapi.cli("clear trace")
638 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
639 self.pg0.add_stream(tx)
640
641 self.pg_enable_capture(self.pg_interfaces)
642 self.pg_start()
643
644 rx = self.pg0.get_capture()
645 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
646
647 #
648 # Add a non-recursive route with a 3 out labels
649 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800650 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
651 [VppRoutePath(self.pg0.remote_ip4,
652 self.pg0.sw_if_index,
653 labels=[32, 33, 34])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000654 route_10_0_0_2.add_vpp_config()
655
656 #
657 # a stream that matches the route for 10.0.0.1
658 # PG0 is in the default table
659 #
660 self.vapi.cli("clear trace")
661 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
662 self.pg0.add_stream(tx)
663
664 self.pg_enable_capture(self.pg_interfaces)
665 self.pg_start()
666
667 rx = self.pg0.get_capture()
668 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
669
670 #
Matej Klottondeb69842016-12-09 15:05:46 +0100671 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000672 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800673 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
674 [VppRoutePath("10.0.0.1",
675 0xffffffff,
676 labels=[44])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000677 route_11_0_0_1.add_vpp_config()
678
679 #
680 # a stream that matches the route for 11.0.0.1, should pick up
681 # the label stack for 11.0.0.1 and 10.0.0.1
682 #
683 self.vapi.cli("clear trace")
684 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
685 self.pg0.add_stream(tx)
686
687 self.pg_enable_capture(self.pg_interfaces)
688 self.pg_start()
689
690 rx = self.pg0.get_capture()
691 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
692
693 #
694 # add a recursive path, with 2 labels, via the 3 label route
695 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800696 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
697 [VppRoutePath("10.0.0.2",
698 0xffffffff,
699 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000700 route_11_0_0_2.add_vpp_config()
701
702 #
703 # a stream that matches the route for 11.0.0.1, should pick up
704 # the label stack for 11.0.0.1 and 10.0.0.1
705 #
706 self.vapi.cli("clear trace")
707 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
708 self.pg0.add_stream(tx)
709
710 self.pg_enable_capture(self.pg_interfaces)
711 self.pg_start()
712
713 rx = self.pg0.get_capture()
714 self.verify_capture_labelled_ip4(
715 self.pg0, rx, tx, [32, 33, 34, 44, 45])
716
717 #
718 # cleanup
719 #
720 route_11_0_0_2.remove_vpp_config()
721 route_11_0_0_1.remove_vpp_config()
722 route_10_0_0_2.remove_vpp_config()
723 route_10_0_0_1.remove_vpp_config()
724
725 def test_tunnel(self):
726 """ MPLS Tunnel Tests """
727
728 #
729 # Create a tunnel with a single out label
730 #
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800731 mpls_tun = VppMPLSTunnelInterface(self,
732 [VppRoutePath(self.pg0.remote_ip4,
733 self.pg0.sw_if_index,
734 labels=[44, 46])])
735 mpls_tun.add_vpp_config()
736 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000737
738 #
739 # add an unlabelled route through the new tunnel
740 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800741 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
742 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800743 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800744 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000745
746 self.vapi.cli("clear trace")
747 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
748 self.pg0.add_stream(tx)
749
750 self.pg_enable_capture(self.pg_interfaces)
751 self.pg_start()
752
753 rx = self.pg0.get_capture()
754 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000755
Neale Ranns8c4611b2017-05-23 03:43:47 -0700756 #
757 # add a labelled route through the new tunnel
758 #
759 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
760 [VppRoutePath("0.0.0.0",
761 mpls_tun._sw_if_index,
762 labels=[33])])
763 route_10_0_0_4.add_vpp_config()
764
765 self.vapi.cli("clear trace")
766 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
767 self.pg0.add_stream(tx)
768
769 self.pg_enable_capture(self.pg_interfaces)
770 self.pg_start()
771
772 rx = self.pg0.get_capture()
773 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
774 ttl=63, top=2)
775
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000776 def test_v4_exp_null(self):
777 """ MPLS V4 Explicit NULL test """
778
779 #
780 # The first test case has an MPLS TTL of 0
781 # all packet should be dropped
782 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000783 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000784 self.pg0.add_stream(tx)
785
786 self.pg_enable_capture(self.pg_interfaces)
787 self.pg_start()
788
Klement Sekera9225dee2016-12-12 08:36:58 +0100789 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000790
791 #
792 # a stream with a non-zero MPLS TTL
793 # PG0 is in the default table
794 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000795 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000796 self.pg0.add_stream(tx)
797
798 self.pg_enable_capture(self.pg_interfaces)
799 self.pg_start()
800
801 rx = self.pg0.get_capture()
802 self.verify_capture_ip4(self.pg0, rx, tx)
803
804 #
805 # a stream with a non-zero MPLS TTL
806 # PG1 is in table 1
807 # we are ensuring the post-pop lookup occurs in the VRF table
808 #
809 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000810 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000811 self.pg1.add_stream(tx)
812
813 self.pg_enable_capture(self.pg_interfaces)
814 self.pg_start()
815
816 rx = self.pg1.get_capture()
817 self.verify_capture_ip4(self.pg0, rx, tx)
818
819 def test_v6_exp_null(self):
820 """ MPLS V6 Explicit NULL test """
821
822 #
823 # a stream with a non-zero MPLS TTL
824 # PG0 is in the default table
825 #
826 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000827 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000828 self.pg0.add_stream(tx)
829
830 self.pg_enable_capture(self.pg_interfaces)
831 self.pg_start()
832
833 rx = self.pg0.get_capture()
834 self.verify_capture_ip6(self.pg0, rx, tx)
835
836 #
837 # a stream with a non-zero MPLS TTL
838 # PG1 is in table 1
839 # we are ensuring the post-pop lookup occurs in the VRF table
840 #
841 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000842 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000843 self.pg1.add_stream(tx)
844
845 self.pg_enable_capture(self.pg_interfaces)
846 self.pg_start()
847
848 rx = self.pg1.get_capture()
849 self.verify_capture_ip6(self.pg0, rx, tx)
850
Neale Rannscb630ff2016-12-14 13:31:29 +0100851 def test_deag(self):
852 """ MPLS Deagg """
853
854 #
855 # A de-agg route - next-hop lookup in default table
856 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800857 route_34_eos = VppMplsRoute(self, 34, 1,
858 [VppRoutePath("0.0.0.0",
859 0xffffffff,
860 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100861 route_34_eos.add_vpp_config()
862
863 #
864 # ping an interface in the default table
865 # PG0 is in the default table
866 #
867 self.vapi.cli("clear trace")
868 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
869 ip_itf=self.pg0)
870 self.pg0.add_stream(tx)
871
872 self.pg_enable_capture(self.pg_interfaces)
873 self.pg_start()
874
875 rx = self.pg0.get_capture()
876 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
877
878 #
879 # A de-agg route - next-hop lookup in non-default table
880 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800881 route_35_eos = VppMplsRoute(self, 35, 1,
882 [VppRoutePath("0.0.0.0",
883 0xffffffff,
884 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100885 route_35_eos.add_vpp_config()
886
887 #
888 # ping an interface in the non-default table
889 # PG0 is in the default table. packet arrive labelled in the
890 # default table and egress unlabelled in the non-default
891 #
892 self.vapi.cli("clear trace")
Klement Sekeradab231a2016-12-21 08:50:14 +0100893 tx = self.create_stream_labelled_ip4(
894 self.pg0, [35], ping=1, ip_itf=self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +0100895 self.pg0.add_stream(tx)
896
897 self.pg_enable_capture(self.pg_interfaces)
898 self.pg_start()
899
Klement Sekeradab231a2016-12-21 08:50:14 +0100900 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
901 rx = self.pg1.get_capture(packet_count)
Neale Rannscb630ff2016-12-14 13:31:29 +0100902 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
903
Neale Ranns6af1c042017-05-26 03:48:53 -0700904 #
905 # Double pop
906 #
907 route_36_neos = VppMplsRoute(self, 36, 0,
908 [VppRoutePath("0.0.0.0",
909 0xffffffff)])
910 route_36_neos.add_vpp_config()
911
912 self.vapi.cli("clear trace")
913 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
914 ping=1, ip_itf=self.pg1)
915 self.pg0.add_stream(tx)
916
917 self.pg_enable_capture(self.pg_interfaces)
918 self.pg_start()
919
920 rx = self.pg1.get_capture(len(tx))
921 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
922
923 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +0100924 route_35_eos.remove_vpp_config()
925 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000926
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800927 def test_interface_rx(self):
928 """ MPLS Interface Receive """
929
930 #
931 # Add a non-recursive route that will forward the traffic
932 # post-interface-rx
933 #
934 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
935 table_id=1,
936 paths=[VppRoutePath(self.pg1.remote_ip4,
937 self.pg1.sw_if_index)])
938 route_10_0_0_1.add_vpp_config()
939
940 #
941 # An interface receive label that maps traffic to RX on interface
942 # pg1
943 # by injecting the packet in on pg0, which is in table 0
944 # doing an interface-rx on pg1 and matching a route in table 1
945 # if the packet egresses, then we must have swapped to pg1
946 # so as to have matched the route in table 1
947 #
948 route_34_eos = VppMplsRoute(self, 34, 1,
949 [VppRoutePath("0.0.0.0",
950 self.pg1.sw_if_index,
951 is_interface_rx=1)])
952 route_34_eos.add_vpp_config()
953
954 #
955 # ping an interface in the default table
956 # PG0 is in the default table
957 #
958 self.vapi.cli("clear trace")
959 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
960 dst_ip="10.0.0.1")
961 self.pg0.add_stream(tx)
962
963 self.pg_enable_capture(self.pg_interfaces)
964 self.pg_start()
965
966 rx = self.pg1.get_capture(257)
967 self.verify_capture_ip4(self.pg1, rx, tx)
968
969 def test_mcast_mid_point(self):
970 """ MPLS Multicast Mid Point """
971
972 #
973 # Add a non-recursive route that will forward the traffic
974 # post-interface-rx
975 #
976 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
977 table_id=1,
978 paths=[VppRoutePath(self.pg1.remote_ip4,
979 self.pg1.sw_if_index)])
980 route_10_0_0_1.add_vpp_config()
981
982 #
983 # Add a mcast entry that replicate to pg2 and pg3
984 # and replicate to a interface-rx (like a bud node would)
985 #
986 route_3400_eos = VppMplsRoute(self, 3400, 1,
987 [VppRoutePath(self.pg2.remote_ip4,
988 self.pg2.sw_if_index,
989 labels=[3401]),
990 VppRoutePath(self.pg3.remote_ip4,
991 self.pg3.sw_if_index,
992 labels=[3402]),
993 VppRoutePath("0.0.0.0",
994 self.pg1.sw_if_index,
995 is_interface_rx=1)],
996 is_multicast=1)
997 route_3400_eos.add_vpp_config()
998
999 #
1000 # ping an interface in the default table
1001 # PG0 is in the default table
1002 #
1003 self.vapi.cli("clear trace")
1004 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
1005 dst_ip="10.0.0.1")
1006 self.pg0.add_stream(tx)
1007
1008 self.pg_enable_capture(self.pg_interfaces)
1009 self.pg_start()
1010
1011 rx = self.pg1.get_capture(257)
1012 self.verify_capture_ip4(self.pg1, rx, tx)
1013
1014 rx = self.pg2.get_capture(257)
1015 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
1016 rx = self.pg3.get_capture(257)
1017 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
1018
1019 def test_mcast_head(self):
1020 """ MPLS Multicast Head-end """
1021
1022 #
1023 # Create a multicast tunnel with two replications
1024 #
1025 mpls_tun = VppMPLSTunnelInterface(self,
1026 [VppRoutePath(self.pg2.remote_ip4,
1027 self.pg2.sw_if_index,
1028 labels=[42]),
1029 VppRoutePath(self.pg3.remote_ip4,
1030 self.pg3.sw_if_index,
1031 labels=[43])],
1032 is_multicast=1)
1033 mpls_tun.add_vpp_config()
1034 mpls_tun.admin_up()
1035
1036 #
1037 # add an unlabelled route through the new tunnel
1038 #
1039 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1040 [VppRoutePath("0.0.0.0",
1041 mpls_tun._sw_if_index)])
1042 route_10_0_0_3.add_vpp_config()
1043
1044 self.vapi.cli("clear trace")
1045 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1046 self.pg0.add_stream(tx)
1047
1048 self.pg_enable_capture(self.pg_interfaces)
1049 self.pg_start()
1050
1051 rx = self.pg2.get_capture(257)
1052 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
1053 rx = self.pg3.get_capture(257)
1054 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
1055
1056 #
1057 # An an IP multicast route via the tunnel
1058 # A (*,G).
1059 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1060 #
1061 route_232_1_1_1 = VppIpMRoute(
1062 self,
1063 "0.0.0.0",
1064 "232.1.1.1", 32,
1065 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1066 [VppMRoutePath(self.pg0.sw_if_index,
1067 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1068 VppMRoutePath(mpls_tun._sw_if_index,
1069 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1070 route_232_1_1_1.add_vpp_config()
1071
1072 self.vapi.cli("clear trace")
1073 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1074 self.pg0.add_stream(tx)
1075
1076 self.pg_enable_capture(self.pg_interfaces)
1077 self.pg_start()
1078
1079 rx = self.pg2.get_capture(257)
1080 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
1081 rx = self.pg3.get_capture(257)
1082 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
1083
Neale Ranns31426c62017-05-24 10:32:58 -07001084 def test_mcast_ip4_tail(self):
1085 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001086
1087 #
1088 # Add a multicast route that will forward the traffic
1089 # post-disposition
1090 #
1091 route_232_1_1_1 = VppIpMRoute(
1092 self,
1093 "0.0.0.0",
1094 "232.1.1.1", 32,
1095 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1096 table_id=1,
1097 paths=[VppMRoutePath(self.pg1.sw_if_index,
1098 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1099 route_232_1_1_1.add_vpp_config()
1100
1101 #
1102 # An interface receive label that maps traffic to RX on interface
1103 # pg1
1104 # by injecting the packet in on pg0, which is in table 0
1105 # doing an rpf-id and matching a route in table 1
1106 # if the packet egresses, then we must have matched the route in
1107 # table 1
1108 #
1109 route_34_eos = VppMplsRoute(self, 34, 1,
1110 [VppRoutePath("0.0.0.0",
1111 self.pg1.sw_if_index,
1112 nh_table_id=1,
1113 rpf_id=55)],
1114 is_multicast=1)
1115
1116 route_34_eos.add_vpp_config()
1117
1118 #
1119 # Drop due to interface lookup miss
1120 #
1121 self.vapi.cli("clear trace")
1122 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1123 dst_ip="232.1.1.1", n=1)
1124 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1125
1126 #
1127 # set the RPF-ID of the enrtry to match the input packet's
1128 #
1129 route_232_1_1_1.update_rpf_id(55)
1130
1131 self.vapi.cli("clear trace")
1132 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1133 dst_ip="232.1.1.1", n=257)
1134 self.pg0.add_stream(tx)
1135
1136 self.pg_enable_capture(self.pg_interfaces)
1137 self.pg_start()
1138
1139 rx = self.pg1.get_capture(257)
1140 self.verify_capture_ip4(self.pg1, rx, tx)
1141
1142 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001143 # disposed packets have an invalid IPv4 checkusm
1144 #
1145 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1146 dst_ip="232.1.1.1", n=65,
1147 chksum=1)
1148 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1149
1150 #
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001151 # set the RPF-ID of the enrtry to not match the input packet's
1152 #
1153 route_232_1_1_1.update_rpf_id(56)
1154 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1155 dst_ip="232.1.1.1")
1156 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1157
Neale Ranns31426c62017-05-24 10:32:58 -07001158 def test_mcast_ip6_tail(self):
1159 """ MPLS IPv6 Multicast Tail """
1160
1161 #
1162 # Add a multicast route that will forward the traffic
1163 # post-disposition
1164 #
1165 route_ff = VppIpMRoute(
1166 self,
1167 "::",
1168 "ff01::1", 32,
1169 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1170 table_id=1,
1171 paths=[VppMRoutePath(self.pg1.sw_if_index,
1172 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1173 is_ip6=1)
1174 route_ff.add_vpp_config()
1175
1176 #
1177 # An interface receive label that maps traffic to RX on interface
1178 # pg1
1179 # by injecting the packet in on pg0, which is in table 0
1180 # doing an rpf-id and matching a route in table 1
1181 # if the packet egresses, then we must have matched the route in
1182 # table 1
1183 #
1184 route_34_eos = VppMplsRoute(
1185 self, 34, 1,
1186 [VppRoutePath("::",
1187 self.pg1.sw_if_index,
1188 nh_table_id=1,
1189 rpf_id=55,
Neale Rannsda78f952017-05-24 09:15:43 -07001190 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns31426c62017-05-24 10:32:58 -07001191 is_multicast=1)
1192
1193 route_34_eos.add_vpp_config()
1194
1195 #
1196 # Drop due to interface lookup miss
1197 #
1198 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1199 dst_ip="ff01::1")
1200
1201 #
1202 # set the RPF-ID of the enrtry to match the input packet's
1203 #
1204 route_ff.update_rpf_id(55)
1205
1206 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1207 dst_ip="ff01::1")
1208 self.pg0.add_stream(tx)
1209
1210 self.pg_enable_capture(self.pg_interfaces)
1211 self.pg_start()
1212
1213 rx = self.pg1.get_capture(257)
1214 self.verify_capture_ip6(self.pg1, rx, tx)
1215
1216 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001217 # disposed packets have hop-limit = 1
1218 #
1219 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1220 dst_ip="ff01::1", hlim=1)
1221 self.send_and_assert_no_replies(self.pg0, tx, "Hop Limt Expired")
1222
1223 #
Neale Ranns31426c62017-05-24 10:32:58 -07001224 # set the RPF-ID of the enrtry to not match the input packet's
1225 #
1226 route_ff.update_rpf_id(56)
1227 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1228 dst_ip="ff01::1")
1229 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1230
Neale Ranns180279b2017-03-16 15:49:09 -04001231
1232class TestMPLSDisabled(VppTestCase):
1233 """ MPLS disabled """
1234
1235 def setUp(self):
1236 super(TestMPLSDisabled, self).setUp()
1237
1238 # create 2 pg interfaces
1239 self.create_pg_interfaces(range(2))
1240
Neale Ranns15002542017-09-10 04:39:11 -07001241 self.tbl = VppMplsTable(self, 0)
1242 self.tbl.add_vpp_config()
1243
Neale Ranns180279b2017-03-16 15:49:09 -04001244 # PG0 is MPLS enalbed
1245 self.pg0.admin_up()
1246 self.pg0.config_ip4()
1247 self.pg0.resolve_arp()
1248 self.pg0.enable_mpls()
1249
1250 # PG 1 is not MPLS enabled
1251 self.pg1.admin_up()
1252
1253 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001254 for i in self.pg_interfaces:
1255 i.unconfig_ip4()
1256 i.admin_down()
1257
Neale Ranns15002542017-09-10 04:39:11 -07001258 self.pg0.disable_mpls()
1259 super(TestMPLSDisabled, self).tearDown()
1260
Neale Ranns180279b2017-03-16 15:49:09 -04001261 def send_and_assert_no_replies(self, intf, pkts, remark):
1262 intf.add_stream(pkts)
1263 self.pg_enable_capture(self.pg_interfaces)
1264 self.pg_start()
1265 for i in self.pg_interfaces:
1266 i.get_capture(0)
1267 i.assert_nothing_captured(remark=remark)
1268
1269 def test_mpls_disabled(self):
1270 """ MPLS Disabled """
1271
1272 tx = (Ether(src=self.pg1.remote_mac,
1273 dst=self.pg1.local_mac) /
1274 MPLS(label=32, ttl=64) /
1275 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1276 UDP(sport=1234, dport=1234) /
1277 Raw('\xa5' * 100))
1278
1279 #
1280 # A simple MPLS xconnect - eos label in label out
1281 #
1282 route_32_eos = VppMplsRoute(self, 32, 1,
1283 [VppRoutePath(self.pg0.remote_ip4,
1284 self.pg0.sw_if_index,
1285 labels=[33])])
1286 route_32_eos.add_vpp_config()
1287
1288 #
1289 # PG1 does not forward IP traffic
1290 #
1291 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1292
1293 #
1294 # MPLS enable PG1
1295 #
1296 self.pg1.enable_mpls()
1297
1298 #
1299 # Now we get packets through
1300 #
1301 self.pg1.add_stream(tx)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304
1305 rx = self.pg0.get_capture(1)
1306
1307 #
1308 # Disable PG1
1309 #
1310 self.pg1.disable_mpls()
1311
1312 #
1313 # PG1 does not forward IP traffic
1314 #
1315 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1316 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1317
1318
Neale Rannsf12a83f2017-04-18 09:09:40 -07001319class TestMPLSPIC(VppTestCase):
1320 """ MPLS PIC edge convergence """
1321
1322 def setUp(self):
1323 super(TestMPLSPIC, self).setUp()
1324
1325 # create 2 pg interfaces
1326 self.create_pg_interfaces(range(4))
1327
Neale Ranns15002542017-09-10 04:39:11 -07001328 mpls_tbl = VppMplsTable(self, 0)
1329 mpls_tbl.add_vpp_config()
1330 tbl4 = VppIpTable(self, 1)
1331 tbl4.add_vpp_config()
1332 tbl6 = VppIpTable(self, 1, is_ip6=1)
1333 tbl6.add_vpp_config()
1334
Neale Rannsf12a83f2017-04-18 09:09:40 -07001335 # core links
1336 self.pg0.admin_up()
1337 self.pg0.config_ip4()
1338 self.pg0.resolve_arp()
1339 self.pg0.enable_mpls()
1340 self.pg1.admin_up()
1341 self.pg1.config_ip4()
1342 self.pg1.resolve_arp()
1343 self.pg1.enable_mpls()
1344
1345 # VRF (customer facing) link
1346 self.pg2.admin_up()
1347 self.pg2.set_table_ip4(1)
1348 self.pg2.config_ip4()
1349 self.pg2.resolve_arp()
1350 self.pg2.set_table_ip6(1)
1351 self.pg2.config_ip6()
1352 self.pg2.resolve_ndp()
1353 self.pg3.admin_up()
1354 self.pg3.set_table_ip4(1)
1355 self.pg3.config_ip4()
1356 self.pg3.resolve_arp()
1357 self.pg3.set_table_ip6(1)
1358 self.pg3.config_ip6()
1359 self.pg3.resolve_ndp()
1360
1361 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001362 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001363 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001364 for i in self.pg_interfaces:
1365 i.unconfig_ip4()
1366 i.unconfig_ip6()
1367 i.set_table_ip4(0)
1368 i.set_table_ip6(0)
1369 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001370 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001371
1372 def test_mpls_ibgp_pic(self):
1373 """ MPLS iBGP PIC edge convergence
1374
1375 1) setup many iBGP VPN routes via a pair of iBGP peers.
1376 2) Check EMCP forwarding to these peers
1377 3) withdraw the IGP route to one of these peers.
1378 4) check forwarding continues to the remaining peer
1379 """
1380
1381 #
1382 # IGP+LDP core routes
1383 #
1384 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1385 [VppRoutePath(self.pg0.remote_ip4,
1386 self.pg0.sw_if_index,
1387 labels=[45])])
1388 core_10_0_0_45.add_vpp_config()
1389
1390 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1391 [VppRoutePath(self.pg1.remote_ip4,
1392 self.pg1.sw_if_index,
1393 labels=[46])])
1394 core_10_0_0_46.add_vpp_config()
1395
1396 #
1397 # Lot's of VPN routes. We need more the 64 so VPP will build
1398 # the fast convergence indirection
1399 #
1400 vpn_routes = []
1401 pkts = []
1402 for ii in range(64):
1403 dst = "192.168.1.%d" % ii
1404 vpn_routes.append(VppIpRoute(self, dst, 32,
1405 [VppRoutePath("10.0.0.45",
1406 0xffffffff,
1407 labels=[145],
1408 is_resolve_host=1),
1409 VppRoutePath("10.0.0.46",
1410 0xffffffff,
1411 labels=[146],
1412 is_resolve_host=1)],
1413 table_id=1))
1414 vpn_routes[ii].add_vpp_config()
1415
1416 pkts.append(Ether(dst=self.pg2.local_mac,
1417 src=self.pg2.remote_mac) /
1418 IP(src=self.pg2.remote_ip4, dst=dst) /
1419 UDP(sport=1234, dport=1234) /
1420 Raw('\xa5' * 100))
1421
1422 #
1423 # Send the packet stream (one pkt to each VPN route)
1424 # - expect a 50-50 split of the traffic
1425 #
1426 self.pg2.add_stream(pkts)
1427 self.pg_enable_capture(self.pg_interfaces)
1428 self.pg_start()
1429
1430 rx0 = self.pg0._get_capture(1)
1431 rx1 = self.pg1._get_capture(1)
1432
1433 # not testig the LB hashing algorithm so we're not concerned
1434 # with the split ratio, just as long as neither is 0
1435 self.assertNotEqual(0, len(rx0))
1436 self.assertNotEqual(0, len(rx1))
1437
1438 #
1439 # use a test CLI command to stop the FIB walk process, this
1440 # will prevent the FIB converging the VPN routes and thus allow
1441 # us to probe the interim (psot-fail, pre-converge) state
1442 #
1443 self.vapi.ppcli("test fib-walk-process disable")
1444
1445 #
1446 # Withdraw one of the IGP routes
1447 #
1448 core_10_0_0_46.remove_vpp_config()
1449
1450 #
1451 # now all packets should be forwarded through the remaining peer
1452 #
1453 self.vapi.ppcli("clear trace")
1454 self.pg2.add_stream(pkts)
1455 self.pg_enable_capture(self.pg_interfaces)
1456 self.pg_start()
1457
1458 rx0 = self.pg0.get_capture(len(pkts))
1459
1460 #
1461 # enable the FIB walk process to converge the FIB
1462 #
1463 self.vapi.ppcli("test fib-walk-process enable")
1464
1465 #
1466 # packets should still be forwarded through the remaining peer
1467 #
1468 self.pg2.add_stream(pkts)
1469 self.pg_enable_capture(self.pg_interfaces)
1470 self.pg_start()
1471
1472 rx0 = self.pg0.get_capture(64)
1473
1474 #
1475 # Add the IGP route back and we return to load-balancing
1476 #
1477 core_10_0_0_46.add_vpp_config()
1478
1479 self.pg2.add_stream(pkts)
1480 self.pg_enable_capture(self.pg_interfaces)
1481 self.pg_start()
1482
1483 rx0 = self.pg0._get_capture(1)
1484 rx1 = self.pg1._get_capture(1)
1485 self.assertNotEqual(0, len(rx0))
1486 self.assertNotEqual(0, len(rx1))
1487
1488 def test_mpls_ebgp_pic(self):
1489 """ MPLS eBGP PIC edge convergence
1490
1491 1) setup many eBGP VPN routes via a pair of eBGP peers
1492 2) Check EMCP forwarding to these peers
1493 3) withdraw one eBGP path - expect LB across remaining eBGP
1494 """
1495
1496 #
1497 # Lot's of VPN routes. We need more the 64 so VPP will build
1498 # the fast convergence indirection
1499 #
1500 vpn_routes = []
1501 vpn_bindings = []
1502 pkts = []
1503 for ii in range(64):
1504 dst = "192.168.1.%d" % ii
1505 local_label = 1600 + ii
1506 vpn_routes.append(VppIpRoute(self, dst, 32,
1507 [VppRoutePath(self.pg2.remote_ip4,
1508 0xffffffff,
1509 nh_table_id=1,
1510 is_resolve_attached=1),
1511 VppRoutePath(self.pg3.remote_ip4,
1512 0xffffffff,
1513 nh_table_id=1,
1514 is_resolve_attached=1)],
1515 table_id=1))
1516 vpn_routes[ii].add_vpp_config()
1517
1518 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1519 ip_table_id=1))
1520 vpn_bindings[ii].add_vpp_config()
1521
1522 pkts.append(Ether(dst=self.pg0.local_mac,
1523 src=self.pg0.remote_mac) /
1524 MPLS(label=local_label, ttl=64) /
1525 IP(src=self.pg0.remote_ip4, dst=dst) /
1526 UDP(sport=1234, dport=1234) /
1527 Raw('\xa5' * 100))
1528
1529 self.pg0.add_stream(pkts)
1530 self.pg_enable_capture(self.pg_interfaces)
1531 self.pg_start()
1532
1533 rx0 = self.pg2._get_capture(1)
1534 rx1 = self.pg3._get_capture(1)
1535 self.assertNotEqual(0, len(rx0))
1536 self.assertNotEqual(0, len(rx1))
1537
1538 #
1539 # use a test CLI command to stop the FIB walk process, this
1540 # will prevent the FIB converging the VPN routes and thus allow
1541 # us to probe the interim (psot-fail, pre-converge) state
1542 #
1543 self.vapi.ppcli("test fib-walk-process disable")
1544
1545 #
1546 # withdraw the connected prefix on the interface.
1547 #
1548 self.pg2.unconfig_ip4()
1549
1550 #
1551 # now all packets should be forwarded through the remaining peer
1552 #
1553 self.pg0.add_stream(pkts)
1554 self.pg_enable_capture(self.pg_interfaces)
1555 self.pg_start()
1556
1557 rx0 = self.pg3.get_capture(len(pkts))
1558
1559 #
1560 # enable the FIB walk process to converge the FIB
1561 #
1562 self.vapi.ppcli("test fib-walk-process enable")
1563 self.pg0.add_stream(pkts)
1564 self.pg_enable_capture(self.pg_interfaces)
1565 self.pg_start()
1566
1567 rx0 = self.pg3.get_capture(len(pkts))
1568
1569 #
1570 # put the connecteds back
1571 #
1572 self.pg2.config_ip4()
1573
1574 self.pg0.add_stream(pkts)
1575 self.pg_enable_capture(self.pg_interfaces)
1576 self.pg_start()
1577
1578 rx0 = self.pg2._get_capture(1)
1579 rx1 = self.pg3._get_capture(1)
1580 self.assertNotEqual(0, len(rx0))
1581 self.assertNotEqual(0, len(rx1))
1582
1583 def test_mpls_v6_ebgp_pic(self):
1584 """ MPLSv6 eBGP PIC edge convergence
1585
1586 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1587 2) Check EMCP forwarding to these peers
1588 3) withdraw one eBGP path - expect LB across remaining eBGP
1589 """
1590
1591 #
1592 # Lot's of VPN routes. We need more the 64 so VPP will build
1593 # the fast convergence indirection
1594 #
1595 vpn_routes = []
1596 vpn_bindings = []
1597 pkts = []
1598 for ii in range(64):
1599 dst = "3000::%d" % ii
1600 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001601 vpn_routes.append(VppIpRoute(
1602 self, dst, 128,
1603 [VppRoutePath(self.pg2.remote_ip6,
1604 0xffffffff,
1605 nh_table_id=1,
1606 is_resolve_attached=1,
1607 proto=DpoProto.DPO_PROTO_IP6),
1608 VppRoutePath(self.pg3.remote_ip6,
1609 0xffffffff,
1610 nh_table_id=1,
1611 proto=DpoProto.DPO_PROTO_IP6,
1612 is_resolve_attached=1)],
1613 table_id=1,
1614 is_ip6=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001615 vpn_routes[ii].add_vpp_config()
1616
1617 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1618 ip_table_id=1,
1619 is_ip6=1))
1620 vpn_bindings[ii].add_vpp_config()
1621
1622 pkts.append(Ether(dst=self.pg0.local_mac,
1623 src=self.pg0.remote_mac) /
1624 MPLS(label=local_label, ttl=64) /
1625 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1626 UDP(sport=1234, dport=1234) /
1627 Raw('\xa5' * 100))
1628
1629 self.pg0.add_stream(pkts)
1630 self.pg_enable_capture(self.pg_interfaces)
1631 self.pg_start()
1632
1633 rx0 = self.pg2._get_capture(1)
1634 rx1 = self.pg3._get_capture(1)
1635 self.assertNotEqual(0, len(rx0))
1636 self.assertNotEqual(0, len(rx1))
1637
1638 #
1639 # use a test CLI command to stop the FIB walk process, this
1640 # will prevent the FIB converging the VPN routes and thus allow
1641 # us to probe the interim (psot-fail, pre-converge) state
1642 #
1643 self.vapi.ppcli("test fib-walk-process disable")
1644
1645 #
1646 # withdraw the connected prefix on the interface.
1647 # and shutdown the interface so the ND cache is flushed.
1648 #
1649 self.pg2.unconfig_ip6()
1650 self.pg2.admin_down()
1651
1652 #
1653 # now all packets should be forwarded through the remaining peer
1654 #
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1657 self.pg_start()
1658
1659 rx0 = self.pg3.get_capture(len(pkts))
1660
1661 #
1662 # enable the FIB walk process to converge the FIB
1663 #
1664 self.vapi.ppcli("test fib-walk-process enable")
1665 self.pg0.add_stream(pkts)
1666 self.pg_enable_capture(self.pg_interfaces)
1667 self.pg_start()
1668
1669 rx0 = self.pg3.get_capture(len(pkts))
1670
1671 #
1672 # put the connecteds back
1673 #
1674 self.pg2.admin_up()
1675 self.pg2.config_ip6()
1676
1677 self.pg0.add_stream(pkts)
1678 self.pg_enable_capture(self.pg_interfaces)
1679 self.pg_start()
1680
1681 rx0 = self.pg2._get_capture(1)
1682 rx1 = self.pg3._get_capture(1)
1683 self.assertNotEqual(0, len(rx0))
1684 self.assertNotEqual(0, len(rx1))
1685
1686
Neale Rannsda78f952017-05-24 09:15:43 -07001687class TestMPLSL2(VppTestCase):
1688 """ MPLS-L2 """
1689
1690 def setUp(self):
1691 super(TestMPLSL2, self).setUp()
1692
1693 # create 2 pg interfaces
1694 self.create_pg_interfaces(range(2))
1695
Neale Ranns15002542017-09-10 04:39:11 -07001696 # create the default MPLS table
1697 self.tables = []
1698 tbl = VppMplsTable(self, 0)
1699 tbl.add_vpp_config()
1700 self.tables.append(tbl)
1701
Neale Rannsda78f952017-05-24 09:15:43 -07001702 # use pg0 as the core facing interface
1703 self.pg0.admin_up()
1704 self.pg0.config_ip4()
1705 self.pg0.resolve_arp()
1706 self.pg0.enable_mpls()
1707
Neale Ranns15002542017-09-10 04:39:11 -07001708 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07001709 for i in self.pg_interfaces[1:]:
1710 i.admin_up()
1711
1712 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07001713 for i in self.pg_interfaces[1:]:
1714 i.admin_down()
1715
1716 self.pg0.disable_mpls()
1717 self.pg0.unconfig_ip4()
1718 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001719 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07001720
1721 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1722 ttl=255, top=None):
1723 if top is None:
1724 top = len(mpls_labels) - 1
1725
1726 capture = verify_filter(capture, sent)
1727
1728 self.assertEqual(len(capture), len(sent))
1729
1730 for i in range(len(capture)):
1731 tx = sent[i]
1732 rx = capture[i]
1733
1734 # the MPLS TTL is 255 since it enters a new tunnel
1735 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1736
1737 tx_eth = tx[Ether]
1738 rx_eth = Ether(str(rx[MPLS].payload))
1739
1740 self.assertEqual(rx_eth.src, tx_eth.src)
1741 self.assertEqual(rx_eth.dst, tx_eth.dst)
1742
1743 def test_vpws(self):
1744 """ Virtual Private Wire Service """
1745
1746 #
1747 # Create an MPLS tunnel that pushes 1 label
1748 #
1749 mpls_tun_1 = VppMPLSTunnelInterface(self,
1750 [VppRoutePath(self.pg0.remote_ip4,
1751 self.pg0.sw_if_index,
1752 labels=[42])],
1753 is_l2=1)
1754 mpls_tun_1.add_vpp_config()
1755 mpls_tun_1.admin_up()
1756
1757 #
1758 # Create a label entry to for 55 that does L2 input to the tunnel
1759 #
1760 route_55_eos = VppMplsRoute(
1761 self, 55, 1,
1762 [VppRoutePath("0.0.0.0",
1763 mpls_tun_1.sw_if_index,
1764 is_interface_rx=1,
1765 proto=DpoProto.DPO_PROTO_ETHERNET)])
1766 route_55_eos.add_vpp_config()
1767
1768 #
1769 # Cross-connect the tunnel with one of the customers L2 interfaces
1770 #
1771 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1772 mpls_tun_1.sw_if_index,
1773 enable=1)
1774 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1775 self.pg1.sw_if_index,
1776 enable=1)
1777
1778 #
1779 # inject a packet from the core
1780 #
1781 pcore = (Ether(dst=self.pg0.local_mac,
1782 src=self.pg0.remote_mac) /
1783 MPLS(label=55, ttl=64) /
1784 Ether(dst="00:00:de:ad:ba:be",
1785 src="00:00:de:ad:be:ef") /
1786 IP(src="10.10.10.10", dst="11.11.11.11") /
1787 UDP(sport=1234, dport=1234) /
1788 Raw('\xa5' * 100))
1789
1790 self.pg0.add_stream(pcore * 65)
1791 self.pg_enable_capture(self.pg_interfaces)
1792 self.pg_start()
1793
1794 rx0 = self.pg1.get_capture(65)
1795 tx = pcore[MPLS].payload
1796
1797 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1798 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1799
1800 #
1801 # Inject a packet from the custoer/L2 side
1802 #
1803 self.pg1.add_stream(tx * 65)
1804 self.pg_enable_capture(self.pg_interfaces)
1805 self.pg_start()
1806
1807 rx0 = self.pg0.get_capture(65)
1808
1809 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1810
1811 def test_vpls(self):
1812 """ Virtual Private LAN Service """
1813 #
1814 # Create an L2 MPLS tunnel
1815 #
1816 mpls_tun = VppMPLSTunnelInterface(self,
1817 [VppRoutePath(self.pg0.remote_ip4,
1818 self.pg0.sw_if_index,
1819 labels=[42])],
1820 is_l2=1)
1821 mpls_tun.add_vpp_config()
1822 mpls_tun.admin_up()
1823
1824 #
1825 # Create a label entry to for 55 that does L2 input to the tunnel
1826 #
1827 route_55_eos = VppMplsRoute(
1828 self, 55, 1,
1829 [VppRoutePath("0.0.0.0",
1830 mpls_tun.sw_if_index,
1831 is_interface_rx=1,
1832 proto=DpoProto.DPO_PROTO_ETHERNET)])
1833 route_55_eos.add_vpp_config()
1834
1835 #
1836 # add to tunnel to the customers bridge-domain
1837 #
1838 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1839 bd_id=1)
1840 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1841 bd_id=1)
1842
1843 #
1844 # Packet from the customer interface and from the core
1845 #
1846 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1847 src="00:00:de:ad:be:ef") /
1848 IP(src="10.10.10.10", dst="11.11.11.11") /
1849 UDP(sport=1234, dport=1234) /
1850 Raw('\xa5' * 100))
1851 p_core = (Ether(src="00:00:de:ad:ba:be",
1852 dst="00:00:de:ad:be:ef") /
1853 IP(dst="10.10.10.10", src="11.11.11.11") /
1854 UDP(sport=1234, dport=1234) /
1855 Raw('\xa5' * 100))
1856
1857 #
1858 # The BD is learning, so send in one of each packet to learn
1859 #
1860 p_core_encap = (Ether(dst=self.pg0.local_mac,
1861 src=self.pg0.remote_mac) /
1862 MPLS(label=55, ttl=64) /
1863 p_core)
1864
1865 self.pg1.add_stream(p_cust)
1866 self.pg_enable_capture(self.pg_interfaces)
1867 self.pg_start()
1868 self.pg0.add_stream(p_core_encap)
1869 self.pg_enable_capture(self.pg_interfaces)
1870 self.pg_start()
1871
1872 # we've learnt this so expect it be be forwarded
1873 rx0 = self.pg1.get_capture(1)
1874
1875 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1876 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1877
1878 #
1879 # now a stream in each direction
1880 #
1881 self.pg1.add_stream(p_cust * 65)
1882 self.pg_enable_capture(self.pg_interfaces)
1883 self.pg_start()
1884
1885 rx0 = self.pg0.get_capture(65)
1886
1887 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1888
1889 #
1890 # remove interfaces from customers bridge-domain
1891 #
1892 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1893 bd_id=1,
1894 enable=0)
1895 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1896 bd_id=1,
1897 enable=0)
1898
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001899if __name__ == '__main__':
1900 unittest.main(testRunner=VppTestRunner)