blob: aa5e67439b70107fa4cdd9ba4792a84f21590e7d [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 Rannsad422ed2016-11-02 14:20:04 +0000317 def test_swap(self):
318 """ MPLS label swap tests """
319
320 #
321 # A simple MPLS xconnect - eos label in label out
322 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800323 route_32_eos = VppMplsRoute(self, 32, 1,
324 [VppRoutePath(self.pg0.remote_ip4,
325 self.pg0.sw_if_index,
326 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000327 route_32_eos.add_vpp_config()
328
329 #
330 # a stream that matches the route for 10.0.0.1
331 # PG0 is in the default table
332 #
333 self.vapi.cli("clear trace")
334 tx = self.create_stream_labelled_ip4(self.pg0, [32])
335 self.pg0.add_stream(tx)
336
337 self.pg_enable_capture(self.pg_interfaces)
338 self.pg_start()
339
340 rx = self.pg0.get_capture()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800341 self.verify_capture_labelled(self.pg0, rx, tx, [33])
Neale Rannsad422ed2016-11-02 14:20:04 +0000342
343 #
344 # A simple MPLS xconnect - non-eos label in label out
345 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800346 route_32_neos = VppMplsRoute(self, 32, 0,
347 [VppRoutePath(self.pg0.remote_ip4,
348 self.pg0.sw_if_index,
349 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000350 route_32_neos.add_vpp_config()
351
352 #
353 # a stream that matches the route for 10.0.0.1
354 # PG0 is in the default table
355 #
356 self.vapi.cli("clear trace")
357 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
358 self.pg0.add_stream(tx)
359
360 self.pg_enable_capture(self.pg_interfaces)
361 self.pg_start()
362
363 rx = self.pg0.get_capture()
364 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
365
366 #
367 # An MPLS xconnect - EOS label in IP out
368 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800369 route_33_eos = VppMplsRoute(self, 33, 1,
370 [VppRoutePath(self.pg0.remote_ip4,
371 self.pg0.sw_if_index,
372 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000373 route_33_eos.add_vpp_config()
374
375 self.vapi.cli("clear trace")
376 tx = self.create_stream_labelled_ip4(self.pg0, [33])
377 self.pg0.add_stream(tx)
378
379 self.pg_enable_capture(self.pg_interfaces)
380 self.pg_start()
381
382 rx = self.pg0.get_capture()
383 self.verify_capture_ip4(self.pg0, rx, tx)
384
385 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700386 # disposed packets have an invalid IPv4 checkusm
387 #
388 tx = self.create_stream_labelled_ip4(self.pg0, [33],
389 dst_ip=self.pg0.remote_ip4,
390 n=65,
391 chksum=1)
392 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
393
394 #
395 # An MPLS xconnect - EOS label in IPv6 out
396 #
397 route_333_eos = VppMplsRoute(
398 self, 333, 1,
399 [VppRoutePath(self.pg0.remote_ip6,
400 self.pg0.sw_if_index,
401 labels=[],
402 proto=DpoProto.DPO_PROTO_IP6)])
403 route_333_eos.add_vpp_config()
404
405 self.vapi.cli("clear trace")
406 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64)
407 self.pg0.add_stream(tx)
408
409 self.pg_enable_capture(self.pg_interfaces)
410 self.pg_start()
411
412 rx = self.pg0.get_capture()
413 self.verify_capture_ip6(self.pg0, rx, tx)
414
415 #
416 # disposed packets have an TTL expired
417 #
418 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64,
419 dst_ip=self.pg1.remote_ip6,
420 hlim=1)
421
422 self.vapi.cli("clear trace")
423 tx = self.create_stream_labelled_ip6(self.pg0, [333], 64,
424 dst_ip=self.pg1.remote_ip6,
425 hlim=0)
426 self.pg0.add_stream(tx)
427
428 self.pg_enable_capture(self.pg_interfaces)
429 self.pg_start()
430
431 rx = self.pg0.get_capture()
432 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
433
434 #
435 # An MPLS xconnect - EOS label in IPv6 out w imp-null
436 #
437 route_334_eos = VppMplsRoute(
438 self, 334, 1,
439 [VppRoutePath(self.pg0.remote_ip6,
440 self.pg0.sw_if_index,
441 labels=[3],
442 proto=DpoProto.DPO_PROTO_IP6)])
443 route_334_eos.add_vpp_config()
444
445 self.vapi.cli("clear trace")
446 tx = self.create_stream_labelled_ip6(self.pg0, [334], 64)
447 self.pg0.add_stream(tx)
448
449 self.pg_enable_capture(self.pg_interfaces)
450 self.pg_start()
451
452 rx = self.pg0.get_capture()
453 self.verify_capture_ip6(self.pg0, rx, tx)
454
455 #
456 # disposed packets have an TTL expired
457 #
458 self.vapi.cli("clear trace")
459 tx = self.create_stream_labelled_ip6(self.pg0, [334], 64,
460 dst_ip=self.pg1.remote_ip6,
461 hlim=0)
462 self.pg0.add_stream(tx)
463
464 self.pg_enable_capture(self.pg_interfaces)
465 self.pg_start()
466
467 rx = self.pg0.get_capture()
468 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
469
470 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000471 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
472 # so this traffic should be dropped.
473 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800474 route_33_neos = VppMplsRoute(self, 33, 0,
475 [VppRoutePath(self.pg0.remote_ip4,
476 self.pg0.sw_if_index,
477 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000478 route_33_neos.add_vpp_config()
479
480 self.vapi.cli("clear trace")
481 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
482 self.pg0.add_stream(tx)
483
484 self.pg_enable_capture(self.pg_interfaces)
485 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100486 self.pg0.assert_nothing_captured(
487 remark="MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000488
489 #
490 # A recursive EOS x-connect, which resolves through another x-connect
491 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800492 route_34_eos = VppMplsRoute(self, 34, 1,
493 [VppRoutePath("0.0.0.0",
494 0xffffffff,
495 nh_via_label=32,
496 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000497 route_34_eos.add_vpp_config()
498
Neale Rannsad422ed2016-11-02 14:20:04 +0000499 tx = self.create_stream_labelled_ip4(self.pg0, [34])
500 self.pg0.add_stream(tx)
501
502 self.pg_enable_capture(self.pg_interfaces)
503 self.pg_start()
504
505 rx = self.pg0.get_capture()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800506 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
Neale Rannsad422ed2016-11-02 14:20:04 +0000507
508 #
Matej Klottondeb69842016-12-09 15:05:46 +0100509 # A recursive non-EOS x-connect, which resolves through another
510 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000511 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800512 route_34_neos = VppMplsRoute(self, 34, 0,
513 [VppRoutePath("0.0.0.0",
514 0xffffffff,
515 nh_via_label=32,
516 labels=[44, 46])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000517 route_34_neos.add_vpp_config()
518
519 self.vapi.cli("clear trace")
520 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
521 self.pg0.add_stream(tx)
522
523 self.pg_enable_capture(self.pg_interfaces)
524 self.pg_start()
525
526 rx = self.pg0.get_capture()
Matej Klottondeb69842016-12-09 15:05:46 +0100527 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Rannsad422ed2016-11-02 14:20:04 +0000528 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
529
530 #
Matej Klottondeb69842016-12-09 15:05:46 +0100531 # an recursive IP route that resolves through the recursive non-eos
532 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000533 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800534 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
535 [VppRoutePath("0.0.0.0",
536 0xffffffff,
537 nh_via_label=34,
538 labels=[55])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000539 ip_10_0_0_1.add_vpp_config()
540
541 self.vapi.cli("clear trace")
542 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
543 self.pg0.add_stream(tx)
544
545 self.pg_enable_capture(self.pg_interfaces)
546 self.pg_start()
547
548 rx = self.pg0.get_capture()
549 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
550
551 ip_10_0_0_1.remove_vpp_config()
552 route_34_neos.remove_vpp_config()
553 route_34_eos.remove_vpp_config()
554 route_33_neos.remove_vpp_config()
555 route_33_eos.remove_vpp_config()
556 route_32_neos.remove_vpp_config()
557 route_32_eos.remove_vpp_config()
558
559 def test_bind(self):
560 """ MPLS Local Label Binding test """
561
562 #
563 # Add a non-recursive route with a single out label
564 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800565 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
566 [VppRoutePath(self.pg0.remote_ip4,
567 self.pg0.sw_if_index,
568 labels=[45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000569 route_10_0_0_1.add_vpp_config()
570
571 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800572 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000573 binding.add_vpp_config()
574
575 # non-EOS stream
576 self.vapi.cli("clear trace")
577 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
578 self.pg0.add_stream(tx)
579
580 self.pg_enable_capture(self.pg_interfaces)
581 self.pg_start()
582
583 rx = self.pg0.get_capture()
584 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
585
586 # EOS stream
587 self.vapi.cli("clear trace")
588 tx = self.create_stream_labelled_ip4(self.pg0, [44])
589 self.pg0.add_stream(tx)
590
591 self.pg_enable_capture(self.pg_interfaces)
592 self.pg_start()
593
594 rx = self.pg0.get_capture()
595 self.verify_capture_labelled(self.pg0, rx, tx, [45])
596
597 # IP stream
598 self.vapi.cli("clear trace")
599 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
600 self.pg0.add_stream(tx)
601
602 self.pg_enable_capture(self.pg_interfaces)
603 self.pg_start()
604
605 rx = self.pg0.get_capture()
606 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
607
608 #
609 # cleanup
610 #
611 binding.remove_vpp_config()
612 route_10_0_0_1.remove_vpp_config()
613
614 def test_imposition(self):
615 """ MPLS label imposition test """
616
617 #
618 # Add a non-recursive route with a single out label
619 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800620 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
621 [VppRoutePath(self.pg0.remote_ip4,
622 self.pg0.sw_if_index,
623 labels=[32])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000624 route_10_0_0_1.add_vpp_config()
625
626 #
627 # a stream that matches the route for 10.0.0.1
628 # PG0 is in the default table
629 #
630 self.vapi.cli("clear trace")
631 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
632 self.pg0.add_stream(tx)
633
634 self.pg_enable_capture(self.pg_interfaces)
635 self.pg_start()
636
637 rx = self.pg0.get_capture()
638 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
639
640 #
641 # Add a non-recursive route with a 3 out labels
642 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800643 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
644 [VppRoutePath(self.pg0.remote_ip4,
645 self.pg0.sw_if_index,
646 labels=[32, 33, 34])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000647 route_10_0_0_2.add_vpp_config()
648
649 #
650 # a stream that matches the route for 10.0.0.1
651 # PG0 is in the default table
652 #
653 self.vapi.cli("clear trace")
654 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
655 self.pg0.add_stream(tx)
656
657 self.pg_enable_capture(self.pg_interfaces)
658 self.pg_start()
659
660 rx = self.pg0.get_capture()
661 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
662
663 #
Matej Klottondeb69842016-12-09 15:05:46 +0100664 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000665 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800666 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
667 [VppRoutePath("10.0.0.1",
668 0xffffffff,
669 labels=[44])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000670 route_11_0_0_1.add_vpp_config()
671
672 #
673 # a stream that matches the route for 11.0.0.1, should pick up
674 # the label stack for 11.0.0.1 and 10.0.0.1
675 #
676 self.vapi.cli("clear trace")
677 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
678 self.pg0.add_stream(tx)
679
680 self.pg_enable_capture(self.pg_interfaces)
681 self.pg_start()
682
683 rx = self.pg0.get_capture()
684 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
685
686 #
687 # add a recursive path, with 2 labels, via the 3 label route
688 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800689 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
690 [VppRoutePath("10.0.0.2",
691 0xffffffff,
692 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000693 route_11_0_0_2.add_vpp_config()
694
695 #
696 # a stream that matches the route for 11.0.0.1, should pick up
697 # the label stack for 11.0.0.1 and 10.0.0.1
698 #
699 self.vapi.cli("clear trace")
700 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
701 self.pg0.add_stream(tx)
702
703 self.pg_enable_capture(self.pg_interfaces)
704 self.pg_start()
705
706 rx = self.pg0.get_capture()
707 self.verify_capture_labelled_ip4(
708 self.pg0, rx, tx, [32, 33, 34, 44, 45])
709
710 #
711 # cleanup
712 #
713 route_11_0_0_2.remove_vpp_config()
714 route_11_0_0_1.remove_vpp_config()
715 route_10_0_0_2.remove_vpp_config()
716 route_10_0_0_1.remove_vpp_config()
717
718 def test_tunnel(self):
719 """ MPLS Tunnel Tests """
720
721 #
722 # Create a tunnel with a single out label
723 #
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800724 mpls_tun = VppMPLSTunnelInterface(self,
725 [VppRoutePath(self.pg0.remote_ip4,
726 self.pg0.sw_if_index,
727 labels=[44, 46])])
728 mpls_tun.add_vpp_config()
729 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000730
731 #
732 # add an unlabelled route through the new tunnel
733 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800734 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
735 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800736 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800737 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000738
739 self.vapi.cli("clear trace")
740 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
741 self.pg0.add_stream(tx)
742
743 self.pg_enable_capture(self.pg_interfaces)
744 self.pg_start()
745
746 rx = self.pg0.get_capture()
747 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000748
Neale Ranns8c4611b2017-05-23 03:43:47 -0700749 #
750 # add a labelled route through the new tunnel
751 #
752 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
753 [VppRoutePath("0.0.0.0",
754 mpls_tun._sw_if_index,
755 labels=[33])])
756 route_10_0_0_4.add_vpp_config()
757
758 self.vapi.cli("clear trace")
759 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
760 self.pg0.add_stream(tx)
761
762 self.pg_enable_capture(self.pg_interfaces)
763 self.pg_start()
764
765 rx = self.pg0.get_capture()
766 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
767 ttl=63, top=2)
768
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000769 def test_v4_exp_null(self):
770 """ MPLS V4 Explicit NULL test """
771
772 #
773 # The first test case has an MPLS TTL of 0
774 # all packet should be dropped
775 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000776 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000777 self.pg0.add_stream(tx)
778
779 self.pg_enable_capture(self.pg_interfaces)
780 self.pg_start()
781
Klement Sekera9225dee2016-12-12 08:36:58 +0100782 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000783
784 #
785 # a stream with a non-zero MPLS TTL
786 # PG0 is in the default table
787 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000788 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000789 self.pg0.add_stream(tx)
790
791 self.pg_enable_capture(self.pg_interfaces)
792 self.pg_start()
793
794 rx = self.pg0.get_capture()
795 self.verify_capture_ip4(self.pg0, rx, tx)
796
797 #
798 # a stream with a non-zero MPLS TTL
799 # PG1 is in table 1
800 # we are ensuring the post-pop lookup occurs in the VRF table
801 #
802 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000803 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000804 self.pg1.add_stream(tx)
805
806 self.pg_enable_capture(self.pg_interfaces)
807 self.pg_start()
808
809 rx = self.pg1.get_capture()
810 self.verify_capture_ip4(self.pg0, rx, tx)
811
812 def test_v6_exp_null(self):
813 """ MPLS V6 Explicit NULL test """
814
815 #
816 # a stream with a non-zero MPLS TTL
817 # PG0 is in the default table
818 #
819 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000820 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000821 self.pg0.add_stream(tx)
822
823 self.pg_enable_capture(self.pg_interfaces)
824 self.pg_start()
825
826 rx = self.pg0.get_capture()
827 self.verify_capture_ip6(self.pg0, rx, tx)
828
829 #
830 # a stream with a non-zero MPLS TTL
831 # PG1 is in table 1
832 # we are ensuring the post-pop lookup occurs in the VRF table
833 #
834 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000835 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000836 self.pg1.add_stream(tx)
837
838 self.pg_enable_capture(self.pg_interfaces)
839 self.pg_start()
840
841 rx = self.pg1.get_capture()
842 self.verify_capture_ip6(self.pg0, rx, tx)
843
Neale Rannscb630ff2016-12-14 13:31:29 +0100844 def test_deag(self):
845 """ MPLS Deagg """
846
847 #
848 # A de-agg route - next-hop lookup in default table
849 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800850 route_34_eos = VppMplsRoute(self, 34, 1,
851 [VppRoutePath("0.0.0.0",
852 0xffffffff,
853 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100854 route_34_eos.add_vpp_config()
855
856 #
857 # ping an interface in the default table
858 # PG0 is in the default table
859 #
860 self.vapi.cli("clear trace")
861 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
862 ip_itf=self.pg0)
863 self.pg0.add_stream(tx)
864
865 self.pg_enable_capture(self.pg_interfaces)
866 self.pg_start()
867
868 rx = self.pg0.get_capture()
869 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
870
871 #
872 # A de-agg route - next-hop lookup in non-default table
873 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800874 route_35_eos = VppMplsRoute(self, 35, 1,
875 [VppRoutePath("0.0.0.0",
876 0xffffffff,
877 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100878 route_35_eos.add_vpp_config()
879
880 #
881 # ping an interface in the non-default table
882 # PG0 is in the default table. packet arrive labelled in the
883 # default table and egress unlabelled in the non-default
884 #
885 self.vapi.cli("clear trace")
Klement Sekeradab231a2016-12-21 08:50:14 +0100886 tx = self.create_stream_labelled_ip4(
887 self.pg0, [35], ping=1, ip_itf=self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +0100888 self.pg0.add_stream(tx)
889
890 self.pg_enable_capture(self.pg_interfaces)
891 self.pg_start()
892
Klement Sekeradab231a2016-12-21 08:50:14 +0100893 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
894 rx = self.pg1.get_capture(packet_count)
Neale Rannscb630ff2016-12-14 13:31:29 +0100895 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
896
Neale Ranns6af1c042017-05-26 03:48:53 -0700897 #
898 # Double pop
899 #
900 route_36_neos = VppMplsRoute(self, 36, 0,
901 [VppRoutePath("0.0.0.0",
902 0xffffffff)])
903 route_36_neos.add_vpp_config()
904
905 self.vapi.cli("clear trace")
906 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
907 ping=1, ip_itf=self.pg1)
908 self.pg0.add_stream(tx)
909
910 self.pg_enable_capture(self.pg_interfaces)
911 self.pg_start()
912
913 rx = self.pg1.get_capture(len(tx))
914 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
915
916 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +0100917 route_35_eos.remove_vpp_config()
918 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000919
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800920 def test_interface_rx(self):
921 """ MPLS Interface Receive """
922
923 #
924 # Add a non-recursive route that will forward the traffic
925 # post-interface-rx
926 #
927 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
928 table_id=1,
929 paths=[VppRoutePath(self.pg1.remote_ip4,
930 self.pg1.sw_if_index)])
931 route_10_0_0_1.add_vpp_config()
932
933 #
934 # An interface receive label that maps traffic to RX on interface
935 # pg1
936 # by injecting the packet in on pg0, which is in table 0
937 # doing an interface-rx on pg1 and matching a route in table 1
938 # if the packet egresses, then we must have swapped to pg1
939 # so as to have matched the route in table 1
940 #
941 route_34_eos = VppMplsRoute(self, 34, 1,
942 [VppRoutePath("0.0.0.0",
943 self.pg1.sw_if_index,
944 is_interface_rx=1)])
945 route_34_eos.add_vpp_config()
946
947 #
948 # ping an interface in the default table
949 # PG0 is in the default table
950 #
951 self.vapi.cli("clear trace")
952 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
953 dst_ip="10.0.0.1")
954 self.pg0.add_stream(tx)
955
956 self.pg_enable_capture(self.pg_interfaces)
957 self.pg_start()
958
959 rx = self.pg1.get_capture(257)
960 self.verify_capture_ip4(self.pg1, rx, tx)
961
962 def test_mcast_mid_point(self):
963 """ MPLS Multicast Mid Point """
964
965 #
966 # Add a non-recursive route that will forward the traffic
967 # post-interface-rx
968 #
969 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
970 table_id=1,
971 paths=[VppRoutePath(self.pg1.remote_ip4,
972 self.pg1.sw_if_index)])
973 route_10_0_0_1.add_vpp_config()
974
975 #
976 # Add a mcast entry that replicate to pg2 and pg3
977 # and replicate to a interface-rx (like a bud node would)
978 #
979 route_3400_eos = VppMplsRoute(self, 3400, 1,
980 [VppRoutePath(self.pg2.remote_ip4,
981 self.pg2.sw_if_index,
982 labels=[3401]),
983 VppRoutePath(self.pg3.remote_ip4,
984 self.pg3.sw_if_index,
985 labels=[3402]),
986 VppRoutePath("0.0.0.0",
987 self.pg1.sw_if_index,
988 is_interface_rx=1)],
989 is_multicast=1)
990 route_3400_eos.add_vpp_config()
991
992 #
993 # ping an interface in the default table
994 # PG0 is in the default table
995 #
996 self.vapi.cli("clear trace")
997 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
998 dst_ip="10.0.0.1")
999 self.pg0.add_stream(tx)
1000
1001 self.pg_enable_capture(self.pg_interfaces)
1002 self.pg_start()
1003
1004 rx = self.pg1.get_capture(257)
1005 self.verify_capture_ip4(self.pg1, rx, tx)
1006
1007 rx = self.pg2.get_capture(257)
1008 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
1009 rx = self.pg3.get_capture(257)
1010 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
1011
1012 def test_mcast_head(self):
1013 """ MPLS Multicast Head-end """
1014
1015 #
1016 # Create a multicast tunnel with two replications
1017 #
1018 mpls_tun = VppMPLSTunnelInterface(self,
1019 [VppRoutePath(self.pg2.remote_ip4,
1020 self.pg2.sw_if_index,
1021 labels=[42]),
1022 VppRoutePath(self.pg3.remote_ip4,
1023 self.pg3.sw_if_index,
1024 labels=[43])],
1025 is_multicast=1)
1026 mpls_tun.add_vpp_config()
1027 mpls_tun.admin_up()
1028
1029 #
1030 # add an unlabelled route through the new tunnel
1031 #
1032 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1033 [VppRoutePath("0.0.0.0",
1034 mpls_tun._sw_if_index)])
1035 route_10_0_0_3.add_vpp_config()
1036
1037 self.vapi.cli("clear trace")
1038 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1039 self.pg0.add_stream(tx)
1040
1041 self.pg_enable_capture(self.pg_interfaces)
1042 self.pg_start()
1043
1044 rx = self.pg2.get_capture(257)
1045 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
1046 rx = self.pg3.get_capture(257)
1047 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
1048
1049 #
1050 # An an IP multicast route via the tunnel
1051 # A (*,G).
1052 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1053 #
1054 route_232_1_1_1 = VppIpMRoute(
1055 self,
1056 "0.0.0.0",
1057 "232.1.1.1", 32,
1058 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1059 [VppMRoutePath(self.pg0.sw_if_index,
1060 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1061 VppMRoutePath(mpls_tun._sw_if_index,
1062 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1063 route_232_1_1_1.add_vpp_config()
1064
1065 self.vapi.cli("clear trace")
1066 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1067 self.pg0.add_stream(tx)
1068
1069 self.pg_enable_capture(self.pg_interfaces)
1070 self.pg_start()
1071
1072 rx = self.pg2.get_capture(257)
1073 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
1074 rx = self.pg3.get_capture(257)
1075 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
1076
Neale Ranns31426c62017-05-24 10:32:58 -07001077 def test_mcast_ip4_tail(self):
1078 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001079
1080 #
1081 # Add a multicast route that will forward the traffic
1082 # post-disposition
1083 #
1084 route_232_1_1_1 = VppIpMRoute(
1085 self,
1086 "0.0.0.0",
1087 "232.1.1.1", 32,
1088 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1089 table_id=1,
1090 paths=[VppMRoutePath(self.pg1.sw_if_index,
1091 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1092 route_232_1_1_1.add_vpp_config()
1093
1094 #
1095 # An interface receive label that maps traffic to RX on interface
1096 # pg1
1097 # by injecting the packet in on pg0, which is in table 0
1098 # doing an rpf-id and matching a route in table 1
1099 # if the packet egresses, then we must have matched the route in
1100 # table 1
1101 #
1102 route_34_eos = VppMplsRoute(self, 34, 1,
1103 [VppRoutePath("0.0.0.0",
1104 self.pg1.sw_if_index,
1105 nh_table_id=1,
1106 rpf_id=55)],
1107 is_multicast=1)
1108
1109 route_34_eos.add_vpp_config()
1110
1111 #
1112 # Drop due to interface lookup miss
1113 #
1114 self.vapi.cli("clear trace")
1115 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1116 dst_ip="232.1.1.1", n=1)
1117 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1118
1119 #
1120 # set the RPF-ID of the enrtry to match the input packet's
1121 #
1122 route_232_1_1_1.update_rpf_id(55)
1123
1124 self.vapi.cli("clear trace")
1125 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1126 dst_ip="232.1.1.1", n=257)
1127 self.pg0.add_stream(tx)
1128
1129 self.pg_enable_capture(self.pg_interfaces)
1130 self.pg_start()
1131
1132 rx = self.pg1.get_capture(257)
1133 self.verify_capture_ip4(self.pg1, rx, tx)
1134
1135 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001136 # disposed packets have an invalid IPv4 checkusm
1137 #
1138 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1139 dst_ip="232.1.1.1", n=65,
1140 chksum=1)
1141 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1142
1143 #
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001144 # set the RPF-ID of the enrtry to not match the input packet's
1145 #
1146 route_232_1_1_1.update_rpf_id(56)
1147 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1148 dst_ip="232.1.1.1")
1149 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1150
Neale Ranns31426c62017-05-24 10:32:58 -07001151 def test_mcast_ip6_tail(self):
1152 """ MPLS IPv6 Multicast Tail """
1153
1154 #
1155 # Add a multicast route that will forward the traffic
1156 # post-disposition
1157 #
1158 route_ff = VppIpMRoute(
1159 self,
1160 "::",
1161 "ff01::1", 32,
1162 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1163 table_id=1,
1164 paths=[VppMRoutePath(self.pg1.sw_if_index,
1165 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1166 is_ip6=1)
1167 route_ff.add_vpp_config()
1168
1169 #
1170 # An interface receive label that maps traffic to RX on interface
1171 # pg1
1172 # by injecting the packet in on pg0, which is in table 0
1173 # doing an rpf-id and matching a route in table 1
1174 # if the packet egresses, then we must have matched the route in
1175 # table 1
1176 #
1177 route_34_eos = VppMplsRoute(
1178 self, 34, 1,
1179 [VppRoutePath("::",
1180 self.pg1.sw_if_index,
1181 nh_table_id=1,
1182 rpf_id=55,
Neale Rannsda78f952017-05-24 09:15:43 -07001183 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns31426c62017-05-24 10:32:58 -07001184 is_multicast=1)
1185
1186 route_34_eos.add_vpp_config()
1187
1188 #
1189 # Drop due to interface lookup miss
1190 #
1191 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1192 dst_ip="ff01::1")
1193
1194 #
1195 # set the RPF-ID of the enrtry to match the input packet's
1196 #
1197 route_ff.update_rpf_id(55)
1198
1199 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1200 dst_ip="ff01::1")
1201 self.pg0.add_stream(tx)
1202
1203 self.pg_enable_capture(self.pg_interfaces)
1204 self.pg_start()
1205
1206 rx = self.pg1.get_capture(257)
1207 self.verify_capture_ip6(self.pg1, rx, tx)
1208
1209 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001210 # disposed packets have hop-limit = 1
1211 #
1212 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1213 dst_ip="ff01::1", hlim=1)
Neale Ranns52fae862018-01-08 04:41:42 -08001214 self.pg0.add_stream(tx)
1215
1216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218
1219 rx = self.pg0.get_capture(257)
1220 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001221
1222 #
Neale Ranns31426c62017-05-24 10:32:58 -07001223 # set the RPF-ID of the enrtry to not match the input packet's
1224 #
1225 route_ff.update_rpf_id(56)
1226 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1227 dst_ip="ff01::1")
1228 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1229
Neale Ranns180279b2017-03-16 15:49:09 -04001230
1231class TestMPLSDisabled(VppTestCase):
1232 """ MPLS disabled """
1233
1234 def setUp(self):
1235 super(TestMPLSDisabled, self).setUp()
1236
1237 # create 2 pg interfaces
1238 self.create_pg_interfaces(range(2))
1239
Neale Ranns15002542017-09-10 04:39:11 -07001240 self.tbl = VppMplsTable(self, 0)
1241 self.tbl.add_vpp_config()
1242
Neale Ranns180279b2017-03-16 15:49:09 -04001243 # PG0 is MPLS enalbed
1244 self.pg0.admin_up()
1245 self.pg0.config_ip4()
1246 self.pg0.resolve_arp()
1247 self.pg0.enable_mpls()
1248
1249 # PG 1 is not MPLS enabled
1250 self.pg1.admin_up()
1251
1252 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001253 for i in self.pg_interfaces:
1254 i.unconfig_ip4()
1255 i.admin_down()
1256
Neale Ranns15002542017-09-10 04:39:11 -07001257 self.pg0.disable_mpls()
1258 super(TestMPLSDisabled, self).tearDown()
1259
Neale Ranns180279b2017-03-16 15:49:09 -04001260 def test_mpls_disabled(self):
1261 """ MPLS Disabled """
1262
1263 tx = (Ether(src=self.pg1.remote_mac,
1264 dst=self.pg1.local_mac) /
1265 MPLS(label=32, ttl=64) /
1266 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1267 UDP(sport=1234, dport=1234) /
1268 Raw('\xa5' * 100))
1269
1270 #
1271 # A simple MPLS xconnect - eos label in label out
1272 #
1273 route_32_eos = VppMplsRoute(self, 32, 1,
1274 [VppRoutePath(self.pg0.remote_ip4,
1275 self.pg0.sw_if_index,
1276 labels=[33])])
1277 route_32_eos.add_vpp_config()
1278
1279 #
1280 # PG1 does not forward IP traffic
1281 #
1282 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1283
1284 #
1285 # MPLS enable PG1
1286 #
1287 self.pg1.enable_mpls()
1288
1289 #
1290 # Now we get packets through
1291 #
1292 self.pg1.add_stream(tx)
1293 self.pg_enable_capture(self.pg_interfaces)
1294 self.pg_start()
1295
1296 rx = self.pg0.get_capture(1)
1297
1298 #
1299 # Disable PG1
1300 #
1301 self.pg1.disable_mpls()
1302
1303 #
1304 # PG1 does not forward IP traffic
1305 #
1306 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1307 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1308
1309
Neale Rannsf12a83f2017-04-18 09:09:40 -07001310class TestMPLSPIC(VppTestCase):
1311 """ MPLS PIC edge convergence """
1312
1313 def setUp(self):
1314 super(TestMPLSPIC, self).setUp()
1315
1316 # create 2 pg interfaces
1317 self.create_pg_interfaces(range(4))
1318
Neale Ranns15002542017-09-10 04:39:11 -07001319 mpls_tbl = VppMplsTable(self, 0)
1320 mpls_tbl.add_vpp_config()
1321 tbl4 = VppIpTable(self, 1)
1322 tbl4.add_vpp_config()
1323 tbl6 = VppIpTable(self, 1, is_ip6=1)
1324 tbl6.add_vpp_config()
1325
Neale Rannsf12a83f2017-04-18 09:09:40 -07001326 # core links
1327 self.pg0.admin_up()
1328 self.pg0.config_ip4()
1329 self.pg0.resolve_arp()
1330 self.pg0.enable_mpls()
1331 self.pg1.admin_up()
1332 self.pg1.config_ip4()
1333 self.pg1.resolve_arp()
1334 self.pg1.enable_mpls()
1335
1336 # VRF (customer facing) link
1337 self.pg2.admin_up()
1338 self.pg2.set_table_ip4(1)
1339 self.pg2.config_ip4()
1340 self.pg2.resolve_arp()
1341 self.pg2.set_table_ip6(1)
1342 self.pg2.config_ip6()
1343 self.pg2.resolve_ndp()
1344 self.pg3.admin_up()
1345 self.pg3.set_table_ip4(1)
1346 self.pg3.config_ip4()
1347 self.pg3.resolve_arp()
1348 self.pg3.set_table_ip6(1)
1349 self.pg3.config_ip6()
1350 self.pg3.resolve_ndp()
1351
1352 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001353 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001354 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001355 for i in self.pg_interfaces:
1356 i.unconfig_ip4()
1357 i.unconfig_ip6()
1358 i.set_table_ip4(0)
1359 i.set_table_ip6(0)
1360 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001361 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001362
1363 def test_mpls_ibgp_pic(self):
1364 """ MPLS iBGP PIC edge convergence
1365
1366 1) setup many iBGP VPN routes via a pair of iBGP peers.
1367 2) Check EMCP forwarding to these peers
1368 3) withdraw the IGP route to one of these peers.
1369 4) check forwarding continues to the remaining peer
1370 """
1371
1372 #
1373 # IGP+LDP core routes
1374 #
1375 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1376 [VppRoutePath(self.pg0.remote_ip4,
1377 self.pg0.sw_if_index,
1378 labels=[45])])
1379 core_10_0_0_45.add_vpp_config()
1380
1381 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1382 [VppRoutePath(self.pg1.remote_ip4,
1383 self.pg1.sw_if_index,
1384 labels=[46])])
1385 core_10_0_0_46.add_vpp_config()
1386
1387 #
1388 # Lot's of VPN routes. We need more the 64 so VPP will build
1389 # the fast convergence indirection
1390 #
1391 vpn_routes = []
1392 pkts = []
1393 for ii in range(64):
1394 dst = "192.168.1.%d" % ii
1395 vpn_routes.append(VppIpRoute(self, dst, 32,
1396 [VppRoutePath("10.0.0.45",
1397 0xffffffff,
1398 labels=[145],
1399 is_resolve_host=1),
1400 VppRoutePath("10.0.0.46",
1401 0xffffffff,
1402 labels=[146],
1403 is_resolve_host=1)],
1404 table_id=1))
1405 vpn_routes[ii].add_vpp_config()
1406
1407 pkts.append(Ether(dst=self.pg2.local_mac,
1408 src=self.pg2.remote_mac) /
1409 IP(src=self.pg2.remote_ip4, dst=dst) /
1410 UDP(sport=1234, dport=1234) /
1411 Raw('\xa5' * 100))
1412
1413 #
1414 # Send the packet stream (one pkt to each VPN route)
1415 # - expect a 50-50 split of the traffic
1416 #
1417 self.pg2.add_stream(pkts)
1418 self.pg_enable_capture(self.pg_interfaces)
1419 self.pg_start()
1420
1421 rx0 = self.pg0._get_capture(1)
1422 rx1 = self.pg1._get_capture(1)
1423
1424 # not testig the LB hashing algorithm so we're not concerned
1425 # with the split ratio, just as long as neither is 0
1426 self.assertNotEqual(0, len(rx0))
1427 self.assertNotEqual(0, len(rx1))
1428
1429 #
1430 # use a test CLI command to stop the FIB walk process, this
1431 # will prevent the FIB converging the VPN routes and thus allow
1432 # us to probe the interim (psot-fail, pre-converge) state
1433 #
1434 self.vapi.ppcli("test fib-walk-process disable")
1435
1436 #
1437 # Withdraw one of the IGP routes
1438 #
1439 core_10_0_0_46.remove_vpp_config()
1440
1441 #
1442 # now all packets should be forwarded through the remaining peer
1443 #
1444 self.vapi.ppcli("clear trace")
1445 self.pg2.add_stream(pkts)
1446 self.pg_enable_capture(self.pg_interfaces)
1447 self.pg_start()
1448
1449 rx0 = self.pg0.get_capture(len(pkts))
1450
1451 #
1452 # enable the FIB walk process to converge the FIB
1453 #
1454 self.vapi.ppcli("test fib-walk-process enable")
1455
1456 #
1457 # packets should still be forwarded through the remaining peer
1458 #
1459 self.pg2.add_stream(pkts)
1460 self.pg_enable_capture(self.pg_interfaces)
1461 self.pg_start()
1462
1463 rx0 = self.pg0.get_capture(64)
1464
1465 #
1466 # Add the IGP route back and we return to load-balancing
1467 #
1468 core_10_0_0_46.add_vpp_config()
1469
1470 self.pg2.add_stream(pkts)
1471 self.pg_enable_capture(self.pg_interfaces)
1472 self.pg_start()
1473
1474 rx0 = self.pg0._get_capture(1)
1475 rx1 = self.pg1._get_capture(1)
1476 self.assertNotEqual(0, len(rx0))
1477 self.assertNotEqual(0, len(rx1))
1478
1479 def test_mpls_ebgp_pic(self):
1480 """ MPLS eBGP PIC edge convergence
1481
1482 1) setup many eBGP VPN routes via a pair of eBGP peers
1483 2) Check EMCP forwarding to these peers
1484 3) withdraw one eBGP path - expect LB across remaining eBGP
1485 """
1486
1487 #
1488 # Lot's of VPN routes. We need more the 64 so VPP will build
1489 # the fast convergence indirection
1490 #
1491 vpn_routes = []
1492 vpn_bindings = []
1493 pkts = []
1494 for ii in range(64):
1495 dst = "192.168.1.%d" % ii
1496 local_label = 1600 + ii
1497 vpn_routes.append(VppIpRoute(self, dst, 32,
1498 [VppRoutePath(self.pg2.remote_ip4,
1499 0xffffffff,
1500 nh_table_id=1,
1501 is_resolve_attached=1),
1502 VppRoutePath(self.pg3.remote_ip4,
1503 0xffffffff,
1504 nh_table_id=1,
1505 is_resolve_attached=1)],
1506 table_id=1))
1507 vpn_routes[ii].add_vpp_config()
1508
1509 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1510 ip_table_id=1))
1511 vpn_bindings[ii].add_vpp_config()
1512
1513 pkts.append(Ether(dst=self.pg0.local_mac,
1514 src=self.pg0.remote_mac) /
1515 MPLS(label=local_label, ttl=64) /
1516 IP(src=self.pg0.remote_ip4, dst=dst) /
1517 UDP(sport=1234, dport=1234) /
1518 Raw('\xa5' * 100))
1519
1520 self.pg0.add_stream(pkts)
1521 self.pg_enable_capture(self.pg_interfaces)
1522 self.pg_start()
1523
1524 rx0 = self.pg2._get_capture(1)
1525 rx1 = self.pg3._get_capture(1)
1526 self.assertNotEqual(0, len(rx0))
1527 self.assertNotEqual(0, len(rx1))
1528
1529 #
1530 # use a test CLI command to stop the FIB walk process, this
1531 # will prevent the FIB converging the VPN routes and thus allow
1532 # us to probe the interim (psot-fail, pre-converge) state
1533 #
1534 self.vapi.ppcli("test fib-walk-process disable")
1535
1536 #
1537 # withdraw the connected prefix on the interface.
1538 #
1539 self.pg2.unconfig_ip4()
1540
1541 #
1542 # now all packets should be forwarded through the remaining peer
1543 #
1544 self.pg0.add_stream(pkts)
1545 self.pg_enable_capture(self.pg_interfaces)
1546 self.pg_start()
1547
1548 rx0 = self.pg3.get_capture(len(pkts))
1549
1550 #
1551 # enable the FIB walk process to converge the FIB
1552 #
1553 self.vapi.ppcli("test fib-walk-process enable")
1554 self.pg0.add_stream(pkts)
1555 self.pg_enable_capture(self.pg_interfaces)
1556 self.pg_start()
1557
1558 rx0 = self.pg3.get_capture(len(pkts))
1559
1560 #
1561 # put the connecteds back
1562 #
1563 self.pg2.config_ip4()
1564
1565 self.pg0.add_stream(pkts)
1566 self.pg_enable_capture(self.pg_interfaces)
1567 self.pg_start()
1568
1569 rx0 = self.pg2._get_capture(1)
1570 rx1 = self.pg3._get_capture(1)
1571 self.assertNotEqual(0, len(rx0))
1572 self.assertNotEqual(0, len(rx1))
1573
1574 def test_mpls_v6_ebgp_pic(self):
1575 """ MPLSv6 eBGP PIC edge convergence
1576
1577 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1578 2) Check EMCP forwarding to these peers
1579 3) withdraw one eBGP path - expect LB across remaining eBGP
1580 """
1581
1582 #
1583 # Lot's of VPN routes. We need more the 64 so VPP will build
1584 # the fast convergence indirection
1585 #
1586 vpn_routes = []
1587 vpn_bindings = []
1588 pkts = []
1589 for ii in range(64):
1590 dst = "3000::%d" % ii
1591 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001592 vpn_routes.append(VppIpRoute(
1593 self, dst, 128,
1594 [VppRoutePath(self.pg2.remote_ip6,
1595 0xffffffff,
1596 nh_table_id=1,
1597 is_resolve_attached=1,
1598 proto=DpoProto.DPO_PROTO_IP6),
1599 VppRoutePath(self.pg3.remote_ip6,
1600 0xffffffff,
1601 nh_table_id=1,
1602 proto=DpoProto.DPO_PROTO_IP6,
1603 is_resolve_attached=1)],
1604 table_id=1,
1605 is_ip6=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001606 vpn_routes[ii].add_vpp_config()
1607
1608 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1609 ip_table_id=1,
1610 is_ip6=1))
1611 vpn_bindings[ii].add_vpp_config()
1612
1613 pkts.append(Ether(dst=self.pg0.local_mac,
1614 src=self.pg0.remote_mac) /
1615 MPLS(label=local_label, ttl=64) /
1616 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1617 UDP(sport=1234, dport=1234) /
1618 Raw('\xa5' * 100))
1619
1620 self.pg0.add_stream(pkts)
1621 self.pg_enable_capture(self.pg_interfaces)
1622 self.pg_start()
1623
1624 rx0 = self.pg2._get_capture(1)
1625 rx1 = self.pg3._get_capture(1)
1626 self.assertNotEqual(0, len(rx0))
1627 self.assertNotEqual(0, len(rx1))
1628
1629 #
1630 # use a test CLI command to stop the FIB walk process, this
1631 # will prevent the FIB converging the VPN routes and thus allow
1632 # us to probe the interim (psot-fail, pre-converge) state
1633 #
1634 self.vapi.ppcli("test fib-walk-process disable")
1635
1636 #
1637 # withdraw the connected prefix on the interface.
1638 # and shutdown the interface so the ND cache is flushed.
1639 #
1640 self.pg2.unconfig_ip6()
1641 self.pg2.admin_down()
1642
1643 #
1644 # now all packets should be forwarded through the remaining peer
1645 #
1646 self.pg0.add_stream(pkts)
1647 self.pg_enable_capture(self.pg_interfaces)
1648 self.pg_start()
1649
1650 rx0 = self.pg3.get_capture(len(pkts))
1651
1652 #
1653 # enable the FIB walk process to converge the FIB
1654 #
1655 self.vapi.ppcli("test fib-walk-process enable")
1656 self.pg0.add_stream(pkts)
1657 self.pg_enable_capture(self.pg_interfaces)
1658 self.pg_start()
1659
1660 rx0 = self.pg3.get_capture(len(pkts))
1661
1662 #
1663 # put the connecteds back
1664 #
1665 self.pg2.admin_up()
1666 self.pg2.config_ip6()
1667
1668 self.pg0.add_stream(pkts)
1669 self.pg_enable_capture(self.pg_interfaces)
1670 self.pg_start()
1671
1672 rx0 = self.pg2._get_capture(1)
1673 rx1 = self.pg3._get_capture(1)
1674 self.assertNotEqual(0, len(rx0))
1675 self.assertNotEqual(0, len(rx1))
1676
1677
Neale Rannsda78f952017-05-24 09:15:43 -07001678class TestMPLSL2(VppTestCase):
1679 """ MPLS-L2 """
1680
1681 def setUp(self):
1682 super(TestMPLSL2, self).setUp()
1683
1684 # create 2 pg interfaces
1685 self.create_pg_interfaces(range(2))
1686
Neale Ranns15002542017-09-10 04:39:11 -07001687 # create the default MPLS table
1688 self.tables = []
1689 tbl = VppMplsTable(self, 0)
1690 tbl.add_vpp_config()
1691 self.tables.append(tbl)
1692
Neale Rannsda78f952017-05-24 09:15:43 -07001693 # use pg0 as the core facing interface
1694 self.pg0.admin_up()
1695 self.pg0.config_ip4()
1696 self.pg0.resolve_arp()
1697 self.pg0.enable_mpls()
1698
Neale Ranns15002542017-09-10 04:39:11 -07001699 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07001700 for i in self.pg_interfaces[1:]:
1701 i.admin_up()
1702
1703 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07001704 for i in self.pg_interfaces[1:]:
1705 i.admin_down()
1706
1707 self.pg0.disable_mpls()
1708 self.pg0.unconfig_ip4()
1709 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001710 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07001711
1712 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1713 ttl=255, top=None):
1714 if top is None:
1715 top = len(mpls_labels) - 1
1716
1717 capture = verify_filter(capture, sent)
1718
1719 self.assertEqual(len(capture), len(sent))
1720
1721 for i in range(len(capture)):
1722 tx = sent[i]
1723 rx = capture[i]
1724
1725 # the MPLS TTL is 255 since it enters a new tunnel
1726 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1727
1728 tx_eth = tx[Ether]
1729 rx_eth = Ether(str(rx[MPLS].payload))
1730
1731 self.assertEqual(rx_eth.src, tx_eth.src)
1732 self.assertEqual(rx_eth.dst, tx_eth.dst)
1733
1734 def test_vpws(self):
1735 """ Virtual Private Wire Service """
1736
1737 #
1738 # Create an MPLS tunnel that pushes 1 label
1739 #
1740 mpls_tun_1 = VppMPLSTunnelInterface(self,
1741 [VppRoutePath(self.pg0.remote_ip4,
1742 self.pg0.sw_if_index,
1743 labels=[42])],
1744 is_l2=1)
1745 mpls_tun_1.add_vpp_config()
1746 mpls_tun_1.admin_up()
1747
1748 #
1749 # Create a label entry to for 55 that does L2 input to the tunnel
1750 #
1751 route_55_eos = VppMplsRoute(
1752 self, 55, 1,
1753 [VppRoutePath("0.0.0.0",
1754 mpls_tun_1.sw_if_index,
1755 is_interface_rx=1,
1756 proto=DpoProto.DPO_PROTO_ETHERNET)])
1757 route_55_eos.add_vpp_config()
1758
1759 #
1760 # Cross-connect the tunnel with one of the customers L2 interfaces
1761 #
1762 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1763 mpls_tun_1.sw_if_index,
1764 enable=1)
1765 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1766 self.pg1.sw_if_index,
1767 enable=1)
1768
1769 #
1770 # inject a packet from the core
1771 #
1772 pcore = (Ether(dst=self.pg0.local_mac,
1773 src=self.pg0.remote_mac) /
1774 MPLS(label=55, ttl=64) /
1775 Ether(dst="00:00:de:ad:ba:be",
1776 src="00:00:de:ad:be:ef") /
1777 IP(src="10.10.10.10", dst="11.11.11.11") /
1778 UDP(sport=1234, dport=1234) /
1779 Raw('\xa5' * 100))
1780
1781 self.pg0.add_stream(pcore * 65)
1782 self.pg_enable_capture(self.pg_interfaces)
1783 self.pg_start()
1784
1785 rx0 = self.pg1.get_capture(65)
1786 tx = pcore[MPLS].payload
1787
1788 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1789 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1790
1791 #
1792 # Inject a packet from the custoer/L2 side
1793 #
1794 self.pg1.add_stream(tx * 65)
1795 self.pg_enable_capture(self.pg_interfaces)
1796 self.pg_start()
1797
1798 rx0 = self.pg0.get_capture(65)
1799
1800 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1801
1802 def test_vpls(self):
1803 """ Virtual Private LAN Service """
1804 #
1805 # Create an L2 MPLS tunnel
1806 #
1807 mpls_tun = VppMPLSTunnelInterface(self,
1808 [VppRoutePath(self.pg0.remote_ip4,
1809 self.pg0.sw_if_index,
1810 labels=[42])],
1811 is_l2=1)
1812 mpls_tun.add_vpp_config()
1813 mpls_tun.admin_up()
1814
1815 #
1816 # Create a label entry to for 55 that does L2 input to the tunnel
1817 #
1818 route_55_eos = VppMplsRoute(
1819 self, 55, 1,
1820 [VppRoutePath("0.0.0.0",
1821 mpls_tun.sw_if_index,
1822 is_interface_rx=1,
1823 proto=DpoProto.DPO_PROTO_ETHERNET)])
1824 route_55_eos.add_vpp_config()
1825
1826 #
1827 # add to tunnel to the customers bridge-domain
1828 #
1829 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1830 bd_id=1)
1831 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1832 bd_id=1)
1833
1834 #
1835 # Packet from the customer interface and from the core
1836 #
1837 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1838 src="00:00:de:ad:be:ef") /
1839 IP(src="10.10.10.10", dst="11.11.11.11") /
1840 UDP(sport=1234, dport=1234) /
1841 Raw('\xa5' * 100))
1842 p_core = (Ether(src="00:00:de:ad:ba:be",
1843 dst="00:00:de:ad:be:ef") /
1844 IP(dst="10.10.10.10", src="11.11.11.11") /
1845 UDP(sport=1234, dport=1234) /
1846 Raw('\xa5' * 100))
1847
1848 #
1849 # The BD is learning, so send in one of each packet to learn
1850 #
1851 p_core_encap = (Ether(dst=self.pg0.local_mac,
1852 src=self.pg0.remote_mac) /
1853 MPLS(label=55, ttl=64) /
1854 p_core)
1855
1856 self.pg1.add_stream(p_cust)
1857 self.pg_enable_capture(self.pg_interfaces)
1858 self.pg_start()
1859 self.pg0.add_stream(p_core_encap)
1860 self.pg_enable_capture(self.pg_interfaces)
1861 self.pg_start()
1862
1863 # we've learnt this so expect it be be forwarded
1864 rx0 = self.pg1.get_capture(1)
1865
1866 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1867 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1868
1869 #
1870 # now a stream in each direction
1871 #
1872 self.pg1.add_stream(p_cust * 65)
1873 self.pg_enable_capture(self.pg_interfaces)
1874 self.pg_start()
1875
1876 rx0 = self.pg0.get_capture(65)
1877
1878 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1879
1880 #
1881 # remove interfaces from customers bridge-domain
1882 #
1883 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1884 bd_id=1,
1885 enable=0)
1886 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1887 bd_id=1,
1888 enable=0)
1889
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001890if __name__ == '__main__':
1891 unittest.main(testRunner=VppTestRunner)