blob: 92a579f20cbccd5f11f545b10ea472d64117ed5d [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
7from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Neale Rannsad422ed2016-11-02 14:20:04 +00008from vpp_ip_route import IpRoute, RoutePath, MplsRoute, MplsIpBind
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 Ranns8fe8cc22016-11-01 10:05:08 +000012from scapy.layers.inet import IP, UDP
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
Klement Sekera7bb873a2016-11-18 07:38:42 +010015from util import ppp
16
Neale Ranns8fe8cc22016-11-01 10:05:08 +000017
Neale Rannsad422ed2016-11-02 14:20:04 +000018
Neale Ranns8fe8cc22016-11-01 10:05:08 +000019class TestMPLS(VppTestCase):
20 """ MPLS Test Case """
21
22 @classmethod
23 def setUpClass(cls):
24 super(TestMPLS, cls).setUpClass()
25
26 def setUp(self):
27 super(TestMPLS, self).setUp()
28
29 # create 2 pg interfaces
Neale Rannsad422ed2016-11-02 14:20:04 +000030 self.create_pg_interfaces(range(2))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000031
32 # setup both interfaces
33 # assign them different tables.
34 table_id = 0
35
36 for i in self.pg_interfaces:
37 i.admin_up()
38 i.set_table_ip4(table_id)
39 i.set_table_ip6(table_id)
40 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000041 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000042 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000043 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000044 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000045 table_id += 1
46
47 def tearDown(self):
48 super(TestMPLS, self).tearDown()
49
Neale Rannsad422ed2016-11-02 14:20:04 +000050 # the default of 64 matches the IP packet TTL default
51 def create_stream_labelled_ip4(self, src_if, mpls_labels, mpls_ttl=255):
Neale Ranns8fe8cc22016-11-01 10:05:08 +000052 pkts = []
53 for i in range(0, 257):
54 info = self.create_packet_info(src_if.sw_if_index,
55 src_if.sw_if_index)
56 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +000057 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
58
59 for ii in range(len(mpls_labels)):
60 if ii == len(mpls_labels) - 1:
61 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
62 else:
63 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
64 p = (p / IP(src=src_if.remote_ip4, dst=src_if.remote_ip4) /
Neale Ranns8fe8cc22016-11-01 10:05:08 +000065 UDP(sport=1234, dport=1234) /
66 Raw(payload))
67 info.data = p.copy()
68 pkts.append(p)
69 return pkts
70
Neale Rannsad422ed2016-11-02 14:20:04 +000071 def create_stream_ip4(self, src_if, dst_ip):
72 pkts = []
73 for i in range(0, 257):
74 info = self.create_packet_info(src_if.sw_if_index,
75 src_if.sw_if_index)
76 payload = self.info_to_payload(info)
77 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
78 IP(src=src_if.remote_ip4, dst=dst_ip) /
79 UDP(sport=1234, dport=1234) /
80 Raw(payload))
81 info.data = p.copy()
82 pkts.append(p)
83 return pkts
84
85 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl):
Neale Ranns8fe8cc22016-11-01 10:05:08 +000086 pkts = []
87 for i in range(0, 257):
88 info = self.create_packet_info(src_if.sw_if_index,
89 src_if.sw_if_index)
90 payload = self.info_to_payload(info)
91 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
92 MPLS(label=mpls_label, ttl=mpls_ttl) /
93 IPv6(src=src_if.remote_ip6, dst=src_if.remote_ip6) /
94 UDP(sport=1234, dport=1234) /
95 Raw(payload))
96 info.data = p.copy()
97 pkts.append(p)
98 return pkts
99
Neale Rannsad422ed2016-11-02 14:20:04 +0000100 def verify_filter(self, capture, sent):
101 if not len(capture) == len(sent):
102 # filter out any IPv6 RAs from the captur
103 for p in capture:
104 if (p.haslayer(IPv6)):
105 capture.remove(p)
106 return capture
107
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000108 def verify_capture_ip4(self, src_if, capture, sent):
109 try:
Neale Rannsad422ed2016-11-02 14:20:04 +0000110 capture = self.verify_filter(capture, sent)
111
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000112 self.assertEqual(len(capture), len(sent))
113
114 for i in range(len(capture)):
115 tx = sent[i]
116 rx = capture[i]
117
118 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000119 eth = rx[Ether]
120 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000121
122 tx_ip = tx[IP]
123 rx_ip = rx[IP]
124
125 self.assertEqual(rx_ip.src, tx_ip.src)
126 self.assertEqual(rx_ip.dst, tx_ip.dst)
127 # IP processing post pop has decremented the TTL
Neale Rannsad422ed2016-11-02 14:20:04 +0000128 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000129
130 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000131 raise
132
133 def verify_mpls_stack(self, rx, mpls_labels, ttl=255, num=0):
134 # the rx'd packet has the MPLS label popped
135 eth = rx[Ether]
136 self.assertEqual(eth.type, 0x8847)
137
138 rx_mpls = rx[MPLS]
139
140 for ii in range(len(mpls_labels)):
141 self.assertEqual(rx_mpls.label, mpls_labels[ii])
142 self.assertEqual(rx_mpls.cos, 0)
143 if ii == num:
144 self.assertEqual(rx_mpls.ttl, ttl)
145 else:
146 self.assertEqual(rx_mpls.ttl, 255)
147
148 if ii == len(mpls_labels) - 1:
149 self.assertEqual(rx_mpls.s, 1)
150 else:
151 # not end of stack
152 self.assertEqual(rx_mpls.s, 0)
153 # pop the label to expose the next
154 rx_mpls = rx_mpls[MPLS].payload
155
156 def verify_capture_labelled_ip4(self, src_if, capture, sent,
157 mpls_labels):
158 try:
159 capture = self.verify_filter(capture, sent)
160
161 self.assertEqual(len(capture), len(sent))
162
163 for i in range(len(capture)):
164 tx = sent[i]
165 rx = capture[i]
166 tx_ip = tx[IP]
167 rx_ip = rx[IP]
168
169 # the MPLS TTL is copied from the IP
170 self.verify_mpls_stack(
171 rx, mpls_labels, rx_ip.ttl, len(mpls_labels) - 1)
172
173 self.assertEqual(rx_ip.src, tx_ip.src)
174 self.assertEqual(rx_ip.dst, tx_ip.dst)
175 # IP processing post pop has decremented the TTL
176 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
177
178 except:
179 raise
180
181 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
182 try:
183 capture = self.verify_filter(capture, sent)
184
185 self.assertEqual(len(capture), len(sent))
186
187 for i in range(len(capture)):
188 tx = sent[i]
189 rx = capture[i]
190 tx_ip = tx[IP]
191 rx_ip = rx[IP]
192
193 # the MPLS TTL is 255 since it enters a new tunnel
194 self.verify_mpls_stack(
195 rx, mpls_labels, 255, len(mpls_labels) - 1)
196
197 self.assertEqual(rx_ip.src, tx_ip.src)
198 self.assertEqual(rx_ip.dst, tx_ip.dst)
199 # IP processing post pop has decremented the TTL
200 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
201
202 except:
203 raise
204
205 def verify_capture_labelled(self, src_if, capture, sent,
206 mpls_labels, ttl=254, num=0):
207 try:
208 capture = self.verify_filter(capture, sent)
209
210 self.assertEqual(len(capture), len(sent))
211
212 for i in range(len(capture)):
213 rx = capture[i]
214 self.verify_mpls_stack(rx, mpls_labels, ttl, num)
215 except:
216 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000217
218 def verify_capture_ip6(self, src_if, capture, sent):
219 try:
220 self.assertEqual(len(capture), len(sent))
221
222 for i in range(len(capture)):
223 tx = sent[i]
224 rx = capture[i]
225
226 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000227 eth = rx[Ether]
228 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000229
230 tx_ip = tx[IPv6]
231 rx_ip = rx[IPv6]
232
233 self.assertEqual(rx_ip.src, tx_ip.src)
234 self.assertEqual(rx_ip.dst, tx_ip.dst)
235 # IP processing post pop has decremented the TTL
236 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
237
238 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000239 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000240
Neale Rannsad422ed2016-11-02 14:20:04 +0000241 def test_swap(self):
242 """ MPLS label swap tests """
243
244 #
245 # A simple MPLS xconnect - eos label in label out
246 #
247 route_32_eos = MplsRoute(self, 32, 1,
248 [RoutePath(self.pg0.remote_ip4,
249 self.pg0.sw_if_index,
250 labels=[33])])
251 route_32_eos.add_vpp_config()
252
253 #
254 # a stream that matches the route for 10.0.0.1
255 # PG0 is in the default table
256 #
257 self.vapi.cli("clear trace")
258 tx = self.create_stream_labelled_ip4(self.pg0, [32])
259 self.pg0.add_stream(tx)
260
261 self.pg_enable_capture(self.pg_interfaces)
262 self.pg_start()
263
264 rx = self.pg0.get_capture()
265 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33])
266
267 #
268 # A simple MPLS xconnect - non-eos label in label out
269 #
270 route_32_neos = MplsRoute(self, 32, 0,
271 [RoutePath(self.pg0.remote_ip4,
272 self.pg0.sw_if_index,
273 labels=[33])])
274 route_32_neos.add_vpp_config()
275
276 #
277 # a stream that matches the route for 10.0.0.1
278 # PG0 is in the default table
279 #
280 self.vapi.cli("clear trace")
281 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
282 self.pg0.add_stream(tx)
283
284 self.pg_enable_capture(self.pg_interfaces)
285 self.pg_start()
286
287 rx = self.pg0.get_capture()
288 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
289
290 #
291 # An MPLS xconnect - EOS label in IP out
292 #
293 route_33_eos = MplsRoute(self, 33, 1,
294 [RoutePath(self.pg0.remote_ip4,
295 self.pg0.sw_if_index,
296 labels=[])])
297 route_33_eos.add_vpp_config()
298
299 self.vapi.cli("clear trace")
300 tx = self.create_stream_labelled_ip4(self.pg0, [33])
301 self.pg0.add_stream(tx)
302
303 self.pg_enable_capture(self.pg_interfaces)
304 self.pg_start()
305
306 rx = self.pg0.get_capture()
307 self.verify_capture_ip4(self.pg0, rx, tx)
308
309 #
310 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
311 # so this traffic should be dropped.
312 #
313 route_33_neos = MplsRoute(self, 33, 0,
314 [RoutePath(self.pg0.remote_ip4,
315 self.pg0.sw_if_index,
316 labels=[])])
317 route_33_neos.add_vpp_config()
318
319 self.vapi.cli("clear trace")
320 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
321 self.pg0.add_stream(tx)
322
323 self.pg_enable_capture(self.pg_interfaces)
324 self.pg_start()
325
326 rx = self.pg0.get_capture()
327 try:
328 self.assertEqual(0, len(rx))
329 except:
330 error("MPLS non-EOS packets popped and forwarded")
331 error(packet.show())
332 raise
333
334 #
335 # A recursive EOS x-connect, which resolves through another x-connect
336 #
337 route_34_eos = MplsRoute(self, 34, 1,
338 [RoutePath("0.0.0.0",
339 0xffffffff,
340 nh_via_label=32,
341 labels=[44, 45])])
342 route_34_eos.add_vpp_config()
343
344 self.vapi.cli("clear trace")
345 tx = self.create_stream_labelled_ip4(self.pg0, [34])
346 self.pg0.add_stream(tx)
347
348 self.pg_enable_capture(self.pg_interfaces)
349 self.pg_start()
350
351 rx = self.pg0.get_capture()
352 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 45])
353
354 #
355 # A recursive non-EOS x-connect, which resolves through another x-connect
356 #
357 route_34_neos = MplsRoute(self, 34, 0,
358 [RoutePath("0.0.0.0",
359 0xffffffff,
360 nh_via_label=32,
361 labels=[44, 46])])
362 route_34_neos.add_vpp_config()
363
364 self.vapi.cli("clear trace")
365 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
366 self.pg0.add_stream(tx)
367
368 self.pg_enable_capture(self.pg_interfaces)
369 self.pg_start()
370
371 rx = self.pg0.get_capture()
372 # it's the 2nd (counting from 0) lael in the stack that is swapped
373 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
374
375 #
376 # an recursive IP route that resolves through the recursive non-eos x-connect
377 #
378 ip_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
379 [RoutePath("0.0.0.0",
380 0xffffffff,
381 nh_via_label=34,
382 labels=[55])])
383 ip_10_0_0_1.add_vpp_config()
384
385 self.vapi.cli("clear trace")
386 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
387 self.pg0.add_stream(tx)
388
389 self.pg_enable_capture(self.pg_interfaces)
390 self.pg_start()
391
392 rx = self.pg0.get_capture()
393 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
394
395 ip_10_0_0_1.remove_vpp_config()
396 route_34_neos.remove_vpp_config()
397 route_34_eos.remove_vpp_config()
398 route_33_neos.remove_vpp_config()
399 route_33_eos.remove_vpp_config()
400 route_32_neos.remove_vpp_config()
401 route_32_eos.remove_vpp_config()
402
403 def test_bind(self):
404 """ MPLS Local Label Binding test """
405
406 #
407 # Add a non-recursive route with a single out label
408 #
409 route_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
410 [RoutePath(self.pg0.remote_ip4,
411 self.pg0.sw_if_index,
412 labels=[45])])
413 route_10_0_0_1.add_vpp_config()
414
415 # bind a local label to the route
416 binding = MplsIpBind(self, 44, "10.0.0.1", 32)
417 binding.add_vpp_config()
418
419 # non-EOS stream
420 self.vapi.cli("clear trace")
421 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
422 self.pg0.add_stream(tx)
423
424 self.pg_enable_capture(self.pg_interfaces)
425 self.pg_start()
426
427 rx = self.pg0.get_capture()
428 self.verify_capture_labelled(self.pg0, rx, tx, [45, 99])
429
430 # EOS stream
431 self.vapi.cli("clear trace")
432 tx = self.create_stream_labelled_ip4(self.pg0, [44])
433 self.pg0.add_stream(tx)
434
435 self.pg_enable_capture(self.pg_interfaces)
436 self.pg_start()
437
438 rx = self.pg0.get_capture()
439 self.verify_capture_labelled(self.pg0, rx, tx, [45])
440
441 # IP stream
442 self.vapi.cli("clear trace")
443 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
444 self.pg0.add_stream(tx)
445
446 self.pg_enable_capture(self.pg_interfaces)
447 self.pg_start()
448
449 rx = self.pg0.get_capture()
450 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [45])
451
452 #
453 # cleanup
454 #
455 binding.remove_vpp_config()
456 route_10_0_0_1.remove_vpp_config()
457
458 def test_imposition(self):
459 """ MPLS label imposition test """
460
461 #
462 # Add a non-recursive route with a single out label
463 #
464 route_10_0_0_1 = IpRoute(self, "10.0.0.1", 32,
465 [RoutePath(self.pg0.remote_ip4,
466 self.pg0.sw_if_index,
467 labels=[32])])
468 route_10_0_0_1.add_vpp_config()
469
470 #
471 # a stream that matches the route for 10.0.0.1
472 # PG0 is in the default table
473 #
474 self.vapi.cli("clear trace")
475 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
476 self.pg0.add_stream(tx)
477
478 self.pg_enable_capture(self.pg_interfaces)
479 self.pg_start()
480
481 rx = self.pg0.get_capture()
482 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32])
483
484 #
485 # Add a non-recursive route with a 3 out labels
486 #
487 route_10_0_0_2 = IpRoute(self, "10.0.0.2", 32,
488 [RoutePath(self.pg0.remote_ip4,
489 self.pg0.sw_if_index,
490 labels=[32, 33, 34])])
491 route_10_0_0_2.add_vpp_config()
492
493 #
494 # a stream that matches the route for 10.0.0.1
495 # PG0 is in the default table
496 #
497 self.vapi.cli("clear trace")
498 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
499 self.pg0.add_stream(tx)
500
501 self.pg_enable_capture(self.pg_interfaces)
502 self.pg_start()
503
504 rx = self.pg0.get_capture()
505 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 33, 34])
506
507 #
508 # add a recursive path, with ouput label, via the 1 label route
509 #
510 route_11_0_0_1 = IpRoute(self, "11.0.0.1", 32,
511 [RoutePath("10.0.0.1",
512 0xffffffff,
513 labels=[44])])
514 route_11_0_0_1.add_vpp_config()
515
516 #
517 # a stream that matches the route for 11.0.0.1, should pick up
518 # the label stack for 11.0.0.1 and 10.0.0.1
519 #
520 self.vapi.cli("clear trace")
521 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
522 self.pg0.add_stream(tx)
523
524 self.pg_enable_capture(self.pg_interfaces)
525 self.pg_start()
526
527 rx = self.pg0.get_capture()
528 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [32, 44])
529
530 #
531 # add a recursive path, with 2 labels, via the 3 label route
532 #
533 route_11_0_0_2 = IpRoute(self, "11.0.0.2", 32,
534 [RoutePath("10.0.0.2",
535 0xffffffff,
536 labels=[44, 45])])
537 route_11_0_0_2.add_vpp_config()
538
539 #
540 # a stream that matches the route for 11.0.0.1, should pick up
541 # the label stack for 11.0.0.1 and 10.0.0.1
542 #
543 self.vapi.cli("clear trace")
544 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
545 self.pg0.add_stream(tx)
546
547 self.pg_enable_capture(self.pg_interfaces)
548 self.pg_start()
549
550 rx = self.pg0.get_capture()
551 self.verify_capture_labelled_ip4(
552 self.pg0, rx, tx, [32, 33, 34, 44, 45])
553
554 #
555 # cleanup
556 #
557 route_11_0_0_2.remove_vpp_config()
558 route_11_0_0_1.remove_vpp_config()
559 route_10_0_0_2.remove_vpp_config()
560 route_10_0_0_1.remove_vpp_config()
561
562 def test_tunnel(self):
563 """ MPLS Tunnel Tests """
564
565 #
566 # Create a tunnel with a single out label
567 #
568 nh_addr = socket.inet_pton(socket.AF_INET, self.pg0.remote_ip4)
569
570 reply = self.vapi.mpls_tunnel_add_del(0xffffffff, # don't know the if index yet
571 1, # IPv4 next-hop
572 nh_addr,
573 self.pg0.sw_if_index,
574 0, # next-hop-table-id
575 1, # next-hop-weight
576 2, # num-out-labels,
577 [44, 46])
578 self.vapi.sw_interface_set_flags(reply.sw_if_index, admin_up_down=1)
579
580 #
581 # add an unlabelled route through the new tunnel
582 #
583 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.3")
584 nh_addr = socket.inet_pton(socket.AF_INET, "0.0.0.0")
585 dest_addr_len = 32
586
587 self.vapi.ip_add_del_route(dest_addr,
588 dest_addr_len,
589 nh_addr, # all zeros next-hop - tunnel is p2p
590 reply.sw_if_index, # sw_if_index of the new tunnel
591 0, # table-id
592 0, # next-hop-table-id
593 1, # next-hop-weight
594 0, # num-out-labels,
595 []) # out-label
596
597 self.vapi.cli("clear trace")
598 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
599 self.pg0.add_stream(tx)
600
601 self.pg_enable_capture(self.pg_interfaces)
602 self.pg_start()
603
604 rx = self.pg0.get_capture()
605 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000606
607 def test_v4_exp_null(self):
608 """ MPLS V4 Explicit NULL test """
609
610 #
611 # The first test case has an MPLS TTL of 0
612 # all packet should be dropped
613 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000614 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000615 self.pg0.add_stream(tx)
616
617 self.pg_enable_capture(self.pg_interfaces)
618 self.pg_start()
619
620 rx = self.pg0.get_capture()
621
622 try:
Neale Rannsad422ed2016-11-02 14:20:04 +0000623 self.assertEqual(0, len(rx))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000624 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100625 self.logger.error("MPLS TTL=0 packets forwarded")
626 self.logger.error(ppp("", rx))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000627 raise
628
629 #
630 # a stream with a non-zero MPLS TTL
631 # PG0 is in the default table
632 #
633 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000634 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000635 self.pg0.add_stream(tx)
636
637 self.pg_enable_capture(self.pg_interfaces)
638 self.pg_start()
639
640 rx = self.pg0.get_capture()
641 self.verify_capture_ip4(self.pg0, rx, tx)
642
643 #
644 # a stream with a non-zero MPLS TTL
645 # PG1 is in table 1
646 # we are ensuring the post-pop lookup occurs in the VRF table
647 #
648 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000649 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000650 self.pg1.add_stream(tx)
651
652 self.pg_enable_capture(self.pg_interfaces)
653 self.pg_start()
654
655 rx = self.pg1.get_capture()
656 self.verify_capture_ip4(self.pg0, rx, tx)
657
658 def test_v6_exp_null(self):
659 """ MPLS V6 Explicit NULL test """
660
661 #
662 # a stream with a non-zero MPLS TTL
663 # PG0 is in the default table
664 #
665 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000666 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000667 self.pg0.add_stream(tx)
668
669 self.pg_enable_capture(self.pg_interfaces)
670 self.pg_start()
671
672 rx = self.pg0.get_capture()
673 self.verify_capture_ip6(self.pg0, rx, tx)
674
675 #
676 # a stream with a non-zero MPLS TTL
677 # PG1 is in table 1
678 # we are ensuring the post-pop lookup occurs in the VRF table
679 #
680 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000681 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000682 self.pg1.add_stream(tx)
683
684 self.pg_enable_capture(self.pg_interfaces)
685 self.pg_start()
686
687 rx = self.pg1.get_capture()
688 self.verify_capture_ip6(self.pg0, rx, tx)
689
690
691if __name__ == '__main__':
692 unittest.main(testRunner=VppTestRunner)