blob: 806e69dc2fa8fddf1ac114260761f619da607495 [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 Rannsad422ed2016-11-02 14:20:04 +00007from vpp_ip_route import IpRoute, RoutePath, MplsRoute, MplsIpBind
Neale Ranns8fe8cc22016-11-01 10:05:08 +00008
9from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010010from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010011from scapy.layers.inet import IP, UDP, ICMP
Klement Sekera7bb873a2016-11-18 07:38:42 +010012from scapy.layers.inet6 import IPv6
Neale Ranns8fe8cc22016-11-01 10:05:08 +000013from scapy.contrib.mpls import MPLS
14
Klement Sekeradab231a2016-12-21 08:50:14 +010015
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016class TestMPLS(VppTestCase):
17 """ MPLS Test Case """
18
19 @classmethod
20 def setUpClass(cls):
21 super(TestMPLS, cls).setUpClass()
22
23 def setUp(self):
24 super(TestMPLS, self).setUp()
25
26 # create 2 pg interfaces
Neale Rannsad422ed2016-11-02 14:20:04 +000027 self.create_pg_interfaces(range(2))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000028
29 # setup both interfaces
30 # assign them different tables.
31 table_id = 0
32
33 for i in self.pg_interfaces:
34 i.admin_up()
35 i.set_table_ip4(table_id)
36 i.set_table_ip6(table_id)
37 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000038 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000039 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000040 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000041 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000042 table_id += 1
43
44 def tearDown(self):
45 super(TestMPLS, self).tearDown()
46
Neale Rannsad422ed2016-11-02 14:20:04 +000047 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +010048 def create_stream_labelled_ip4(
49 self,
50 src_if,
51 mpls_labels,
52 mpls_ttl=255,
53 ping=0,
54 ip_itf=None):
55 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000056 pkts = []
57 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010058 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000059 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +000060 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
61
62 for ii in range(len(mpls_labels)):
63 if ii == len(mpls_labels) - 1:
64 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
65 else:
66 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
Neale Rannscb630ff2016-12-14 13:31:29 +010067 if not ping:
Klement Sekera9225dee2016-12-12 08:36:58 +010068 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
Neale Rannscb630ff2016-12-14 13:31:29 +010069 UDP(sport=1234, dport=1234) /
70 Raw(payload))
71 else:
72 p = (p / IP(src=ip_itf.remote_ip4,
73 dst=ip_itf.local_ip4) /
74 ICMP())
75
Neale Ranns8fe8cc22016-11-01 10:05:08 +000076 info.data = p.copy()
77 pkts.append(p)
78 return pkts
79
Neale Rannsad422ed2016-11-02 14:20:04 +000080 def create_stream_ip4(self, src_if, dst_ip):
Klement Sekeradab231a2016-12-21 08:50:14 +010081 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +000082 pkts = []
83 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010084 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +000085 payload = self.info_to_payload(info)
86 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
87 IP(src=src_if.remote_ip4, dst=dst_ip) /
88 UDP(sport=1234, dport=1234) /
89 Raw(payload))
90 info.data = p.copy()
91 pkts.append(p)
92 return pkts
93
94 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl):
Klement Sekeradab231a2016-12-21 08:50:14 +010095 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000096 pkts = []
97 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +010098 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000099 payload = self.info_to_payload(info)
100 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
101 MPLS(label=mpls_label, ttl=mpls_ttl) /
102 IPv6(src=src_if.remote_ip6, dst=src_if.remote_ip6) /
103 UDP(sport=1234, dport=1234) /
104 Raw(payload))
105 info.data = p.copy()
106 pkts.append(p)
107 return pkts
108
Matej Klottondeb69842016-12-09 15:05:46 +0100109 @staticmethod
110 def verify_filter(capture, sent):
Neale Rannsad422ed2016-11-02 14:20:04 +0000111 if not len(capture) == len(sent):
Matej Klottondeb69842016-12-09 15:05:46 +0100112 # filter out any IPv6 RAs from the capture
Neale Rannsad422ed2016-11-02 14:20:04 +0000113 for p in capture:
Matej Klottondeb69842016-12-09 15:05:46 +0100114 if p.haslayer(IPv6):
Neale Rannsad422ed2016-11-02 14:20:04 +0000115 capture.remove(p)
116 return capture
117
Neale Rannscb630ff2016-12-14 13:31:29 +0100118 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000119 try:
Neale Rannsad422ed2016-11-02 14:20:04 +0000120 capture = self.verify_filter(capture, sent)
121
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000122 self.assertEqual(len(capture), len(sent))
123
124 for i in range(len(capture)):
125 tx = sent[i]
126 rx = capture[i]
127
128 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000129 eth = rx[Ether]
130 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000131
132 tx_ip = tx[IP]
133 rx_ip = rx[IP]
134
Neale Rannscb630ff2016-12-14 13:31:29 +0100135 if not ping_resp:
136 self.assertEqual(rx_ip.src, tx_ip.src)
137 self.assertEqual(rx_ip.dst, tx_ip.dst)
138 # IP processing post pop has decremented the TTL
139 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
140 else:
141 self.assertEqual(rx_ip.src, tx_ip.dst)
142 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000143
144 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000145 raise
146
147 def verify_mpls_stack(self, rx, mpls_labels, ttl=255, num=0):
148 # the rx'd packet has the MPLS label popped
149 eth = rx[Ether]
150 self.assertEqual(eth.type, 0x8847)
151
152 rx_mpls = rx[MPLS]
153
154 for ii in range(len(mpls_labels)):
155 self.assertEqual(rx_mpls.label, mpls_labels[ii])
156 self.assertEqual(rx_mpls.cos, 0)
157 if ii == num:
158 self.assertEqual(rx_mpls.ttl, ttl)
159 else:
160 self.assertEqual(rx_mpls.ttl, 255)
161
162 if ii == len(mpls_labels) - 1:
163 self.assertEqual(rx_mpls.s, 1)
164 else:
165 # not end of stack
166 self.assertEqual(rx_mpls.s, 0)
167 # pop the label to expose the next
168 rx_mpls = rx_mpls[MPLS].payload
169
170 def verify_capture_labelled_ip4(self, src_if, capture, sent,
171 mpls_labels):
172 try:
173 capture = self.verify_filter(capture, sent)
174
175 self.assertEqual(len(capture), len(sent))
176
177 for i in range(len(capture)):
178 tx = sent[i]
179 rx = capture[i]
180 tx_ip = tx[IP]
181 rx_ip = rx[IP]
182
183 # the MPLS TTL is copied from the IP
184 self.verify_mpls_stack(
185 rx, mpls_labels, rx_ip.ttl, len(mpls_labels) - 1)
186
187 self.assertEqual(rx_ip.src, tx_ip.src)
188 self.assertEqual(rx_ip.dst, tx_ip.dst)
189 # IP processing post pop has decremented the TTL
190 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
191
192 except:
193 raise
194
195 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
196 try:
197 capture = self.verify_filter(capture, sent)
198
199 self.assertEqual(len(capture), len(sent))
200
201 for i in range(len(capture)):
202 tx = sent[i]
203 rx = capture[i]
204 tx_ip = tx[IP]
205 rx_ip = rx[IP]
206
207 # the MPLS TTL is 255 since it enters a new tunnel
208 self.verify_mpls_stack(
209 rx, mpls_labels, 255, len(mpls_labels) - 1)
210
211 self.assertEqual(rx_ip.src, tx_ip.src)
212 self.assertEqual(rx_ip.dst, tx_ip.dst)
213 # IP processing post pop has decremented the TTL
214 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
215
216 except:
217 raise
218
219 def verify_capture_labelled(self, src_if, capture, sent,
220 mpls_labels, ttl=254, num=0):
221 try:
222 capture = self.verify_filter(capture, sent)
223
224 self.assertEqual(len(capture), len(sent))
225
226 for i in range(len(capture)):
227 rx = capture[i]
228 self.verify_mpls_stack(rx, mpls_labels, ttl, num)
229 except:
230 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000231
232 def verify_capture_ip6(self, src_if, capture, sent):
233 try:
234 self.assertEqual(len(capture), len(sent))
235
236 for i in range(len(capture)):
237 tx = sent[i]
238 rx = capture[i]
239
240 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000241 eth = rx[Ether]
242 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000243
244 tx_ip = tx[IPv6]
245 rx_ip = rx[IPv6]
246
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.hlim + 1, tx_ip.hlim)
251
252 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000253 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000254
Neale Rannsad422ed2016-11-02 14:20:04 +0000255 def test_swap(self):
256 """ MPLS label swap tests """
257
258 #
259 # A simple MPLS xconnect - eos label in label out
260 #
261 route_32_eos = MplsRoute(self, 32, 1,
262 [RoutePath(self.pg0.remote_ip4,
263 self.pg0.sw_if_index,
264 labels=[33])])
265 route_32_eos.add_vpp_config()
266
267 #
268 # a stream that matches the route for 10.0.0.1
269 # PG0 is in the default table
270 #
271 self.vapi.cli("clear trace")
272 tx = self.create_stream_labelled_ip4(self.pg0, [32])
273 self.pg0.add_stream(tx)
274
275 self.pg_enable_capture(self.pg_interfaces)
276 self.pg_start()
277
278 rx = self.pg0.get_capture()
279 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33])
280
281 #
282 # A simple MPLS xconnect - non-eos label in label out
283 #
284 route_32_neos = MplsRoute(self, 32, 0,
285 [RoutePath(self.pg0.remote_ip4,
286 self.pg0.sw_if_index,
287 labels=[33])])
288 route_32_neos.add_vpp_config()
289
290 #
291 # a stream that matches the route for 10.0.0.1
292 # PG0 is in the default table
293 #
294 self.vapi.cli("clear trace")
295 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
296 self.pg0.add_stream(tx)
297
298 self.pg_enable_capture(self.pg_interfaces)
299 self.pg_start()
300
301 rx = self.pg0.get_capture()
302 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
303
304 #
305 # An MPLS xconnect - EOS label in IP out
306 #
307 route_33_eos = MplsRoute(self, 33, 1,
308 [RoutePath(self.pg0.remote_ip4,
309 self.pg0.sw_if_index,
310 labels=[])])
311 route_33_eos.add_vpp_config()
312
313 self.vapi.cli("clear trace")
314 tx = self.create_stream_labelled_ip4(self.pg0, [33])
315 self.pg0.add_stream(tx)
316
317 self.pg_enable_capture(self.pg_interfaces)
318 self.pg_start()
319
320 rx = self.pg0.get_capture()
321 self.verify_capture_ip4(self.pg0, rx, tx)
322
323 #
324 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
325 # so this traffic should be dropped.
326 #
327 route_33_neos = MplsRoute(self, 33, 0,
328 [RoutePath(self.pg0.remote_ip4,
329 self.pg0.sw_if_index,
330 labels=[])])
331 route_33_neos.add_vpp_config()
332
333 self.vapi.cli("clear trace")
334 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
335 self.pg0.add_stream(tx)
336
337 self.pg_enable_capture(self.pg_interfaces)
338 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100339 self.pg0.assert_nothing_captured(
340 remark="MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000341
342 #
343 # A recursive EOS x-connect, which resolves through another x-connect
344 #
345 route_34_eos = MplsRoute(self, 34, 1,
346 [RoutePath("0.0.0.0",
347 0xffffffff,
348 nh_via_label=32,
349 labels=[44, 45])])
350 route_34_eos.add_vpp_config()
351
Neale Rannsad422ed2016-11-02 14:20:04 +0000352 tx = self.create_stream_labelled_ip4(self.pg0, [34])
353 self.pg0.add_stream(tx)
354
355 self.pg_enable_capture(self.pg_interfaces)
356 self.pg_start()
357
358 rx = self.pg0.get_capture()
359 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 45])
360
361 #
Matej Klottondeb69842016-12-09 15:05:46 +0100362 # A recursive non-EOS x-connect, which resolves through another
363 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000364 #
365 route_34_neos = MplsRoute(self, 34, 0,
366 [RoutePath("0.0.0.0",
367 0xffffffff,
368 nh_via_label=32,
369 labels=[44, 46])])
370 route_34_neos.add_vpp_config()
371
372 self.vapi.cli("clear trace")
373 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
374 self.pg0.add_stream(tx)
375
376 self.pg_enable_capture(self.pg_interfaces)
377 self.pg_start()
378
379 rx = self.pg0.get_capture()
Matej Klottondeb69842016-12-09 15:05:46 +0100380 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Rannsad422ed2016-11-02 14:20:04 +0000381 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
382
383 #
Matej Klottondeb69842016-12-09 15:05:46 +0100384 # an recursive IP route that resolves through the recursive non-eos
385 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000386 #
387 ip_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
388 [RoutePath("0.0.0.0",
389 0xffffffff,
390 nh_via_label=34,
391 labels=[55])])
392 ip_10_0_0_1.add_vpp_config()
393
394 self.vapi.cli("clear trace")
395 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
396 self.pg0.add_stream(tx)
397
398 self.pg_enable_capture(self.pg_interfaces)
399 self.pg_start()
400
401 rx = self.pg0.get_capture()
402 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
403
404 ip_10_0_0_1.remove_vpp_config()
405 route_34_neos.remove_vpp_config()
406 route_34_eos.remove_vpp_config()
407 route_33_neos.remove_vpp_config()
408 route_33_eos.remove_vpp_config()
409 route_32_neos.remove_vpp_config()
410 route_32_eos.remove_vpp_config()
411
412 def test_bind(self):
413 """ MPLS Local Label Binding test """
414
415 #
416 # Add a non-recursive route with a single out label
417 #
418 route_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
419 [RoutePath(self.pg0.remote_ip4,
420 self.pg0.sw_if_index,
421 labels=[45])])
422 route_10_0_0_1.add_vpp_config()
423
424 # bind a local label to the route
425 binding = MplsIpBind(self, 44, "10.0.0.1", 32)
426 binding.add_vpp_config()
427
428 # non-EOS stream
429 self.vapi.cli("clear trace")
430 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
431 self.pg0.add_stream(tx)
432
433 self.pg_enable_capture(self.pg_interfaces)
434 self.pg_start()
435
436 rx = self.pg0.get_capture()
437 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
438
439 # EOS stream
440 self.vapi.cli("clear trace")
441 tx = self.create_stream_labelled_ip4(self.pg0, [44])
442 self.pg0.add_stream(tx)
443
444 self.pg_enable_capture(self.pg_interfaces)
445 self.pg_start()
446
447 rx = self.pg0.get_capture()
448 self.verify_capture_labelled(self.pg0, rx, tx, [45])
449
450 # IP stream
451 self.vapi.cli("clear trace")
452 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
453 self.pg0.add_stream(tx)
454
455 self.pg_enable_capture(self.pg_interfaces)
456 self.pg_start()
457
458 rx = self.pg0.get_capture()
459 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
460
461 #
462 # cleanup
463 #
464 binding.remove_vpp_config()
465 route_10_0_0_1.remove_vpp_config()
466
467 def test_imposition(self):
468 """ MPLS label imposition test """
469
470 #
471 # Add a non-recursive route with a single out label
472 #
473 route_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
474 [RoutePath(self.pg0.remote_ip4,
475 self.pg0.sw_if_index,
476 labels=[32])])
477 route_10_0_0_1.add_vpp_config()
478
479 #
480 # a stream that matches the route for 10.0.0.1
481 # PG0 is in the default table
482 #
483 self.vapi.cli("clear trace")
484 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
485 self.pg0.add_stream(tx)
486
487 self.pg_enable_capture(self.pg_interfaces)
488 self.pg_start()
489
490 rx = self.pg0.get_capture()
491 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
492
493 #
494 # Add a non-recursive route with a 3 out labels
495 #
496 route_10_0_0_2 = IpRoute(self, "10.0.0.2", 32,
497 [RoutePath(self.pg0.remote_ip4,
498 self.pg0.sw_if_index,
499 labels=[32, 33, 34])])
500 route_10_0_0_2.add_vpp_config()
501
502 #
503 # a stream that matches the route for 10.0.0.1
504 # PG0 is in the default table
505 #
506 self.vapi.cli("clear trace")
507 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
508 self.pg0.add_stream(tx)
509
510 self.pg_enable_capture(self.pg_interfaces)
511 self.pg_start()
512
513 rx = self.pg0.get_capture()
514 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
515
516 #
Matej Klottondeb69842016-12-09 15:05:46 +0100517 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000518 #
519 route_11_0_0_1 = IpRoute(self, "11.0.0.1", 32,
520 [RoutePath("10.0.0.1",
521 0xffffffff,
522 labels=[44])])
523 route_11_0_0_1.add_vpp_config()
524
525 #
526 # a stream that matches the route for 11.0.0.1, should pick up
527 # the label stack for 11.0.0.1 and 10.0.0.1
528 #
529 self.vapi.cli("clear trace")
530 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
531 self.pg0.add_stream(tx)
532
533 self.pg_enable_capture(self.pg_interfaces)
534 self.pg_start()
535
536 rx = self.pg0.get_capture()
537 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
538
539 #
540 # add a recursive path, with 2 labels, via the 3 label route
541 #
542 route_11_0_0_2 = IpRoute(self, "11.0.0.2", 32,
543 [RoutePath("10.0.0.2",
544 0xffffffff,
545 labels=[44, 45])])
546 route_11_0_0_2.add_vpp_config()
547
548 #
549 # a stream that matches the route for 11.0.0.1, should pick up
550 # the label stack for 11.0.0.1 and 10.0.0.1
551 #
552 self.vapi.cli("clear trace")
553 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
554 self.pg0.add_stream(tx)
555
556 self.pg_enable_capture(self.pg_interfaces)
557 self.pg_start()
558
559 rx = self.pg0.get_capture()
560 self.verify_capture_labelled_ip4(
561 self.pg0, rx, tx, [32, 33, 34, 44, 45])
562
563 #
564 # cleanup
565 #
566 route_11_0_0_2.remove_vpp_config()
567 route_11_0_0_1.remove_vpp_config()
568 route_10_0_0_2.remove_vpp_config()
569 route_10_0_0_1.remove_vpp_config()
570
571 def test_tunnel(self):
572 """ MPLS Tunnel Tests """
573
574 #
575 # Create a tunnel with a single out label
576 #
577 nh_addr = socket.inet_pton(socket.AF_INET, self.pg0.remote_ip4)
578
Matej Klottondeb69842016-12-09 15:05:46 +0100579 reply = self.vapi.mpls_tunnel_add_del(
580 0xffffffff, # don't know the if index yet
581 1, # IPv4 next-hop
582 nh_addr,
583 self.pg0.sw_if_index,
584 0, # next-hop-table-id
585 1, # next-hop-weight
586 2, # num-out-labels,
Klement Sekera9225dee2016-12-12 08:36:58 +0100587 [44, 46])
Neale Rannsad422ed2016-11-02 14:20:04 +0000588 self.vapi.sw_interface_set_flags(reply.sw_if_index, admin_up_down=1)
589
590 #
591 # add an unlabelled route through the new tunnel
592 #
593 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.3")
594 nh_addr = socket.inet_pton(socket.AF_INET, "0.0.0.0")
595 dest_addr_len = 32
596
Matej Klottondeb69842016-12-09 15:05:46 +0100597 self.vapi.ip_add_del_route(
598 dest_addr,
599 dest_addr_len,
600 nh_addr, # all zeros next-hop - tunnel is p2p
601 reply.sw_if_index, # sw_if_index of the new tunnel
602 0, # table-id
603 0, # next-hop-table-id
604 1, # next-hop-weight
605 0, # num-out-labels,
Klement Sekera9225dee2016-12-12 08:36:58 +0100606 []) # out-label
Neale Rannsad422ed2016-11-02 14:20:04 +0000607
608 self.vapi.cli("clear trace")
609 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
610 self.pg0.add_stream(tx)
611
612 self.pg_enable_capture(self.pg_interfaces)
613 self.pg_start()
614
615 rx = self.pg0.get_capture()
616 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000617
618 def test_v4_exp_null(self):
619 """ MPLS V4 Explicit NULL test """
620
621 #
622 # The first test case has an MPLS TTL of 0
623 # all packet should be dropped
624 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000625 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000626 self.pg0.add_stream(tx)
627
628 self.pg_enable_capture(self.pg_interfaces)
629 self.pg_start()
630
Klement Sekera9225dee2016-12-12 08:36:58 +0100631 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000632
633 #
634 # a stream with a non-zero MPLS TTL
635 # PG0 is in the default table
636 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000637 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000638 self.pg0.add_stream(tx)
639
640 self.pg_enable_capture(self.pg_interfaces)
641 self.pg_start()
642
643 rx = self.pg0.get_capture()
644 self.verify_capture_ip4(self.pg0, rx, tx)
645
646 #
647 # a stream with a non-zero MPLS TTL
648 # PG1 is in table 1
649 # we are ensuring the post-pop lookup occurs in the VRF table
650 #
651 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000652 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000653 self.pg1.add_stream(tx)
654
655 self.pg_enable_capture(self.pg_interfaces)
656 self.pg_start()
657
658 rx = self.pg1.get_capture()
659 self.verify_capture_ip4(self.pg0, rx, tx)
660
661 def test_v6_exp_null(self):
662 """ MPLS V6 Explicit NULL test """
663
664 #
665 # a stream with a non-zero MPLS TTL
666 # PG0 is in the default table
667 #
668 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000669 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000670 self.pg0.add_stream(tx)
671
672 self.pg_enable_capture(self.pg_interfaces)
673 self.pg_start()
674
675 rx = self.pg0.get_capture()
676 self.verify_capture_ip6(self.pg0, rx, tx)
677
678 #
679 # a stream with a non-zero MPLS TTL
680 # PG1 is in table 1
681 # we are ensuring the post-pop lookup occurs in the VRF table
682 #
683 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000684 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000685 self.pg1.add_stream(tx)
686
687 self.pg_enable_capture(self.pg_interfaces)
688 self.pg_start()
689
690 rx = self.pg1.get_capture()
691 self.verify_capture_ip6(self.pg0, rx, tx)
692
Neale Rannscb630ff2016-12-14 13:31:29 +0100693 def test_deag(self):
694 """ MPLS Deagg """
695
696 #
697 # A de-agg route - next-hop lookup in default table
698 #
699 route_34_eos = MplsRoute(self, 34, 1,
Klement Sekeradab231a2016-12-21 08:50:14 +0100700 [RoutePath("0.0.0.0",
701 0xffffffff,
702 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100703 route_34_eos.add_vpp_config()
704
705 #
706 # ping an interface in the default table
707 # PG0 is in the default table
708 #
709 self.vapi.cli("clear trace")
710 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
711 ip_itf=self.pg0)
712 self.pg0.add_stream(tx)
713
714 self.pg_enable_capture(self.pg_interfaces)
715 self.pg_start()
716
717 rx = self.pg0.get_capture()
718 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
719
720 #
721 # A de-agg route - next-hop lookup in non-default table
722 #
723 route_35_eos = MplsRoute(self, 35, 1,
Klement Sekeradab231a2016-12-21 08:50:14 +0100724 [RoutePath("0.0.0.0",
725 0xffffffff,
726 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100727 route_35_eos.add_vpp_config()
728
729 #
730 # ping an interface in the non-default table
731 # PG0 is in the default table. packet arrive labelled in the
732 # default table and egress unlabelled in the non-default
733 #
734 self.vapi.cli("clear trace")
Klement Sekeradab231a2016-12-21 08:50:14 +0100735 tx = self.create_stream_labelled_ip4(
736 self.pg0, [35], ping=1, ip_itf=self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +0100737 self.pg0.add_stream(tx)
738
739 self.pg_enable_capture(self.pg_interfaces)
740 self.pg_start()
741
Klement Sekeradab231a2016-12-21 08:50:14 +0100742 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
743 rx = self.pg1.get_capture(packet_count)
Neale Rannscb630ff2016-12-14 13:31:29 +0100744 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
745
746 route_35_eos.remove_vpp_config()
747 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000748
749if __name__ == '__main__':
750 unittest.main(testRunner=VppTestRunner)