blob: b2226a74bdf48ccbea24bae5dd123ce4f8d13627 [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 Rannsda78f952017-05-24 09:15:43 -07009 MRouteItfFlags, MRouteEntryFlags, DpoProto
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
Klement Sekera7bb873a2016-11-18 07:38:42 +010015from scapy.layers.inet6 import IPv6
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
63
64 for i in self.pg_interfaces:
65 i.admin_up()
66 i.set_table_ip4(table_id)
67 i.set_table_ip6(table_id)
68 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000069 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000070 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000071 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000072 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000073 table_id += 1
74
75 def tearDown(self):
76 super(TestMPLS, self).tearDown()
Neale Ranns4008ac92017-02-13 23:20:04 -080077 for i in self.pg_interfaces:
78 i.unconfig_ip4()
79 i.unconfig_ip6()
80 i.ip6_disable()
81 i.admin_down()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000082
Neale Rannsad422ed2016-11-02 14:20:04 +000083 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +010084 def create_stream_labelled_ip4(
85 self,
86 src_if,
87 mpls_labels,
88 mpls_ttl=255,
89 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080090 ip_itf=None,
91 dst_ip=None,
92 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +010093 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000094 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -080095 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +010096 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000097 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +000098 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
99
100 for ii in range(len(mpls_labels)):
101 if ii == len(mpls_labels) - 1:
102 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1)
103 else:
104 p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0)
Neale Rannscb630ff2016-12-14 13:31:29 +0100105 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800106 if not dst_ip:
107 p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) /
108 UDP(sport=1234, dport=1234) /
109 Raw(payload))
110 else:
111 p = (p / IP(src=src_if.local_ip4, dst=dst_ip) /
112 UDP(sport=1234, dport=1234) /
113 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100114 else:
115 p = (p / IP(src=ip_itf.remote_ip4,
116 dst=ip_itf.local_ip4) /
117 ICMP())
118
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000119 info.data = p.copy()
120 pkts.append(p)
121 return pkts
122
Neale Rannsad422ed2016-11-02 14:20:04 +0000123 def create_stream_ip4(self, src_if, dst_ip):
Klement Sekeradab231a2016-12-21 08:50:14 +0100124 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000125 pkts = []
126 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100127 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000128 payload = self.info_to_payload(info)
129 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
130 IP(src=src_if.remote_ip4, dst=dst_ip) /
131 UDP(sport=1234, dport=1234) /
132 Raw(payload))
133 info.data = p.copy()
134 pkts.append(p)
135 return pkts
136
Neale Ranns31426c62017-05-24 10:32:58 -0700137 def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl,
138 dst_ip=None):
139 if dst_ip is None:
140 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100141 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000142 pkts = []
143 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100144 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000145 payload = self.info_to_payload(info)
146 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
147 MPLS(label=mpls_label, ttl=mpls_ttl) /
Neale Ranns31426c62017-05-24 10:32:58 -0700148 IPv6(src=src_if.remote_ip6, dst=dst_ip) /
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000149 UDP(sport=1234, dport=1234) /
150 Raw(payload))
151 info.data = p.copy()
152 pkts.append(p)
153 return pkts
154
Neale Rannscb630ff2016-12-14 13:31:29 +0100155 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000156 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700157 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000158
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000159 self.assertEqual(len(capture), len(sent))
160
161 for i in range(len(capture)):
162 tx = sent[i]
163 rx = capture[i]
164
165 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000166 eth = rx[Ether]
167 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000168
169 tx_ip = tx[IP]
170 rx_ip = rx[IP]
171
Neale Rannscb630ff2016-12-14 13:31:29 +0100172 if not ping_resp:
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 else:
178 self.assertEqual(rx_ip.src, tx_ip.dst)
179 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000180
181 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000182 raise
183
Neale Rannsad422ed2016-11-02 14:20:04 +0000184 def verify_capture_labelled_ip4(self, src_if, capture, sent,
185 mpls_labels):
186 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700187 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000188
189 self.assertEqual(len(capture), len(sent))
190
191 for i in range(len(capture)):
192 tx = sent[i]
193 rx = capture[i]
194 tx_ip = tx[IP]
195 rx_ip = rx[IP]
196
197 # the MPLS TTL is copied from the IP
Neale Rannsda78f952017-05-24 09:15:43 -0700198 verify_mpls_stack(self, rx, mpls_labels, rx_ip.ttl,
199 len(mpls_labels) - 1)
Neale Rannsad422ed2016-11-02 14:20:04 +0000200
201 self.assertEqual(rx_ip.src, tx_ip.src)
202 self.assertEqual(rx_ip.dst, tx_ip.dst)
203 # IP processing post pop has decremented the TTL
204 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
205
206 except:
207 raise
208
Neale Ranns8c4611b2017-05-23 03:43:47 -0700209 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
210 ttl=255, top=None):
211 if top is None:
212 top = len(mpls_labels) - 1
Neale Rannsad422ed2016-11-02 14:20:04 +0000213 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700214 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000215
216 self.assertEqual(len(capture), len(sent))
217
218 for i in range(len(capture)):
219 tx = sent[i]
220 rx = capture[i]
221 tx_ip = tx[IP]
222 rx_ip = rx[IP]
223
224 # the MPLS TTL is 255 since it enters a new tunnel
Neale Rannsda78f952017-05-24 09:15:43 -0700225 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
Neale Rannsad422ed2016-11-02 14:20:04 +0000226
227 self.assertEqual(rx_ip.src, tx_ip.src)
228 self.assertEqual(rx_ip.dst, tx_ip.dst)
229 # IP processing post pop has decremented the TTL
230 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
231
232 except:
233 raise
234
235 def verify_capture_labelled(self, src_if, capture, sent,
236 mpls_labels, ttl=254, num=0):
237 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700238 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000239
240 self.assertEqual(len(capture), len(sent))
241
242 for i in range(len(capture)):
243 rx = capture[i]
Neale Rannsda78f952017-05-24 09:15:43 -0700244 verify_mpls_stack(self, rx, mpls_labels, ttl, num)
Neale Rannsad422ed2016-11-02 14:20:04 +0000245 except:
246 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000247
248 def verify_capture_ip6(self, src_if, capture, sent):
249 try:
250 self.assertEqual(len(capture), len(sent))
251
252 for i in range(len(capture)):
253 tx = sent[i]
254 rx = capture[i]
255
256 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000257 eth = rx[Ether]
258 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000259
260 tx_ip = tx[IPv6]
261 rx_ip = rx[IPv6]
262
263 self.assertEqual(rx_ip.src, tx_ip.src)
264 self.assertEqual(rx_ip.dst, tx_ip.dst)
265 # IP processing post pop has decremented the TTL
266 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
267
268 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000269 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000270
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800271 def send_and_assert_no_replies(self, intf, pkts, remark):
272 intf.add_stream(pkts)
273 self.pg_enable_capture(self.pg_interfaces)
274 self.pg_start()
275 for i in self.pg_interfaces:
276 i.assert_nothing_captured(remark=remark)
277
Neale Rannsad422ed2016-11-02 14:20:04 +0000278 def test_swap(self):
279 """ MPLS label swap tests """
280
281 #
282 # A simple MPLS xconnect - eos label in label out
283 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800284 route_32_eos = VppMplsRoute(self, 32, 1,
285 [VppRoutePath(self.pg0.remote_ip4,
286 self.pg0.sw_if_index,
287 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000288 route_32_eos.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])
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()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800302 self.verify_capture_labelled(self.pg0, rx, tx, [33])
Neale Rannsad422ed2016-11-02 14:20:04 +0000303
304 #
305 # A simple MPLS xconnect - non-eos label in label out
306 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800307 route_32_neos = VppMplsRoute(self, 32, 0,
308 [VppRoutePath(self.pg0.remote_ip4,
309 self.pg0.sw_if_index,
310 labels=[33])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000311 route_32_neos.add_vpp_config()
312
313 #
314 # a stream that matches the route for 10.0.0.1
315 # PG0 is in the default table
316 #
317 self.vapi.cli("clear trace")
318 tx = self.create_stream_labelled_ip4(self.pg0, [32, 99])
319 self.pg0.add_stream(tx)
320
321 self.pg_enable_capture(self.pg_interfaces)
322 self.pg_start()
323
324 rx = self.pg0.get_capture()
325 self.verify_capture_labelled(self.pg0, rx, tx, [33, 99])
326
327 #
328 # An MPLS xconnect - EOS label in IP out
329 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800330 route_33_eos = VppMplsRoute(self, 33, 1,
331 [VppRoutePath(self.pg0.remote_ip4,
332 self.pg0.sw_if_index,
333 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000334 route_33_eos.add_vpp_config()
335
336 self.vapi.cli("clear trace")
337 tx = self.create_stream_labelled_ip4(self.pg0, [33])
338 self.pg0.add_stream(tx)
339
340 self.pg_enable_capture(self.pg_interfaces)
341 self.pg_start()
342
343 rx = self.pg0.get_capture()
344 self.verify_capture_ip4(self.pg0, rx, tx)
345
346 #
347 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
348 # so this traffic should be dropped.
349 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800350 route_33_neos = VppMplsRoute(self, 33, 0,
351 [VppRoutePath(self.pg0.remote_ip4,
352 self.pg0.sw_if_index,
353 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000354 route_33_neos.add_vpp_config()
355
356 self.vapi.cli("clear trace")
357 tx = self.create_stream_labelled_ip4(self.pg0, [33, 99])
358 self.pg0.add_stream(tx)
359
360 self.pg_enable_capture(self.pg_interfaces)
361 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +0100362 self.pg0.assert_nothing_captured(
363 remark="MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000364
365 #
366 # A recursive EOS x-connect, which resolves through another x-connect
367 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800368 route_34_eos = VppMplsRoute(self, 34, 1,
369 [VppRoutePath("0.0.0.0",
370 0xffffffff,
371 nh_via_label=32,
372 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000373 route_34_eos.add_vpp_config()
374
Neale Rannsad422ed2016-11-02 14:20:04 +0000375 tx = self.create_stream_labelled_ip4(self.pg0, [34])
376 self.pg0.add_stream(tx)
377
378 self.pg_enable_capture(self.pg_interfaces)
379 self.pg_start()
380
381 rx = self.pg0.get_capture()
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800382 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 45], num=2)
Neale Rannsad422ed2016-11-02 14:20:04 +0000383
384 #
Matej Klottondeb69842016-12-09 15:05:46 +0100385 # A recursive non-EOS x-connect, which resolves through another
386 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000387 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800388 route_34_neos = VppMplsRoute(self, 34, 0,
389 [VppRoutePath("0.0.0.0",
390 0xffffffff,
391 nh_via_label=32,
392 labels=[44, 46])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000393 route_34_neos.add_vpp_config()
394
395 self.vapi.cli("clear trace")
396 tx = self.create_stream_labelled_ip4(self.pg0, [34, 99])
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()
Matej Klottondeb69842016-12-09 15:05:46 +0100403 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Rannsad422ed2016-11-02 14:20:04 +0000404 self.verify_capture_labelled(self.pg0, rx, tx, [33, 44, 46, 99], num=2)
405
406 #
Matej Klottondeb69842016-12-09 15:05:46 +0100407 # an recursive IP route that resolves through the recursive non-eos
408 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000409 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800410 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
411 [VppRoutePath("0.0.0.0",
412 0xffffffff,
413 nh_via_label=34,
414 labels=[55])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000415 ip_10_0_0_1.add_vpp_config()
416
417 self.vapi.cli("clear trace")
418 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
419 self.pg0.add_stream(tx)
420
421 self.pg_enable_capture(self.pg_interfaces)
422 self.pg_start()
423
424 rx = self.pg0.get_capture()
425 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [33, 44, 46, 55])
426
427 ip_10_0_0_1.remove_vpp_config()
428 route_34_neos.remove_vpp_config()
429 route_34_eos.remove_vpp_config()
430 route_33_neos.remove_vpp_config()
431 route_33_eos.remove_vpp_config()
432 route_32_neos.remove_vpp_config()
433 route_32_eos.remove_vpp_config()
434
435 def test_bind(self):
436 """ MPLS Local Label Binding test """
437
438 #
439 # Add a non-recursive route with a single out label
440 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800441 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
442 [VppRoutePath(self.pg0.remote_ip4,
443 self.pg0.sw_if_index,
444 labels=[45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000445 route_10_0_0_1.add_vpp_config()
446
447 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800448 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000449 binding.add_vpp_config()
450
451 # non-EOS stream
452 self.vapi.cli("clear trace")
453 tx = self.create_stream_labelled_ip4(self.pg0, [44, 99])
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(self.pg0, rx, tx, [45, 99])
461
462 # EOS stream
463 self.vapi.cli("clear trace")
464 tx = self.create_stream_labelled_ip4(self.pg0, [44])
465 self.pg0.add_stream(tx)
466
467 self.pg_enable_capture(self.pg_interfaces)
468 self.pg_start()
469
470 rx = self.pg0.get_capture()
471 self.verify_capture_labelled(self.pg0, rx, tx, [45])
472
473 # IP stream
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, [45])
483
484 #
485 # cleanup
486 #
487 binding.remove_vpp_config()
488 route_10_0_0_1.remove_vpp_config()
489
490 def test_imposition(self):
491 """ MPLS label imposition test """
492
493 #
494 # Add a non-recursive route with a single out label
495 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800496 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
497 [VppRoutePath(self.pg0.remote_ip4,
498 self.pg0.sw_if_index,
499 labels=[32])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000500 route_10_0_0_1.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.1")
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])
515
516 #
517 # Add a non-recursive route with a 3 out labels
518 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800519 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
520 [VppRoutePath(self.pg0.remote_ip4,
521 self.pg0.sw_if_index,
522 labels=[32, 33, 34])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000523 route_10_0_0_2.add_vpp_config()
524
525 #
526 # a stream that matches the route for 10.0.0.1
527 # PG0 is in the default table
528 #
529 self.vapi.cli("clear trace")
530 tx = self.create_stream_ip4(self.pg0, "10.0.0.2")
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, 33, 34])
538
539 #
Matej Klottondeb69842016-12-09 15:05:46 +0100540 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000541 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800542 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
543 [VppRoutePath("10.0.0.1",
544 0xffffffff,
545 labels=[44])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000546 route_11_0_0_1.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.1")
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(self.pg0, rx, tx, [32, 44])
561
562 #
563 # add a recursive path, with 2 labels, via the 3 label route
564 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800565 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
566 [VppRoutePath("10.0.0.2",
567 0xffffffff,
568 labels=[44, 45])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000569 route_11_0_0_2.add_vpp_config()
570
571 #
572 # a stream that matches the route for 11.0.0.1, should pick up
573 # the label stack for 11.0.0.1 and 10.0.0.1
574 #
575 self.vapi.cli("clear trace")
576 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
577 self.pg0.add_stream(tx)
578
579 self.pg_enable_capture(self.pg_interfaces)
580 self.pg_start()
581
582 rx = self.pg0.get_capture()
583 self.verify_capture_labelled_ip4(
584 self.pg0, rx, tx, [32, 33, 34, 44, 45])
585
586 #
587 # cleanup
588 #
589 route_11_0_0_2.remove_vpp_config()
590 route_11_0_0_1.remove_vpp_config()
591 route_10_0_0_2.remove_vpp_config()
592 route_10_0_0_1.remove_vpp_config()
593
594 def test_tunnel(self):
595 """ MPLS Tunnel Tests """
596
597 #
598 # Create a tunnel with a single out label
599 #
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800600 mpls_tun = VppMPLSTunnelInterface(self,
601 [VppRoutePath(self.pg0.remote_ip4,
602 self.pg0.sw_if_index,
603 labels=[44, 46])])
604 mpls_tun.add_vpp_config()
605 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000606
607 #
608 # add an unlabelled route through the new tunnel
609 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800610 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
611 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800612 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800613 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000614
615 self.vapi.cli("clear trace")
616 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
617 self.pg0.add_stream(tx)
618
619 self.pg_enable_capture(self.pg_interfaces)
620 self.pg_start()
621
622 rx = self.pg0.get_capture()
623 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000624
Neale Ranns8c4611b2017-05-23 03:43:47 -0700625 #
626 # add a labelled route through the new tunnel
627 #
628 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
629 [VppRoutePath("0.0.0.0",
630 mpls_tun._sw_if_index,
631 labels=[33])])
632 route_10_0_0_4.add_vpp_config()
633
634 self.vapi.cli("clear trace")
635 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
636 self.pg0.add_stream(tx)
637
638 self.pg_enable_capture(self.pg_interfaces)
639 self.pg_start()
640
641 rx = self.pg0.get_capture()
642 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
643 ttl=63, top=2)
644
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000645 def test_v4_exp_null(self):
646 """ MPLS V4 Explicit NULL test """
647
648 #
649 # The first test case has an MPLS TTL of 0
650 # all packet should be dropped
651 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000652 tx = self.create_stream_labelled_ip4(self.pg0, [0], 0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000653 self.pg0.add_stream(tx)
654
655 self.pg_enable_capture(self.pg_interfaces)
656 self.pg_start()
657
Klement Sekera9225dee2016-12-12 08:36:58 +0100658 self.pg0.assert_nothing_captured(remark="MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000659
660 #
661 # a stream with a non-zero MPLS TTL
662 # PG0 is in the default table
663 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000664 tx = self.create_stream_labelled_ip4(self.pg0, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000665 self.pg0.add_stream(tx)
666
667 self.pg_enable_capture(self.pg_interfaces)
668 self.pg_start()
669
670 rx = self.pg0.get_capture()
671 self.verify_capture_ip4(self.pg0, rx, tx)
672
673 #
674 # a stream with a non-zero MPLS TTL
675 # PG1 is in table 1
676 # we are ensuring the post-pop lookup occurs in the VRF table
677 #
678 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000679 tx = self.create_stream_labelled_ip4(self.pg1, [0])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000680 self.pg1.add_stream(tx)
681
682 self.pg_enable_capture(self.pg_interfaces)
683 self.pg_start()
684
685 rx = self.pg1.get_capture()
686 self.verify_capture_ip4(self.pg0, rx, tx)
687
688 def test_v6_exp_null(self):
689 """ MPLS V6 Explicit NULL test """
690
691 #
692 # a stream with a non-zero MPLS TTL
693 # PG0 is in the default table
694 #
695 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000696 tx = self.create_stream_labelled_ip6(self.pg0, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000697 self.pg0.add_stream(tx)
698
699 self.pg_enable_capture(self.pg_interfaces)
700 self.pg_start()
701
702 rx = self.pg0.get_capture()
703 self.verify_capture_ip6(self.pg0, rx, tx)
704
705 #
706 # a stream with a non-zero MPLS TTL
707 # PG1 is in table 1
708 # we are ensuring the post-pop lookup occurs in the VRF table
709 #
710 self.vapi.cli("clear trace")
Neale Rannsad422ed2016-11-02 14:20:04 +0000711 tx = self.create_stream_labelled_ip6(self.pg1, 2, 2)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000712 self.pg1.add_stream(tx)
713
714 self.pg_enable_capture(self.pg_interfaces)
715 self.pg_start()
716
717 rx = self.pg1.get_capture()
718 self.verify_capture_ip6(self.pg0, rx, tx)
719
Neale Rannscb630ff2016-12-14 13:31:29 +0100720 def test_deag(self):
721 """ MPLS Deagg """
722
723 #
724 # A de-agg route - next-hop lookup in default table
725 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800726 route_34_eos = VppMplsRoute(self, 34, 1,
727 [VppRoutePath("0.0.0.0",
728 0xffffffff,
729 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100730 route_34_eos.add_vpp_config()
731
732 #
733 # ping an interface in the default table
734 # PG0 is in the default table
735 #
736 self.vapi.cli("clear trace")
737 tx = self.create_stream_labelled_ip4(self.pg0, [34], ping=1,
738 ip_itf=self.pg0)
739 self.pg0.add_stream(tx)
740
741 self.pg_enable_capture(self.pg_interfaces)
742 self.pg_start()
743
744 rx = self.pg0.get_capture()
745 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
746
747 #
748 # A de-agg route - next-hop lookup in non-default table
749 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800750 route_35_eos = VppMplsRoute(self, 35, 1,
751 [VppRoutePath("0.0.0.0",
752 0xffffffff,
753 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +0100754 route_35_eos.add_vpp_config()
755
756 #
757 # ping an interface in the non-default table
758 # PG0 is in the default table. packet arrive labelled in the
759 # default table and egress unlabelled in the non-default
760 #
761 self.vapi.cli("clear trace")
Klement Sekeradab231a2016-12-21 08:50:14 +0100762 tx = self.create_stream_labelled_ip4(
763 self.pg0, [35], ping=1, ip_itf=self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +0100764 self.pg0.add_stream(tx)
765
766 self.pg_enable_capture(self.pg_interfaces)
767 self.pg_start()
768
Klement Sekeradab231a2016-12-21 08:50:14 +0100769 packet_count = self.get_packet_count_for_if_idx(self.pg0.sw_if_index)
770 rx = self.pg1.get_capture(packet_count)
Neale Rannscb630ff2016-12-14 13:31:29 +0100771 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
772
Neale Ranns6af1c042017-05-26 03:48:53 -0700773 #
774 # Double pop
775 #
776 route_36_neos = VppMplsRoute(self, 36, 0,
777 [VppRoutePath("0.0.0.0",
778 0xffffffff)])
779 route_36_neos.add_vpp_config()
780
781 self.vapi.cli("clear trace")
782 tx = self.create_stream_labelled_ip4(self.pg0, [36, 35],
783 ping=1, ip_itf=self.pg1)
784 self.pg0.add_stream(tx)
785
786 self.pg_enable_capture(self.pg_interfaces)
787 self.pg_start()
788
789 rx = self.pg1.get_capture(len(tx))
790 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
791
792 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +0100793 route_35_eos.remove_vpp_config()
794 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000795
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800796 def test_interface_rx(self):
797 """ MPLS Interface Receive """
798
799 #
800 # Add a non-recursive route that will forward the traffic
801 # post-interface-rx
802 #
803 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
804 table_id=1,
805 paths=[VppRoutePath(self.pg1.remote_ip4,
806 self.pg1.sw_if_index)])
807 route_10_0_0_1.add_vpp_config()
808
809 #
810 # An interface receive label that maps traffic to RX on interface
811 # pg1
812 # by injecting the packet in on pg0, which is in table 0
813 # doing an interface-rx on pg1 and matching a route in table 1
814 # if the packet egresses, then we must have swapped to pg1
815 # so as to have matched the route in table 1
816 #
817 route_34_eos = VppMplsRoute(self, 34, 1,
818 [VppRoutePath("0.0.0.0",
819 self.pg1.sw_if_index,
820 is_interface_rx=1)])
821 route_34_eos.add_vpp_config()
822
823 #
824 # ping an interface in the default table
825 # PG0 is in the default table
826 #
827 self.vapi.cli("clear trace")
828 tx = self.create_stream_labelled_ip4(self.pg0, [34], n=257,
829 dst_ip="10.0.0.1")
830 self.pg0.add_stream(tx)
831
832 self.pg_enable_capture(self.pg_interfaces)
833 self.pg_start()
834
835 rx = self.pg1.get_capture(257)
836 self.verify_capture_ip4(self.pg1, rx, tx)
837
838 def test_mcast_mid_point(self):
839 """ MPLS Multicast Mid Point """
840
841 #
842 # Add a non-recursive route that will forward the traffic
843 # post-interface-rx
844 #
845 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
846 table_id=1,
847 paths=[VppRoutePath(self.pg1.remote_ip4,
848 self.pg1.sw_if_index)])
849 route_10_0_0_1.add_vpp_config()
850
851 #
852 # Add a mcast entry that replicate to pg2 and pg3
853 # and replicate to a interface-rx (like a bud node would)
854 #
855 route_3400_eos = VppMplsRoute(self, 3400, 1,
856 [VppRoutePath(self.pg2.remote_ip4,
857 self.pg2.sw_if_index,
858 labels=[3401]),
859 VppRoutePath(self.pg3.remote_ip4,
860 self.pg3.sw_if_index,
861 labels=[3402]),
862 VppRoutePath("0.0.0.0",
863 self.pg1.sw_if_index,
864 is_interface_rx=1)],
865 is_multicast=1)
866 route_3400_eos.add_vpp_config()
867
868 #
869 # ping an interface in the default table
870 # PG0 is in the default table
871 #
872 self.vapi.cli("clear trace")
873 tx = self.create_stream_labelled_ip4(self.pg0, [3400], n=257,
874 dst_ip="10.0.0.1")
875 self.pg0.add_stream(tx)
876
877 self.pg_enable_capture(self.pg_interfaces)
878 self.pg_start()
879
880 rx = self.pg1.get_capture(257)
881 self.verify_capture_ip4(self.pg1, rx, tx)
882
883 rx = self.pg2.get_capture(257)
884 self.verify_capture_labelled(self.pg2, rx, tx, [3401])
885 rx = self.pg3.get_capture(257)
886 self.verify_capture_labelled(self.pg3, rx, tx, [3402])
887
888 def test_mcast_head(self):
889 """ MPLS Multicast Head-end """
890
891 #
892 # Create a multicast tunnel with two replications
893 #
894 mpls_tun = VppMPLSTunnelInterface(self,
895 [VppRoutePath(self.pg2.remote_ip4,
896 self.pg2.sw_if_index,
897 labels=[42]),
898 VppRoutePath(self.pg3.remote_ip4,
899 self.pg3.sw_if_index,
900 labels=[43])],
901 is_multicast=1)
902 mpls_tun.add_vpp_config()
903 mpls_tun.admin_up()
904
905 #
906 # add an unlabelled route through the new tunnel
907 #
908 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
909 [VppRoutePath("0.0.0.0",
910 mpls_tun._sw_if_index)])
911 route_10_0_0_3.add_vpp_config()
912
913 self.vapi.cli("clear trace")
914 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
915 self.pg0.add_stream(tx)
916
917 self.pg_enable_capture(self.pg_interfaces)
918 self.pg_start()
919
920 rx = self.pg2.get_capture(257)
921 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
922 rx = self.pg3.get_capture(257)
923 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
924
925 #
926 # An an IP multicast route via the tunnel
927 # A (*,G).
928 # one accepting interface, pg0, 1 forwarding interface via the tunnel
929 #
930 route_232_1_1_1 = VppIpMRoute(
931 self,
932 "0.0.0.0",
933 "232.1.1.1", 32,
934 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
935 [VppMRoutePath(self.pg0.sw_if_index,
936 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
937 VppMRoutePath(mpls_tun._sw_if_index,
938 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
939 route_232_1_1_1.add_vpp_config()
940
941 self.vapi.cli("clear trace")
942 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
943 self.pg0.add_stream(tx)
944
945 self.pg_enable_capture(self.pg_interfaces)
946 self.pg_start()
947
948 rx = self.pg2.get_capture(257)
949 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [42])
950 rx = self.pg3.get_capture(257)
951 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [43])
952
Neale Ranns31426c62017-05-24 10:32:58 -0700953 def test_mcast_ip4_tail(self):
954 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800955
956 #
957 # Add a multicast route that will forward the traffic
958 # post-disposition
959 #
960 route_232_1_1_1 = VppIpMRoute(
961 self,
962 "0.0.0.0",
963 "232.1.1.1", 32,
964 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
965 table_id=1,
966 paths=[VppMRoutePath(self.pg1.sw_if_index,
967 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
968 route_232_1_1_1.add_vpp_config()
969
970 #
971 # An interface receive label that maps traffic to RX on interface
972 # pg1
973 # by injecting the packet in on pg0, which is in table 0
974 # doing an rpf-id and matching a route in table 1
975 # if the packet egresses, then we must have matched the route in
976 # table 1
977 #
978 route_34_eos = VppMplsRoute(self, 34, 1,
979 [VppRoutePath("0.0.0.0",
980 self.pg1.sw_if_index,
981 nh_table_id=1,
982 rpf_id=55)],
983 is_multicast=1)
984
985 route_34_eos.add_vpp_config()
986
987 #
988 # Drop due to interface lookup miss
989 #
990 self.vapi.cli("clear trace")
991 tx = self.create_stream_labelled_ip4(self.pg0, [34],
992 dst_ip="232.1.1.1", n=1)
993 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
994
995 #
996 # set the RPF-ID of the enrtry to match the input packet's
997 #
998 route_232_1_1_1.update_rpf_id(55)
999
1000 self.vapi.cli("clear trace")
1001 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1002 dst_ip="232.1.1.1", n=257)
1003 self.pg0.add_stream(tx)
1004
1005 self.pg_enable_capture(self.pg_interfaces)
1006 self.pg_start()
1007
1008 rx = self.pg1.get_capture(257)
1009 self.verify_capture_ip4(self.pg1, rx, tx)
1010
1011 #
1012 # set the RPF-ID of the enrtry to not match the input packet's
1013 #
1014 route_232_1_1_1.update_rpf_id(56)
1015 tx = self.create_stream_labelled_ip4(self.pg0, [34],
1016 dst_ip="232.1.1.1")
1017 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1018
Neale Ranns31426c62017-05-24 10:32:58 -07001019 def test_mcast_ip6_tail(self):
1020 """ MPLS IPv6 Multicast Tail """
1021
1022 #
1023 # Add a multicast route that will forward the traffic
1024 # post-disposition
1025 #
1026 route_ff = VppIpMRoute(
1027 self,
1028 "::",
1029 "ff01::1", 32,
1030 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1031 table_id=1,
1032 paths=[VppMRoutePath(self.pg1.sw_if_index,
1033 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
1034 is_ip6=1)
1035 route_ff.add_vpp_config()
1036
1037 #
1038 # An interface receive label that maps traffic to RX on interface
1039 # pg1
1040 # by injecting the packet in on pg0, which is in table 0
1041 # doing an rpf-id and matching a route in table 1
1042 # if the packet egresses, then we must have matched the route in
1043 # table 1
1044 #
1045 route_34_eos = VppMplsRoute(
1046 self, 34, 1,
1047 [VppRoutePath("::",
1048 self.pg1.sw_if_index,
1049 nh_table_id=1,
1050 rpf_id=55,
Neale Rannsda78f952017-05-24 09:15:43 -07001051 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns31426c62017-05-24 10:32:58 -07001052 is_multicast=1)
1053
1054 route_34_eos.add_vpp_config()
1055
1056 #
1057 # Drop due to interface lookup miss
1058 #
1059 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1060 dst_ip="ff01::1")
1061
1062 #
1063 # set the RPF-ID of the enrtry to match the input packet's
1064 #
1065 route_ff.update_rpf_id(55)
1066
1067 tx = self.create_stream_labelled_ip6(self.pg0, [34], 255,
1068 dst_ip="ff01::1")
1069 self.pg0.add_stream(tx)
1070
1071 self.pg_enable_capture(self.pg_interfaces)
1072 self.pg_start()
1073
1074 rx = self.pg1.get_capture(257)
1075 self.verify_capture_ip6(self.pg1, rx, tx)
1076
1077 #
1078 # set the RPF-ID of the enrtry to not match the input packet's
1079 #
1080 route_ff.update_rpf_id(56)
1081 tx = self.create_stream_labelled_ip6(self.pg0, [34], 225,
1082 dst_ip="ff01::1")
1083 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1084
Neale Ranns180279b2017-03-16 15:49:09 -04001085
1086class TestMPLSDisabled(VppTestCase):
1087 """ MPLS disabled """
1088
1089 def setUp(self):
1090 super(TestMPLSDisabled, self).setUp()
1091
1092 # create 2 pg interfaces
1093 self.create_pg_interfaces(range(2))
1094
1095 # PG0 is MPLS enalbed
1096 self.pg0.admin_up()
1097 self.pg0.config_ip4()
1098 self.pg0.resolve_arp()
1099 self.pg0.enable_mpls()
1100
1101 # PG 1 is not MPLS enabled
1102 self.pg1.admin_up()
1103
1104 def tearDown(self):
1105 super(TestMPLSDisabled, self).tearDown()
1106 for i in self.pg_interfaces:
1107 i.unconfig_ip4()
1108 i.admin_down()
1109
1110 def send_and_assert_no_replies(self, intf, pkts, remark):
1111 intf.add_stream(pkts)
1112 self.pg_enable_capture(self.pg_interfaces)
1113 self.pg_start()
1114 for i in self.pg_interfaces:
1115 i.get_capture(0)
1116 i.assert_nothing_captured(remark=remark)
1117
1118 def test_mpls_disabled(self):
1119 """ MPLS Disabled """
1120
1121 tx = (Ether(src=self.pg1.remote_mac,
1122 dst=self.pg1.local_mac) /
1123 MPLS(label=32, ttl=64) /
1124 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1125 UDP(sport=1234, dport=1234) /
1126 Raw('\xa5' * 100))
1127
1128 #
1129 # A simple MPLS xconnect - eos label in label out
1130 #
1131 route_32_eos = VppMplsRoute(self, 32, 1,
1132 [VppRoutePath(self.pg0.remote_ip4,
1133 self.pg0.sw_if_index,
1134 labels=[33])])
1135 route_32_eos.add_vpp_config()
1136
1137 #
1138 # PG1 does not forward IP traffic
1139 #
1140 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1141
1142 #
1143 # MPLS enable PG1
1144 #
1145 self.pg1.enable_mpls()
1146
1147 #
1148 # Now we get packets through
1149 #
1150 self.pg1.add_stream(tx)
1151 self.pg_enable_capture(self.pg_interfaces)
1152 self.pg_start()
1153
1154 rx = self.pg0.get_capture(1)
1155
1156 #
1157 # Disable PG1
1158 #
1159 self.pg1.disable_mpls()
1160
1161 #
1162 # PG1 does not forward IP traffic
1163 #
1164 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1165 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1166
1167
Neale Rannsf12a83f2017-04-18 09:09:40 -07001168class TestMPLSPIC(VppTestCase):
1169 """ MPLS PIC edge convergence """
1170
1171 def setUp(self):
1172 super(TestMPLSPIC, self).setUp()
1173
1174 # create 2 pg interfaces
1175 self.create_pg_interfaces(range(4))
1176
1177 # core links
1178 self.pg0.admin_up()
1179 self.pg0.config_ip4()
1180 self.pg0.resolve_arp()
1181 self.pg0.enable_mpls()
1182 self.pg1.admin_up()
1183 self.pg1.config_ip4()
1184 self.pg1.resolve_arp()
1185 self.pg1.enable_mpls()
1186
1187 # VRF (customer facing) link
1188 self.pg2.admin_up()
1189 self.pg2.set_table_ip4(1)
1190 self.pg2.config_ip4()
1191 self.pg2.resolve_arp()
1192 self.pg2.set_table_ip6(1)
1193 self.pg2.config_ip6()
1194 self.pg2.resolve_ndp()
1195 self.pg3.admin_up()
1196 self.pg3.set_table_ip4(1)
1197 self.pg3.config_ip4()
1198 self.pg3.resolve_arp()
1199 self.pg3.set_table_ip6(1)
1200 self.pg3.config_ip6()
1201 self.pg3.resolve_ndp()
1202
1203 def tearDown(self):
1204 super(TestMPLSPIC, self).tearDown()
1205 self.pg0.disable_mpls()
1206 for i in self.pg_interfaces:
1207 i.unconfig_ip4()
1208 i.unconfig_ip6()
1209 i.set_table_ip4(0)
1210 i.set_table_ip6(0)
1211 i.admin_down()
1212
1213 def test_mpls_ibgp_pic(self):
1214 """ MPLS iBGP PIC edge convergence
1215
1216 1) setup many iBGP VPN routes via a pair of iBGP peers.
1217 2) Check EMCP forwarding to these peers
1218 3) withdraw the IGP route to one of these peers.
1219 4) check forwarding continues to the remaining peer
1220 """
1221
1222 #
1223 # IGP+LDP core routes
1224 #
1225 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1226 [VppRoutePath(self.pg0.remote_ip4,
1227 self.pg0.sw_if_index,
1228 labels=[45])])
1229 core_10_0_0_45.add_vpp_config()
1230
1231 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1232 [VppRoutePath(self.pg1.remote_ip4,
1233 self.pg1.sw_if_index,
1234 labels=[46])])
1235 core_10_0_0_46.add_vpp_config()
1236
1237 #
1238 # Lot's of VPN routes. We need more the 64 so VPP will build
1239 # the fast convergence indirection
1240 #
1241 vpn_routes = []
1242 pkts = []
1243 for ii in range(64):
1244 dst = "192.168.1.%d" % ii
1245 vpn_routes.append(VppIpRoute(self, dst, 32,
1246 [VppRoutePath("10.0.0.45",
1247 0xffffffff,
1248 labels=[145],
1249 is_resolve_host=1),
1250 VppRoutePath("10.0.0.46",
1251 0xffffffff,
1252 labels=[146],
1253 is_resolve_host=1)],
1254 table_id=1))
1255 vpn_routes[ii].add_vpp_config()
1256
1257 pkts.append(Ether(dst=self.pg2.local_mac,
1258 src=self.pg2.remote_mac) /
1259 IP(src=self.pg2.remote_ip4, dst=dst) /
1260 UDP(sport=1234, dport=1234) /
1261 Raw('\xa5' * 100))
1262
1263 #
1264 # Send the packet stream (one pkt to each VPN route)
1265 # - expect a 50-50 split of the traffic
1266 #
1267 self.pg2.add_stream(pkts)
1268 self.pg_enable_capture(self.pg_interfaces)
1269 self.pg_start()
1270
1271 rx0 = self.pg0._get_capture(1)
1272 rx1 = self.pg1._get_capture(1)
1273
1274 # not testig the LB hashing algorithm so we're not concerned
1275 # with the split ratio, just as long as neither is 0
1276 self.assertNotEqual(0, len(rx0))
1277 self.assertNotEqual(0, len(rx1))
1278
1279 #
1280 # use a test CLI command to stop the FIB walk process, this
1281 # will prevent the FIB converging the VPN routes and thus allow
1282 # us to probe the interim (psot-fail, pre-converge) state
1283 #
1284 self.vapi.ppcli("test fib-walk-process disable")
1285
1286 #
1287 # Withdraw one of the IGP routes
1288 #
1289 core_10_0_0_46.remove_vpp_config()
1290
1291 #
1292 # now all packets should be forwarded through the remaining peer
1293 #
1294 self.vapi.ppcli("clear trace")
1295 self.pg2.add_stream(pkts)
1296 self.pg_enable_capture(self.pg_interfaces)
1297 self.pg_start()
1298
1299 rx0 = self.pg0.get_capture(len(pkts))
1300
1301 #
1302 # enable the FIB walk process to converge the FIB
1303 #
1304 self.vapi.ppcli("test fib-walk-process enable")
1305
1306 #
1307 # packets should still be forwarded through the remaining peer
1308 #
1309 self.pg2.add_stream(pkts)
1310 self.pg_enable_capture(self.pg_interfaces)
1311 self.pg_start()
1312
1313 rx0 = self.pg0.get_capture(64)
1314
1315 #
1316 # Add the IGP route back and we return to load-balancing
1317 #
1318 core_10_0_0_46.add_vpp_config()
1319
1320 self.pg2.add_stream(pkts)
1321 self.pg_enable_capture(self.pg_interfaces)
1322 self.pg_start()
1323
1324 rx0 = self.pg0._get_capture(1)
1325 rx1 = self.pg1._get_capture(1)
1326 self.assertNotEqual(0, len(rx0))
1327 self.assertNotEqual(0, len(rx1))
1328
1329 def test_mpls_ebgp_pic(self):
1330 """ MPLS eBGP PIC edge convergence
1331
1332 1) setup many eBGP VPN routes via a pair of eBGP peers
1333 2) Check EMCP forwarding to these peers
1334 3) withdraw one eBGP path - expect LB across remaining eBGP
1335 """
1336
1337 #
1338 # Lot's of VPN routes. We need more the 64 so VPP will build
1339 # the fast convergence indirection
1340 #
1341 vpn_routes = []
1342 vpn_bindings = []
1343 pkts = []
1344 for ii in range(64):
1345 dst = "192.168.1.%d" % ii
1346 local_label = 1600 + ii
1347 vpn_routes.append(VppIpRoute(self, dst, 32,
1348 [VppRoutePath(self.pg2.remote_ip4,
1349 0xffffffff,
1350 nh_table_id=1,
1351 is_resolve_attached=1),
1352 VppRoutePath(self.pg3.remote_ip4,
1353 0xffffffff,
1354 nh_table_id=1,
1355 is_resolve_attached=1)],
1356 table_id=1))
1357 vpn_routes[ii].add_vpp_config()
1358
1359 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1360 ip_table_id=1))
1361 vpn_bindings[ii].add_vpp_config()
1362
1363 pkts.append(Ether(dst=self.pg0.local_mac,
1364 src=self.pg0.remote_mac) /
1365 MPLS(label=local_label, ttl=64) /
1366 IP(src=self.pg0.remote_ip4, dst=dst) /
1367 UDP(sport=1234, dport=1234) /
1368 Raw('\xa5' * 100))
1369
1370 self.pg0.add_stream(pkts)
1371 self.pg_enable_capture(self.pg_interfaces)
1372 self.pg_start()
1373
1374 rx0 = self.pg2._get_capture(1)
1375 rx1 = self.pg3._get_capture(1)
1376 self.assertNotEqual(0, len(rx0))
1377 self.assertNotEqual(0, len(rx1))
1378
1379 #
1380 # use a test CLI command to stop the FIB walk process, this
1381 # will prevent the FIB converging the VPN routes and thus allow
1382 # us to probe the interim (psot-fail, pre-converge) state
1383 #
1384 self.vapi.ppcli("test fib-walk-process disable")
1385
1386 #
1387 # withdraw the connected prefix on the interface.
1388 #
1389 self.pg2.unconfig_ip4()
1390
1391 #
1392 # now all packets should be forwarded through the remaining peer
1393 #
1394 self.pg0.add_stream(pkts)
1395 self.pg_enable_capture(self.pg_interfaces)
1396 self.pg_start()
1397
1398 rx0 = self.pg3.get_capture(len(pkts))
1399
1400 #
1401 # enable the FIB walk process to converge the FIB
1402 #
1403 self.vapi.ppcli("test fib-walk-process enable")
1404 self.pg0.add_stream(pkts)
1405 self.pg_enable_capture(self.pg_interfaces)
1406 self.pg_start()
1407
1408 rx0 = self.pg3.get_capture(len(pkts))
1409
1410 #
1411 # put the connecteds back
1412 #
1413 self.pg2.config_ip4()
1414
1415 self.pg0.add_stream(pkts)
1416 self.pg_enable_capture(self.pg_interfaces)
1417 self.pg_start()
1418
1419 rx0 = self.pg2._get_capture(1)
1420 rx1 = self.pg3._get_capture(1)
1421 self.assertNotEqual(0, len(rx0))
1422 self.assertNotEqual(0, len(rx1))
1423
1424 def test_mpls_v6_ebgp_pic(self):
1425 """ MPLSv6 eBGP PIC edge convergence
1426
1427 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1428 2) Check EMCP forwarding to these peers
1429 3) withdraw one eBGP path - expect LB across remaining eBGP
1430 """
1431
1432 #
1433 # Lot's of VPN routes. We need more the 64 so VPP will build
1434 # the fast convergence indirection
1435 #
1436 vpn_routes = []
1437 vpn_bindings = []
1438 pkts = []
1439 for ii in range(64):
1440 dst = "3000::%d" % ii
1441 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001442 vpn_routes.append(VppIpRoute(
1443 self, dst, 128,
1444 [VppRoutePath(self.pg2.remote_ip6,
1445 0xffffffff,
1446 nh_table_id=1,
1447 is_resolve_attached=1,
1448 proto=DpoProto.DPO_PROTO_IP6),
1449 VppRoutePath(self.pg3.remote_ip6,
1450 0xffffffff,
1451 nh_table_id=1,
1452 proto=DpoProto.DPO_PROTO_IP6,
1453 is_resolve_attached=1)],
1454 table_id=1,
1455 is_ip6=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001456 vpn_routes[ii].add_vpp_config()
1457
1458 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
1459 ip_table_id=1,
1460 is_ip6=1))
1461 vpn_bindings[ii].add_vpp_config()
1462
1463 pkts.append(Ether(dst=self.pg0.local_mac,
1464 src=self.pg0.remote_mac) /
1465 MPLS(label=local_label, ttl=64) /
1466 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1467 UDP(sport=1234, dport=1234) /
1468 Raw('\xa5' * 100))
1469
1470 self.pg0.add_stream(pkts)
1471 self.pg_enable_capture(self.pg_interfaces)
1472 self.pg_start()
1473
1474 rx0 = self.pg2._get_capture(1)
1475 rx1 = self.pg3._get_capture(1)
1476 self.assertNotEqual(0, len(rx0))
1477 self.assertNotEqual(0, len(rx1))
1478
1479 #
1480 # use a test CLI command to stop the FIB walk process, this
1481 # will prevent the FIB converging the VPN routes and thus allow
1482 # us to probe the interim (psot-fail, pre-converge) state
1483 #
1484 self.vapi.ppcli("test fib-walk-process disable")
1485
1486 #
1487 # withdraw the connected prefix on the interface.
1488 # and shutdown the interface so the ND cache is flushed.
1489 #
1490 self.pg2.unconfig_ip6()
1491 self.pg2.admin_down()
1492
1493 #
1494 # now all packets should be forwarded through the remaining peer
1495 #
1496 self.pg0.add_stream(pkts)
1497 self.pg_enable_capture(self.pg_interfaces)
1498 self.pg_start()
1499
1500 rx0 = self.pg3.get_capture(len(pkts))
1501
1502 #
1503 # enable the FIB walk process to converge the FIB
1504 #
1505 self.vapi.ppcli("test fib-walk-process enable")
1506 self.pg0.add_stream(pkts)
1507 self.pg_enable_capture(self.pg_interfaces)
1508 self.pg_start()
1509
1510 rx0 = self.pg3.get_capture(len(pkts))
1511
1512 #
1513 # put the connecteds back
1514 #
1515 self.pg2.admin_up()
1516 self.pg2.config_ip6()
1517
1518 self.pg0.add_stream(pkts)
1519 self.pg_enable_capture(self.pg_interfaces)
1520 self.pg_start()
1521
1522 rx0 = self.pg2._get_capture(1)
1523 rx1 = self.pg3._get_capture(1)
1524 self.assertNotEqual(0, len(rx0))
1525 self.assertNotEqual(0, len(rx1))
1526
1527
Neale Rannsda78f952017-05-24 09:15:43 -07001528class TestMPLSL2(VppTestCase):
1529 """ MPLS-L2 """
1530
1531 def setUp(self):
1532 super(TestMPLSL2, self).setUp()
1533
1534 # create 2 pg interfaces
1535 self.create_pg_interfaces(range(2))
1536
1537 # use pg0 as the core facing interface
1538 self.pg0.admin_up()
1539 self.pg0.config_ip4()
1540 self.pg0.resolve_arp()
1541 self.pg0.enable_mpls()
1542
1543 # use the other 2 for customer facg L2 links
1544 for i in self.pg_interfaces[1:]:
1545 i.admin_up()
1546
1547 def tearDown(self):
1548 super(TestMPLSL2, self).tearDown()
1549 for i in self.pg_interfaces[1:]:
1550 i.admin_down()
1551
1552 self.pg0.disable_mpls()
1553 self.pg0.unconfig_ip4()
1554 self.pg0.admin_down()
1555
1556 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
1557 ttl=255, top=None):
1558 if top is None:
1559 top = len(mpls_labels) - 1
1560
1561 capture = verify_filter(capture, sent)
1562
1563 self.assertEqual(len(capture), len(sent))
1564
1565 for i in range(len(capture)):
1566 tx = sent[i]
1567 rx = capture[i]
1568
1569 # the MPLS TTL is 255 since it enters a new tunnel
1570 verify_mpls_stack(self, rx, mpls_labels, ttl, top)
1571
1572 tx_eth = tx[Ether]
1573 rx_eth = Ether(str(rx[MPLS].payload))
1574
1575 self.assertEqual(rx_eth.src, tx_eth.src)
1576 self.assertEqual(rx_eth.dst, tx_eth.dst)
1577
1578 def test_vpws(self):
1579 """ Virtual Private Wire Service """
1580
1581 #
1582 # Create an MPLS tunnel that pushes 1 label
1583 #
1584 mpls_tun_1 = VppMPLSTunnelInterface(self,
1585 [VppRoutePath(self.pg0.remote_ip4,
1586 self.pg0.sw_if_index,
1587 labels=[42])],
1588 is_l2=1)
1589 mpls_tun_1.add_vpp_config()
1590 mpls_tun_1.admin_up()
1591
1592 #
1593 # Create a label entry to for 55 that does L2 input to the tunnel
1594 #
1595 route_55_eos = VppMplsRoute(
1596 self, 55, 1,
1597 [VppRoutePath("0.0.0.0",
1598 mpls_tun_1.sw_if_index,
1599 is_interface_rx=1,
1600 proto=DpoProto.DPO_PROTO_ETHERNET)])
1601 route_55_eos.add_vpp_config()
1602
1603 #
1604 # Cross-connect the tunnel with one of the customers L2 interfaces
1605 #
1606 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
1607 mpls_tun_1.sw_if_index,
1608 enable=1)
1609 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
1610 self.pg1.sw_if_index,
1611 enable=1)
1612
1613 #
1614 # inject a packet from the core
1615 #
1616 pcore = (Ether(dst=self.pg0.local_mac,
1617 src=self.pg0.remote_mac) /
1618 MPLS(label=55, ttl=64) /
1619 Ether(dst="00:00:de:ad:ba:be",
1620 src="00:00:de:ad:be:ef") /
1621 IP(src="10.10.10.10", dst="11.11.11.11") /
1622 UDP(sport=1234, dport=1234) /
1623 Raw('\xa5' * 100))
1624
1625 self.pg0.add_stream(pcore * 65)
1626 self.pg_enable_capture(self.pg_interfaces)
1627 self.pg_start()
1628
1629 rx0 = self.pg1.get_capture(65)
1630 tx = pcore[MPLS].payload
1631
1632 self.assertEqual(rx0[0][Ether].dst, tx[Ether].dst)
1633 self.assertEqual(rx0[0][Ether].src, tx[Ether].src)
1634
1635 #
1636 # Inject a packet from the custoer/L2 side
1637 #
1638 self.pg1.add_stream(tx * 65)
1639 self.pg_enable_capture(self.pg_interfaces)
1640 self.pg_start()
1641
1642 rx0 = self.pg0.get_capture(65)
1643
1644 self.verify_capture_tunneled_ethernet(rx0, tx*65, [42])
1645
1646 def test_vpls(self):
1647 """ Virtual Private LAN Service """
1648 #
1649 # Create an L2 MPLS tunnel
1650 #
1651 mpls_tun = VppMPLSTunnelInterface(self,
1652 [VppRoutePath(self.pg0.remote_ip4,
1653 self.pg0.sw_if_index,
1654 labels=[42])],
1655 is_l2=1)
1656 mpls_tun.add_vpp_config()
1657 mpls_tun.admin_up()
1658
1659 #
1660 # Create a label entry to for 55 that does L2 input to the tunnel
1661 #
1662 route_55_eos = VppMplsRoute(
1663 self, 55, 1,
1664 [VppRoutePath("0.0.0.0",
1665 mpls_tun.sw_if_index,
1666 is_interface_rx=1,
1667 proto=DpoProto.DPO_PROTO_ETHERNET)])
1668 route_55_eos.add_vpp_config()
1669
1670 #
1671 # add to tunnel to the customers bridge-domain
1672 #
1673 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1674 bd_id=1)
1675 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1676 bd_id=1)
1677
1678 #
1679 # Packet from the customer interface and from the core
1680 #
1681 p_cust = (Ether(dst="00:00:de:ad:ba:be",
1682 src="00:00:de:ad:be:ef") /
1683 IP(src="10.10.10.10", dst="11.11.11.11") /
1684 UDP(sport=1234, dport=1234) /
1685 Raw('\xa5' * 100))
1686 p_core = (Ether(src="00:00:de:ad:ba:be",
1687 dst="00:00:de:ad:be:ef") /
1688 IP(dst="10.10.10.10", src="11.11.11.11") /
1689 UDP(sport=1234, dport=1234) /
1690 Raw('\xa5' * 100))
1691
1692 #
1693 # The BD is learning, so send in one of each packet to learn
1694 #
1695 p_core_encap = (Ether(dst=self.pg0.local_mac,
1696 src=self.pg0.remote_mac) /
1697 MPLS(label=55, ttl=64) /
1698 p_core)
1699
1700 self.pg1.add_stream(p_cust)
1701 self.pg_enable_capture(self.pg_interfaces)
1702 self.pg_start()
1703 self.pg0.add_stream(p_core_encap)
1704 self.pg_enable_capture(self.pg_interfaces)
1705 self.pg_start()
1706
1707 # we've learnt this so expect it be be forwarded
1708 rx0 = self.pg1.get_capture(1)
1709
1710 self.assertEqual(rx0[0][Ether].dst, p_core[Ether].dst)
1711 self.assertEqual(rx0[0][Ether].src, p_core[Ether].src)
1712
1713 #
1714 # now a stream in each direction
1715 #
1716 self.pg1.add_stream(p_cust * 65)
1717 self.pg_enable_capture(self.pg_interfaces)
1718 self.pg_start()
1719
1720 rx0 = self.pg0.get_capture(65)
1721
1722 self.verify_capture_tunneled_ethernet(rx0, p_cust*65, [42])
1723
1724 #
1725 # remove interfaces from customers bridge-domain
1726 #
1727 self.vapi.sw_interface_set_l2_bridge(mpls_tun.sw_if_index,
1728 bd_id=1,
1729 enable=0)
1730 self.vapi.sw_interface_set_l2_bridge(self.pg1.sw_if_index,
1731 bd_id=1,
1732 enable=0)
1733
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001734if __name__ == '__main__':
1735 unittest.main(testRunner=VppTestRunner)