blob: 41d9426b508db76b5db2b5f3e8e49f6146b3cb82 [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, \
8 VppMplsIpBind
Neale Ranns8fe8cc22016-11-01 10:05:08 +00009
10from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010011from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010012from scapy.layers.inet import IP, UDP, ICMP
Klement Sekera7bb873a2016-11-18 07:38:42 +010013from scapy.layers.inet6 import IPv6
Neale Ranns8fe8cc22016-11-01 10:05:08 +000014from scapy.contrib.mpls import MPLS
15
Klement Sekeradab231a2016-12-21 08:50:14 +010016
Neale Ranns8fe8cc22016-11-01 10:05:08 +000017class TestMPLS(VppTestCase):
18 """ MPLS Test Case """
19
20 @classmethod
21 def setUpClass(cls):
22 super(TestMPLS, cls).setUpClass()
23
24 def setUp(self):
25 super(TestMPLS, self).setUp()
26
27 # create 2 pg interfaces
Neale Rannsad422ed2016-11-02 14:20:04 +000028 self.create_pg_interfaces(range(2))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000029
30 # setup both interfaces
31 # assign them different tables.
32 table_id = 0
33
34 for i in self.pg_interfaces:
35 i.admin_up()
36 i.set_table_ip4(table_id)
37 i.set_table_ip6(table_id)
38 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000039 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000040 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000041 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000042 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000043 table_id += 1
44
45 def tearDown(self):
46 super(TestMPLS, self).tearDown()
47
Neale Rannsad422ed2016-11-02 14:20:04 +000048 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +010049 def create_stream_labelled_ip4(
50 self,
51 src_if,
52 mpls_labels,
53 mpls_ttl=255,
54 ping=0,
55 ip_itf=None):
56 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000057 pkts = []
58 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010059 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000060 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +000061 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
62
63 for ii in range(len(mpls_labels)):
64 if ii == len(mpls_labels) - 1:
65 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
66 else:
67 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
Neale Rannscb630ff2016-12-14 13:31:29 +010068 if not ping:
Klement Sekera9225dee2016-12-12 08:36:58 +010069 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
Neale Rannscb630ff2016-12-14 13:31:29 +010070 UDP(sport=1234, dport=1234) /
71 Raw(payload))
72 else:
73 p = (p / IP(src=ip_itf.remote_ip4,
74 dst=ip_itf.local_ip4) /
75 ICMP())
76
Neale Ranns8fe8cc22016-11-01 10:05:08 +000077 info.data = p.copy()
78 pkts.append(p)
79 return pkts
80
Neale Rannsad422ed2016-11-02 14:20:04 +000081 def create_stream_ip4(self, src_if, dst_ip):
Klement Sekeradab231a2016-12-21 08:50:14 +010082 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +000083 pkts = []
84 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010085 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +000086 payload = self.info_to_payload(info)
87 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
88 IP(src=src_if.remote_ip4, dst=dst_ip) /
89 UDP(sport=1234, dport=1234) /
90 Raw(payload))
91 info.data = p.copy()
92 pkts.append(p)
93 return pkts
94
95 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl):
Klement Sekeradab231a2016-12-21 08:50:14 +010096 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000097 pkts = []
98 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010099 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000100 payload = self.info_to_payload(info)
101 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
102 MPLS(label=mpls_label, ttl=mpls_ttl) /
103 IPv6(src=src_if.remote_ip6, dst=src_if.remote_ip6) /
104 UDP(sport=1234, dport=1234) /
105 Raw(payload))
106 info.data = p.copy()
107 pkts.append(p)
108 return pkts
109
Matej Klottondeb69842016-12-09 15:05:46 +0100110 @staticmethod
111 def verify_filter(capture, sent):
Neale Rannsad422ed2016-11-02 14:20:04 +0000112 if not len(capture) == len(sent):
Matej Klottondeb69842016-12-09 15:05:46 +0100113 # filter out any IPv6 RAs from the capture
Neale Rannsad422ed2016-11-02 14:20:04 +0000114 for p in capture:
Matej Klottondeb69842016-12-09 15:05:46 +0100115 if p.haslayer(IPv6):
Neale Rannsad422ed2016-11-02 14:20:04 +0000116 capture.remove(p)
117 return capture
118
Neale Rannscb630ff2016-12-14 13:31:29 +0100119 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000120 try:
Neale Rannsad422ed2016-11-02 14:20:04 +0000121 capture = self.verify_filter(capture, sent)
122
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000123 self.assertEqual(len(capture), len(sent))
124
125 for i in range(len(capture)):
126 tx = sent[i]
127 rx = capture[i]
128
129 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000130 eth = rx[Ether]
131 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000132
133 tx_ip = tx[IP]
134 rx_ip = rx[IP]
135
Neale Rannscb630ff2016-12-14 13:31:29 +0100136 if not ping_resp:
137 self.assertEqual(rx_ip.src, tx_ip.src)
138 self.assertEqual(rx_ip.dst, tx_ip.dst)
139 # IP processing post pop has decremented the TTL
140 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
141 else:
142 self.assertEqual(rx_ip.src, tx_ip.dst)
143 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000144
145 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000146 raise
147
148 def verify_mpls_stack(self, rx, mpls_labels, ttl=255, num=0):
149 # the rx'd packet has the MPLS label popped
150 eth = rx[Ether]
151 self.assertEqual(eth.type, 0x8847)
152
153 rx_mpls = rx[MPLS]
154
155 for ii in range(len(mpls_labels)):
156 self.assertEqual(rx_mpls.label, mpls_labels[ii])
157 self.assertEqual(rx_mpls.cos, 0)
158 if ii == num:
159 self.assertEqual(rx_mpls.ttl, ttl)
160 else:
161 self.assertEqual(rx_mpls.ttl, 255)
162
163 if ii == len(mpls_labels) - 1:
164 self.assertEqual(rx_mpls.s, 1)
165 else:
166 # not end of stack
167 self.assertEqual(rx_mpls.s, 0)
168 # pop the label to expose the next
169 rx_mpls = rx_mpls[MPLS].payload
170
171 def verify_capture_labelled_ip4(self, src_if, capture, sent,
172 mpls_labels):
173 try:
174 capture = self.verify_filter(capture, sent)
175
176 self.assertEqual(len(capture), len(sent))
177
178 for i in range(len(capture)):
179 tx = sent[i]
180 rx = capture[i]
181 tx_ip = tx[IP]
182 rx_ip = rx[IP]
183
184 # the MPLS TTL is copied from the IP
185 self.verify_mpls_stack(
186 rx, mpls_labels, rx_ip.ttl, len(mpls_labels) - 1)
187
188 self.assertEqual(rx_ip.src, tx_ip.src)
189 self.assertEqual(rx_ip.dst, tx_ip.dst)
190 # IP processing post pop has decremented the TTL
191 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
192
193 except:
194 raise
195
196 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
197 try:
198 capture = self.verify_filter(capture, sent)
199
200 self.assertEqual(len(capture), len(sent))
201
202 for i in range(len(capture)):
203 tx = sent[i]
204 rx = capture[i]
205 tx_ip = tx[IP]
206 rx_ip = rx[IP]
207
208 # the MPLS TTL is 255 since it enters a new tunnel
209 self.verify_mpls_stack(
210 rx, mpls_labels, 255, len(mpls_labels) - 1)
211
212 self.assertEqual(rx_ip.src, tx_ip.src)
213 self.assertEqual(rx_ip.dst, tx_ip.dst)
214 # IP processing post pop has decremented the TTL
215 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
216
217 except:
218 raise
219
220 def verify_capture_labelled(self, src_if, capture, sent,
221 mpls_labels, ttl=254, num=0):
222 try:
223 capture = self.verify_filter(capture, sent)
224
225 self.assertEqual(len(capture), len(sent))
226
227 for i in range(len(capture)):
228 rx = capture[i]
229 self.verify_mpls_stack(rx, mpls_labels, ttl, num)
230 except:
231 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000232
233 def verify_capture_ip6(self, src_if, capture, sent):
234 try:
235 self.assertEqual(len(capture), len(sent))
236
237 for i in range(len(capture)):
238 tx = sent[i]
239 rx = capture[i]
240
241 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000242 eth = rx[Ether]
243 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000244
245 tx_ip = tx[IPv6]
246 rx_ip = rx[IPv6]
247
248 self.assertEqual(rx_ip.src, tx_ip.src)
249 self.assertEqual(rx_ip.dst, tx_ip.dst)
250 # IP processing post pop has decremented the TTL
251 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
252
253 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000254 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000255
Neale Rannsad422ed2016-11-02 14:20:04 +0000256 def test_swap(self):
257 """ MPLS label swap tests """
258
259 #
260 # A simple MPLS xconnect - eos label in label out
261 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800262 route_32_eos = VppMplsRoute(self, 32, 1,
263 [VppRoutePath(self.pg0.remote_ip4,
264 self.pg0.sw_if_index,
265 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000266 route_32_eos.add_vpp_config()
267
268 #
269 # a stream that matches the route for 10.0.0.1
270 # PG0 is in the default table
271 #
272 self.vapi.cli("clear trace")
273 tx = self.create_stream_labelled_ip4(self.pg0, [32])
274 self.pg0.add_stream(tx)
275
276 self.pg_enable_capture(self.pg_interfaces)
277 self.pg_start()
278
279 rx = self.pg0.get_capture()
280 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33])
281
282 #
283 # A simple MPLS xconnect - non-eos label in label out
284 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800285 route_32_neos = VppMplsRoute(self, 32, 0,
286 [VppRoutePath(self.pg0.remote_ip4,
287 self.pg0.sw_if_index,
288 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000289 route_32_neos.add_vpp_config()
290
291 #
292 # a stream that matches the route for 10.0.0.1
293 # PG0 is in the default table
294 #
295 self.vapi.cli("clear trace")
296 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
297 self.pg0.add_stream(tx)
298
299 self.pg_enable_capture(self.pg_interfaces)
300 self.pg_start()
301
302 rx = self.pg0.get_capture()
303 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
304
305 #
306 # An MPLS xconnect - EOS label in IP out
307 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800308 route_33_eos = VppMplsRoute(self, 33, 1,
309 [VppRoutePath(self.pg0.remote_ip4,
310 self.pg0.sw_if_index,
311 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000312 route_33_eos.add_vpp_config()
313
314 self.vapi.cli("clear trace")
315 tx = self.create_stream_labelled_ip4(self.pg0, [33])
316 self.pg0.add_stream(tx)
317
318 self.pg_enable_capture(self.pg_interfaces)
319 self.pg_start()
320
321 rx = self.pg0.get_capture()
322 self.verify_capture_ip4(self.pg0, rx, tx)
323
324 #
325 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
326 # so this traffic should be dropped.
327 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800328 route_33_neos = VppMplsRoute(self, 33, 0,
329 [VppRoutePath(self.pg0.remote_ip4,
330 self.pg0.sw_if_index,
331 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000332 route_33_neos.add_vpp_config()
333
334 self.vapi.cli("clear trace")
335 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
336 self.pg0.add_stream(tx)
337
338 self.pg_enable_capture(self.pg_interfaces)
339 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100340 self.pg0.assert_nothing_captured(
341 remark="MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000342
343 #
344 # A recursive EOS x-connect, which resolves through another x-connect
345 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800346 route_34_eos = VppMplsRoute(self, 34, 1,
347 [VppRoutePath("0.0.0.0",
348 0xffffffff,
349 nh_via_label=32,
350 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000351 route_34_eos.add_vpp_config()
352
Neale Rannsad422ed2016-11-02 14:20:04 +0000353 tx = self.create_stream_labelled_ip4(self.pg0, [34])
354 self.pg0.add_stream(tx)
355
356 self.pg_enable_capture(self.pg_interfaces)
357 self.pg_start()
358
359 rx = self.pg0.get_capture()
360 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 45])
361
362 #
Matej Klottondeb69842016-12-09 15:05:46 +0100363 # A recursive non-EOS x-connect, which resolves through another
364 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000365 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800366 route_34_neos = VppMplsRoute(self, 34, 0,
367 [VppRoutePath("0.0.0.0",
368 0xffffffff,
369 nh_via_label=32,
370 labels=[44, 46])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000371 route_34_neos.add_vpp_config()
372
373 self.vapi.cli("clear trace")
374 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
375 self.pg0.add_stream(tx)
376
377 self.pg_enable_capture(self.pg_interfaces)
378 self.pg_start()
379
380 rx = self.pg0.get_capture()
Matej Klottondeb69842016-12-09 15:05:46 +0100381 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Rannsad422ed2016-11-02 14:20:04 +0000382 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
383
384 #
Matej Klottondeb69842016-12-09 15:05:46 +0100385 # an recursive IP route that resolves through the recursive non-eos
386 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000387 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800388 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
389 [VppRoutePath("0.0.0.0",
390 0xffffffff,
391 nh_via_label=34,
392 labels=[55])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000393 ip_10_0_0_1.add_vpp_config()
394
395 self.vapi.cli("clear trace")
396 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
397 self.pg0.add_stream(tx)
398
399 self.pg_enable_capture(self.pg_interfaces)
400 self.pg_start()
401
402 rx = self.pg0.get_capture()
403 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
404
405 ip_10_0_0_1.remove_vpp_config()
406 route_34_neos.remove_vpp_config()
407 route_34_eos.remove_vpp_config()
408 route_33_neos.remove_vpp_config()
409 route_33_eos.remove_vpp_config()
410 route_32_neos.remove_vpp_config()
411 route_32_eos.remove_vpp_config()
412
413 def test_bind(self):
414 """ MPLS Local Label Binding test """
415
416 #
417 # Add a non-recursive route with a single out label
418 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800419 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
420 [VppRoutePath(self.pg0.remote_ip4,
421 self.pg0.sw_if_index,
422 labels=[45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000423 route_10_0_0_1.add_vpp_config()
424
425 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800426 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000427 binding.add_vpp_config()
428
429 # non-EOS stream
430 self.vapi.cli("clear trace")
431 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
432 self.pg0.add_stream(tx)
433
434 self.pg_enable_capture(self.pg_interfaces)
435 self.pg_start()
436
437 rx = self.pg0.get_capture()
438 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
439
440 # EOS stream
441 self.vapi.cli("clear trace")
442 tx = self.create_stream_labelled_ip4(self.pg0, [44])
443 self.pg0.add_stream(tx)
444
445 self.pg_enable_capture(self.pg_interfaces)
446 self.pg_start()
447
448 rx = self.pg0.get_capture()
449 self.verify_capture_labelled(self.pg0, rx, tx, [45])
450
451 # IP stream
452 self.vapi.cli("clear trace")
453 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
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_labelled_ip4(self.pg0, rx, tx, [45])
461
462 #
463 # cleanup
464 #
465 binding.remove_vpp_config()
466 route_10_0_0_1.remove_vpp_config()
467
468 def test_imposition(self):
469 """ MPLS label imposition test """
470
471 #
472 # Add a non-recursive route with a single out label
473 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800474 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
475 [VppRoutePath(self.pg0.remote_ip4,
476 self.pg0.sw_if_index,
477 labels=[32])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000478 route_10_0_0_1.add_vpp_config()
479
480 #
481 # a stream that matches the route for 10.0.0.1
482 # PG0 is in the default table
483 #
484 self.vapi.cli("clear trace")
485 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
486 self.pg0.add_stream(tx)
487
488 self.pg_enable_capture(self.pg_interfaces)
489 self.pg_start()
490
491 rx = self.pg0.get_capture()
492 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
493
494 #
495 # Add a non-recursive route with a 3 out labels
496 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800497 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
498 [VppRoutePath(self.pg0.remote_ip4,
499 self.pg0.sw_if_index,
500 labels=[32, 33, 34])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000501 route_10_0_0_2.add_vpp_config()
502
503 #
504 # a stream that matches the route for 10.0.0.1
505 # PG0 is in the default table
506 #
507 self.vapi.cli("clear trace")
508 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
509 self.pg0.add_stream(tx)
510
511 self.pg_enable_capture(self.pg_interfaces)
512 self.pg_start()
513
514 rx = self.pg0.get_capture()
515 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
516
517 #
Matej Klottondeb69842016-12-09 15:05:46 +0100518 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000519 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800520 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
521 [VppRoutePath("10.0.0.1",
522 0xffffffff,
523 labels=[44])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000524 route_11_0_0_1.add_vpp_config()
525
526 #
527 # a stream that matches the route for 11.0.0.1, should pick up
528 # the label stack for 11.0.0.1 and 10.0.0.1
529 #
530 self.vapi.cli("clear trace")
531 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
532 self.pg0.add_stream(tx)
533
534 self.pg_enable_capture(self.pg_interfaces)
535 self.pg_start()
536
537 rx = self.pg0.get_capture()
538 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
539
540 #
541 # add a recursive path, with 2 labels, via the 3 label route
542 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800543 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
544 [VppRoutePath("10.0.0.2",
545 0xffffffff,
546 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000547 route_11_0_0_2.add_vpp_config()
548
549 #
550 # a stream that matches the route for 11.0.0.1, should pick up
551 # the label stack for 11.0.0.1 and 10.0.0.1
552 #
553 self.vapi.cli("clear trace")
554 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
555 self.pg0.add_stream(tx)
556
557 self.pg_enable_capture(self.pg_interfaces)
558 self.pg_start()
559
560 rx = self.pg0.get_capture()
561 self.verify_capture_labelled_ip4(
562 self.pg0, rx, tx, [32, 33, 34, 44, 45])
563
564 #
565 # cleanup
566 #
567 route_11_0_0_2.remove_vpp_config()
568 route_11_0_0_1.remove_vpp_config()
569 route_10_0_0_2.remove_vpp_config()
570 route_10_0_0_1.remove_vpp_config()
571
572 def test_tunnel(self):
573 """ MPLS Tunnel Tests """
574
575 #
576 # Create a tunnel with a single out label
577 #
578 nh_addr = socket.inet_pton(socket.AF_INET, self.pg0.remote_ip4)
579
Matej Klottondeb69842016-12-09 15:05:46 +0100580 reply = self.vapi.mpls_tunnel_add_del(
581 0xffffffff, # don't know the if index yet
582 1, # IPv4 next-hop
583 nh_addr,
584 self.pg0.sw_if_index,
585 0, # next-hop-table-id
586 1, # next-hop-weight
587 2, # num-out-labels,
Klement Sekera9225dee2016-12-12 08:36:58 +0100588 [44, 46])
Neale Rannsad422ed2016-11-02 14:20:04 +0000589 self.vapi.sw_interface_set_flags(reply.sw_if_index, admin_up_down=1)
590
591 #
592 # add an unlabelled route through the new tunnel
593 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800594 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
595 [VppRoutePath("0.0.0.0",
596 reply.sw_if_index)])
597 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000598
599 self.vapi.cli("clear trace")
600 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
601 self.pg0.add_stream(tx)
602
603 self.pg_enable_capture(self.pg_interfaces)
604 self.pg_start()
605
606 rx = self.pg0.get_capture()
607 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000608
609 def test_v4_exp_null(self):
610 """ MPLS V4 Explicit NULL test """
611
612 #
613 # The first test case has an MPLS TTL of 0
614 # all packet should be dropped
615 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000616 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000617 self.pg0.add_stream(tx)
618
619 self.pg_enable_capture(self.pg_interfaces)
620 self.pg_start()
621
Klement Sekera9225dee2016-12-12 08:36:58 +0100622 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000623
624 #
625 # a stream with a non-zero MPLS TTL
626 # PG0 is in the default table
627 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000628 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000629 self.pg0.add_stream(tx)
630
631 self.pg_enable_capture(self.pg_interfaces)
632 self.pg_start()
633
634 rx = self.pg0.get_capture()
635 self.verify_capture_ip4(self.pg0, rx, tx)
636
637 #
638 # a stream with a non-zero MPLS TTL
639 # PG1 is in table 1
640 # we are ensuring the post-pop lookup occurs in the VRF table
641 #
642 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000643 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000644 self.pg1.add_stream(tx)
645
646 self.pg_enable_capture(self.pg_interfaces)
647 self.pg_start()
648
649 rx = self.pg1.get_capture()
650 self.verify_capture_ip4(self.pg0, rx, tx)
651
652 def test_v6_exp_null(self):
653 """ MPLS V6 Explicit NULL test """
654
655 #
656 # a stream with a non-zero MPLS TTL
657 # PG0 is in the default table
658 #
659 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000660 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000661 self.pg0.add_stream(tx)
662
663 self.pg_enable_capture(self.pg_interfaces)
664 self.pg_start()
665
666 rx = self.pg0.get_capture()
667 self.verify_capture_ip6(self.pg0, rx, tx)
668
669 #
670 # a stream with a non-zero MPLS TTL
671 # PG1 is in table 1
672 # we are ensuring the post-pop lookup occurs in the VRF table
673 #
674 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000675 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000676 self.pg1.add_stream(tx)
677
678 self.pg_enable_capture(self.pg_interfaces)
679 self.pg_start()
680
681 rx = self.pg1.get_capture()
682 self.verify_capture_ip6(self.pg0, rx, tx)
683
Neale Rannscb630ff2016-12-14 13:31:29 +0100684 def test_deag(self):
685 """ MPLS Deagg """
686
687 #
688 # A de-agg route - next-hop lookup in default table
689 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800690 route_34_eos = VppMplsRoute(self, 34, 1,
691 [VppRoutePath("0.0.0.0",
692 0xffffffff,
693 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100694 route_34_eos.add_vpp_config()
695
696 #
697 # ping an interface in the default table
698 # PG0 is in the default table
699 #
700 self.vapi.cli("clear trace")
701 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
702 ip_itf=self.pg0)
703 self.pg0.add_stream(tx)
704
705 self.pg_enable_capture(self.pg_interfaces)
706 self.pg_start()
707
708 rx = self.pg0.get_capture()
709 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
710
711 #
712 # A de-agg route - next-hop lookup in non-default table
713 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800714 route_35_eos = VppMplsRoute(self, 35, 1,
715 [VppRoutePath("0.0.0.0",
716 0xffffffff,
717 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100718 route_35_eos.add_vpp_config()
719
720 #
721 # ping an interface in the non-default table
722 # PG0 is in the default table. packet arrive labelled in the
723 # default table and egress unlabelled in the non-default
724 #
725 self.vapi.cli("clear trace")
Klement Sekeradab231a2016-12-21 08:50:14 +0100726 tx = self.create_stream_labelled_ip4(
727 self.pg0, [35], ping=1, ip_itf=self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +0100728 self.pg0.add_stream(tx)
729
730 self.pg_enable_capture(self.pg_interfaces)
731 self.pg_start()
732
Klement Sekeradab231a2016-12-21 08:50:14 +0100733 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
734 rx = self.pg1.get_capture(packet_count)
Neale Rannscb630ff2016-12-14 13:31:29 +0100735 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
736
737 route_35_eos.remove_vpp_config()
738 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000739
740if __name__ == '__main__':
741 unittest.main(testRunner=VppTestRunner)