blob: 5b3054801e7889a9391688fea31b49fb7be492e4 [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 Rannsd5d7b962019-08-04 03:30:56 -07007from vpp_ip import DpoProto, INVALID_INDEX
Neale Ranns5a8123b2017-01-26 01:18:23 -08008from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
Neale Ranns0f26c5a2017-03-01 15:12:11 -08009 VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
Neale Rannsc0a93142018-09-05 15:42:26 -070010 MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \
Neale Ranns097fa662018-05-01 05:17:55 -070011 VppMplsLabel, MplsLspMode, find_mpls_route, \
12 FibPathProto, FibPathType, FibPathFlags, VppMplsLabel, MplsLspMode
Neale Ranns0f26c5a2017-03-01 15:12:11 -080013from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
Neale Ranns8fe8cc22016-11-01 10:05:08 +000014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns8fe8cc22016-11-01 10:05:08 +000016from scapy.packet import Raw
Klement Sekera7bb873a2016-11-18 07:38:42 +010017from scapy.layers.l2 import Ether
Neale Rannscb630ff2016-12-14 13:31:29 +010018from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns62fe07c2017-10-31 12:28:22 -070019from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
Neale Ranns8fe8cc22016-11-01 10:05:08 +000020from scapy.contrib.mpls import MPLS
21
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -040022NUM_PKTS = 67
23
Klement Sekeradab231a2016-12-21 08:50:14 +010024
Neale Rannsda78f952017-05-24 09:15:43 -070025def verify_filter(capture, sent):
26 if not len(capture) == len(sent):
27 # filter out any IPv6 RAs from the capture
28 for p in capture:
29 if p.haslayer(IPv6):
30 capture.remove(p)
31 return capture
32
33
Neale Ranns31ed7442018-02-23 05:29:09 -080034def verify_mpls_stack(tst, rx, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -070035 # the rx'd packet has the MPLS label popped
36 eth = rx[Ether]
37 tst.assertEqual(eth.type, 0x8847)
38
39 rx_mpls = rx[MPLS]
40
41 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -080042 tst.assertEqual(rx_mpls.label, mpls_labels[ii].value)
43 tst.assertEqual(rx_mpls.cos, mpls_labels[ii].exp)
44 tst.assertEqual(rx_mpls.ttl, mpls_labels[ii].ttl)
45
Neale Rannsda78f952017-05-24 09:15:43 -070046 if ii == len(mpls_labels) - 1:
47 tst.assertEqual(rx_mpls.s, 1)
48 else:
49 # not end of stack
50 tst.assertEqual(rx_mpls.s, 0)
51 # pop the label to expose the next
52 rx_mpls = rx_mpls[MPLS].payload
53
54
Neale Ranns8fe8cc22016-11-01 10:05:08 +000055class TestMPLS(VppTestCase):
56 """ MPLS Test Case """
57
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070058 @classmethod
59 def setUpClass(cls):
60 super(TestMPLS, cls).setUpClass()
61
62 @classmethod
63 def tearDownClass(cls):
64 super(TestMPLS, cls).tearDownClass()
65
Neale Ranns8fe8cc22016-11-01 10:05:08 +000066 def setUp(self):
67 super(TestMPLS, self).setUp()
68
69 # create 2 pg interfaces
Neale Ranns0f26c5a2017-03-01 15:12:11 -080070 self.create_pg_interfaces(range(4))
Neale Ranns8fe8cc22016-11-01 10:05:08 +000071
72 # setup both interfaces
73 # assign them different tables.
74 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070075 self.tables = []
76
77 tbl = VppMplsTable(self, 0)
78 tbl.add_vpp_config()
79 self.tables.append(tbl)
Neale Ranns8fe8cc22016-11-01 10:05:08 +000080
81 for i in self.pg_interfaces:
82 i.admin_up()
Neale Ranns15002542017-09-10 04:39:11 -070083
84 if table_id != 0:
85 tbl = VppIpTable(self, table_id)
86 tbl.add_vpp_config()
87 self.tables.append(tbl)
88 tbl = VppIpTable(self, table_id, is_ip6=1)
89 tbl.add_vpp_config()
90 self.tables.append(tbl)
91
Neale Ranns8fe8cc22016-11-01 10:05:08 +000092 i.set_table_ip4(table_id)
93 i.set_table_ip6(table_id)
94 i.config_ip4()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000095 i.resolve_arp()
Neale Rannsad422ed2016-11-02 14:20:04 +000096 i.config_ip6()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000097 i.resolve_ndp()
Neale Rannsad422ed2016-11-02 14:20:04 +000098 i.enable_mpls()
Neale Ranns8fe8cc22016-11-01 10:05:08 +000099 table_id += 1
100
101 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800102 for i in self.pg_interfaces:
103 i.unconfig_ip4()
104 i.unconfig_ip6()
105 i.ip6_disable()
Neale Ranns15002542017-09-10 04:39:11 -0700106 i.set_table_ip4(0)
107 i.set_table_ip6(0)
108 i.disable_mpls()
Neale Ranns4008ac92017-02-13 23:20:04 -0800109 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700110 super(TestMPLS, self).tearDown()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000111
Neale Rannsad422ed2016-11-02 14:20:04 +0000112 # the default of 64 matches the IP packet TTL default
Klement Sekeradab231a2016-12-21 08:50:14 +0100113 def create_stream_labelled_ip4(
114 self,
115 src_if,
116 mpls_labels,
Klement Sekeradab231a2016-12-21 08:50:14 +0100117 ping=0,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800118 ip_itf=None,
119 dst_ip=None,
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700120 chksum=None,
Neale Ranns31ed7442018-02-23 05:29:09 -0800121 ip_ttl=64,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800122 n=257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100123 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000124 pkts = []
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800125 for i in range(0, n):
Klement Sekeradab231a2016-12-21 08:50:14 +0100126 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000127 payload = self.info_to_payload(info)
Neale Rannsad422ed2016-11-02 14:20:04 +0000128 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
129
130 for ii in range(len(mpls_labels)):
Neale Ranns31ed7442018-02-23 05:29:09 -0800131 p = p / MPLS(label=mpls_labels[ii].value,
132 ttl=mpls_labels[ii].ttl,
133 cos=mpls_labels[ii].exp)
Neale Rannscb630ff2016-12-14 13:31:29 +0100134 if not ping:
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800135 if not dst_ip:
Neale Ranns31ed7442018-02-23 05:29:09 -0800136 p = (p / IP(src=src_if.local_ip4,
137 dst=src_if.remote_ip4,
138 ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800139 UDP(sport=1234, dport=1234) /
140 Raw(payload))
141 else:
Neale Ranns31ed7442018-02-23 05:29:09 -0800142 p = (p / IP(src=src_if.local_ip4, dst=dst_ip, ttl=ip_ttl) /
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800143 UDP(sport=1234, dport=1234) /
144 Raw(payload))
Neale Rannscb630ff2016-12-14 13:31:29 +0100145 else:
146 p = (p / IP(src=ip_itf.remote_ip4,
Neale Ranns31ed7442018-02-23 05:29:09 -0800147 dst=ip_itf.local_ip4,
148 ttl=ip_ttl) /
Neale Rannscb630ff2016-12-14 13:31:29 +0100149 ICMP())
150
Neale Ranns4c7c8e52017-10-21 09:37:55 -0700151 if chksum:
152 p[IP].chksum = chksum
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000153 info.data = p.copy()
154 pkts.append(p)
155 return pkts
156
Neale Ranns31ed7442018-02-23 05:29:09 -0800157 def create_stream_ip4(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
Klement Sekeradab231a2016-12-21 08:50:14 +0100158 self.reset_packet_infos()
Neale Rannsad422ed2016-11-02 14:20:04 +0000159 pkts = []
160 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100161 info = self.create_packet_info(src_if, src_if)
Neale Rannsad422ed2016-11-02 14:20:04 +0000162 payload = self.info_to_payload(info)
163 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Ranns31ed7442018-02-23 05:29:09 -0800164 IP(src=src_if.remote_ip4, dst=dst_ip,
165 ttl=ip_ttl, tos=ip_dscp) /
Neale Rannsad422ed2016-11-02 14:20:04 +0000166 UDP(sport=1234, dport=1234) /
167 Raw(payload))
168 info.data = p.copy()
169 pkts.append(p)
170 return pkts
171
Neale Ranns31ed7442018-02-23 05:29:09 -0800172 def create_stream_ip6(self, src_if, dst_ip, ip_ttl=64, ip_dscp=0):
173 self.reset_packet_infos()
174 pkts = []
175 for i in range(0, 257):
176 info = self.create_packet_info(src_if, src_if)
177 payload = self.info_to_payload(info)
178 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
179 IPv6(src=src_if.remote_ip6, dst=dst_ip,
180 hlim=ip_ttl, tc=ip_dscp) /
181 UDP(sport=1234, dport=1234) /
182 Raw(payload))
183 info.data = p.copy()
184 pkts.append(p)
185 return pkts
186
187 def create_stream_labelled_ip6(self, src_if, mpls_labels,
188 hlim=64, dst_ip=None):
Neale Ranns31426c62017-05-24 10:32:58 -0700189 if dst_ip is None:
190 dst_ip = src_if.remote_ip6
Klement Sekeradab231a2016-12-21 08:50:14 +0100191 self.reset_packet_infos()
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000192 pkts = []
193 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100194 info = self.create_packet_info(src_if, src_if)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000195 payload = self.info_to_payload(info)
Neale Ranns31ed7442018-02-23 05:29:09 -0800196 p = Ether(dst=src_if.local_mac, src=src_if.remote_mac)
197 for l in mpls_labels:
198 p = p / MPLS(label=l.value, ttl=l.ttl, cos=l.exp)
199
200 p = p / (IPv6(src=src_if.remote_ip6, dst=dst_ip, hlim=hlim) /
201 UDP(sport=1234, dport=1234) /
202 Raw(payload))
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000203 info.data = p.copy()
204 pkts.append(p)
205 return pkts
206
Neale Ranns31ed7442018-02-23 05:29:09 -0800207 def verify_capture_ip4(self, src_if, capture, sent, ping_resp=0,
208 ip_ttl=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000209 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700210 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000211
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000212 self.assertEqual(len(capture), len(sent))
213
214 for i in range(len(capture)):
215 tx = sent[i]
216 rx = capture[i]
217
218 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000219 eth = rx[Ether]
220 self.assertEqual(eth.type, 0x800)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000221
222 tx_ip = tx[IP]
223 rx_ip = rx[IP]
224
Neale Rannscb630ff2016-12-14 13:31:29 +0100225 if not ping_resp:
226 self.assertEqual(rx_ip.src, tx_ip.src)
227 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800228 self.assertEqual(rx_ip.tos, ip_dscp)
229 if not ip_ttl:
230 # IP processing post pop has decremented the TTL
231 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
232 else:
233 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannscb630ff2016-12-14 13:31:29 +0100234 else:
235 self.assertEqual(rx_ip.src, tx_ip.dst)
236 self.assertEqual(rx_ip.dst, tx_ip.src)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000237
238 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000239 raise
240
Neale Rannsad422ed2016-11-02 14:20:04 +0000241 def verify_capture_labelled_ip4(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800242 mpls_labels, ip_ttl=None):
Neale Rannsad422ed2016-11-02 14:20:04 +0000243 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700244 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000245
246 self.assertEqual(len(capture), len(sent))
247
248 for i in range(len(capture)):
249 tx = sent[i]
250 rx = capture[i]
251 tx_ip = tx[IP]
252 rx_ip = rx[IP]
253
Neale Ranns31ed7442018-02-23 05:29:09 -0800254 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000255
256 self.assertEqual(rx_ip.src, tx_ip.src)
257 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800258 if not ip_ttl:
259 # IP processing post pop has decremented the TTL
260 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
261 else:
262 self.assertEqual(rx_ip.ttl, ip_ttl)
Neale Rannsad422ed2016-11-02 14:20:04 +0000263
264 except:
265 raise
266
Neale Ranns31ed7442018-02-23 05:29:09 -0800267 def verify_capture_labelled_ip6(self, src_if, capture, sent,
268 mpls_labels, ip_ttl=None):
269 try:
270 capture = verify_filter(capture, sent)
271
272 self.assertEqual(len(capture), len(sent))
273
274 for i in range(len(capture)):
275 tx = sent[i]
276 rx = capture[i]
277 tx_ip = tx[IPv6]
278 rx_ip = rx[IPv6]
279
280 verify_mpls_stack(self, rx, mpls_labels)
281
282 self.assertEqual(rx_ip.src, tx_ip.src)
283 self.assertEqual(rx_ip.dst, tx_ip.dst)
284 if not ip_ttl:
285 # IP processing post pop has decremented the TTL
286 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
287 else:
288 self.assertEqual(rx_ip.hlim, ip_ttl)
289
290 except:
291 raise
292
293 def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700295 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000296
297 self.assertEqual(len(capture), len(sent))
298
299 for i in range(len(capture)):
300 tx = sent[i]
301 rx = capture[i]
302 tx_ip = tx[IP]
303 rx_ip = rx[IP]
304
Neale Ranns31ed7442018-02-23 05:29:09 -0800305 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000306
307 self.assertEqual(rx_ip.src, tx_ip.src)
308 self.assertEqual(rx_ip.dst, tx_ip.dst)
309 # IP processing post pop has decremented the TTL
310 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
311
312 except:
313 raise
314
315 def verify_capture_labelled(self, src_if, capture, sent,
Neale Ranns31ed7442018-02-23 05:29:09 -0800316 mpls_labels):
Neale Rannsad422ed2016-11-02 14:20:04 +0000317 try:
Neale Rannsda78f952017-05-24 09:15:43 -0700318 capture = verify_filter(capture, sent)
Neale Rannsad422ed2016-11-02 14:20:04 +0000319
320 self.assertEqual(len(capture), len(sent))
321
322 for i in range(len(capture)):
323 rx = capture[i]
Neale Ranns31ed7442018-02-23 05:29:09 -0800324 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsad422ed2016-11-02 14:20:04 +0000325 except:
326 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000327
Neale Ranns31ed7442018-02-23 05:29:09 -0800328 def verify_capture_ip6(self, src_if, capture, sent,
329 ip_hlim=None, ip_dscp=0):
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000330 try:
331 self.assertEqual(len(capture), len(sent))
332
333 for i in range(len(capture)):
334 tx = sent[i]
335 rx = capture[i]
336
337 # the rx'd packet has the MPLS label popped
Neale Rannsad422ed2016-11-02 14:20:04 +0000338 eth = rx[Ether]
339 self.assertEqual(eth.type, 0x86DD)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000340
341 tx_ip = tx[IPv6]
342 rx_ip = rx[IPv6]
343
344 self.assertEqual(rx_ip.src, tx_ip.src)
345 self.assertEqual(rx_ip.dst, tx_ip.dst)
Neale Ranns31ed7442018-02-23 05:29:09 -0800346 self.assertEqual(rx_ip.tc, ip_dscp)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000347 # IP processing post pop has decremented the TTL
Neale Ranns31ed7442018-02-23 05:29:09 -0800348 if not ip_hlim:
349 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
350 else:
351 self.assertEqual(rx_ip.hlim, ip_hlim)
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000352
353 except:
Neale Rannsad422ed2016-11-02 14:20:04 +0000354 raise
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000355
Neale Ranns62fe07c2017-10-31 12:28:22 -0700356 def verify_capture_ip6_icmp(self, src_if, capture, sent):
357 try:
358 self.assertEqual(len(capture), len(sent))
359
360 for i in range(len(capture)):
361 tx = sent[i]
362 rx = capture[i]
363
364 # the rx'd packet has the MPLS label popped
365 eth = rx[Ether]
366 self.assertEqual(eth.type, 0x86DD)
367
368 tx_ip = tx[IPv6]
369 rx_ip = rx[IPv6]
370
371 self.assertEqual(rx_ip.dst, tx_ip.src)
372 # ICMP sourced from the interface's address
373 self.assertEqual(rx_ip.src, src_if.local_ip6)
374 # hop-limit reset to 255 for IMCP packet
Ole Troan282093f2018-09-19 12:38:51 +0200375 self.assertEqual(rx_ip.hlim, 255)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700376
377 icmp = rx[ICMPv6TimeExceeded]
378
379 except:
380 raise
381
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530382 def verify_capture_fragmented_labelled_ip4(self, src_if, capture, sent,
383 mpls_labels, ip_ttl=None):
384 try:
385 capture = verify_filter(capture, sent)
386
387 for i in range(len(capture)):
388 tx = sent[0]
389 rx = capture[i]
390 tx_ip = tx[IP]
391 rx_ip = rx[IP]
392
393 verify_mpls_stack(self, rx, mpls_labels)
394
395 self.assertEqual(rx_ip.src, tx_ip.src)
396 self.assertEqual(rx_ip.dst, tx_ip.dst)
397 if not ip_ttl:
398 # IP processing post pop has decremented the TTL
399 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
400 else:
401 self.assertEqual(rx_ip.ttl, ip_ttl)
402
403 except:
404 raise
405
Neale Rannsad422ed2016-11-02 14:20:04 +0000406 def test_swap(self):
407 """ MPLS label swap tests """
408
409 #
410 # A simple MPLS xconnect - eos label in label out
411 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800412 route_32_eos = VppMplsRoute(self, 32, 1,
413 [VppRoutePath(self.pg0.remote_ip4,
414 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800415 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000416 route_32_eos.add_vpp_config()
417
Neale Ranns775f73c2018-12-20 03:01:49 -0800418 self.assertTrue(
419 find_mpls_route(self, 0, 32, 1,
420 [VppRoutePath(self.pg0.remote_ip4,
421 self.pg0.sw_if_index,
422 labels=[VppMplsLabel(33)])]))
423
Neale Rannsad422ed2016-11-02 14:20:04 +0000424 #
425 # a stream that matches the route for 10.0.0.1
426 # PG0 is in the default table
427 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800428 tx = self.create_stream_labelled_ip4(self.pg0,
429 [VppMplsLabel(32, ttl=32, exp=1)])
430 rx = self.send_and_expect(self.pg0, tx, self.pg0)
431 self.verify_capture_labelled(self.pg0, rx, tx,
432 [VppMplsLabel(33, ttl=31, exp=1)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000433
Neale Ranns008dbe12018-09-07 09:32:36 -0700434 self.assertEqual(route_32_eos.get_stats_to()['packets'], 257)
435
Neale Rannsad422ed2016-11-02 14:20:04 +0000436 #
437 # A simple MPLS xconnect - non-eos label in label out
438 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800439 route_32_neos = VppMplsRoute(self, 32, 0,
440 [VppRoutePath(self.pg0.remote_ip4,
441 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800442 labels=[VppMplsLabel(33)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000443 route_32_neos.add_vpp_config()
444
445 #
446 # a stream that matches the route for 10.0.0.1
447 # PG0 is in the default table
448 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800449 tx = self.create_stream_labelled_ip4(self.pg0,
450 [VppMplsLabel(32, ttl=21, exp=7),
451 VppMplsLabel(99)])
452 rx = self.send_and_expect(self.pg0, tx, self.pg0)
453 self.verify_capture_labelled(self.pg0, rx, tx,
454 [VppMplsLabel(33, ttl=20, exp=7),
455 VppMplsLabel(99)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700456 self.assertEqual(route_32_neos.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000457
Neale Ranns31ed7442018-02-23 05:29:09 -0800458 #
459 # A simple MPLS xconnect - non-eos label in label out, uniform mode
460 #
461 route_42_neos = VppMplsRoute(
462 self, 42, 0,
463 [VppRoutePath(self.pg0.remote_ip4,
464 self.pg0.sw_if_index,
465 labels=[VppMplsLabel(43, MplsLspMode.UNIFORM)])])
466 route_42_neos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000467
Neale Ranns31ed7442018-02-23 05:29:09 -0800468 tx = self.create_stream_labelled_ip4(self.pg0,
469 [VppMplsLabel(42, ttl=21, exp=7),
470 VppMplsLabel(99)])
471 rx = self.send_and_expect(self.pg0, tx, self.pg0)
472 self.verify_capture_labelled(self.pg0, rx, tx,
473 [VppMplsLabel(43, ttl=20, exp=7),
474 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000475
476 #
477 # An MPLS xconnect - EOS label in IP out
478 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800479 route_33_eos = VppMplsRoute(self, 33, 1,
480 [VppRoutePath(self.pg0.remote_ip4,
481 self.pg0.sw_if_index,
482 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000483 route_33_eos.add_vpp_config()
484
Neale Ranns31ed7442018-02-23 05:29:09 -0800485 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)])
486 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannsad422ed2016-11-02 14:20:04 +0000487 self.verify_capture_ip4(self.pg0, rx, tx)
488
489 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700490 # disposed packets have an invalid IPv4 checksum
Neale Ranns62fe07c2017-10-31 12:28:22 -0700491 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800492 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(33)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700493 dst_ip=self.pg0.remote_ip4,
494 n=65,
495 chksum=1)
496 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
497
498 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800499 # An MPLS xconnect - EOS label in IP out, uniform mode
500 #
501 route_3333_eos = VppMplsRoute(
502 self, 3333, 1,
503 [VppRoutePath(self.pg0.remote_ip4,
504 self.pg0.sw_if_index,
505 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])])
506 route_3333_eos.add_vpp_config()
507
508 tx = self.create_stream_labelled_ip4(
509 self.pg0,
510 [VppMplsLabel(3333, ttl=55, exp=3)])
511 rx = self.send_and_expect(self.pg0, tx, self.pg0)
512 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=54, ip_dscp=0x60)
513 tx = self.create_stream_labelled_ip4(
514 self.pg0,
515 [VppMplsLabel(3333, ttl=66, exp=4)])
516 rx = self.send_and_expect(self.pg0, tx, self.pg0)
517 self.verify_capture_ip4(self.pg0, rx, tx, ip_ttl=65, ip_dscp=0x80)
518
519 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700520 # An MPLS xconnect - EOS label in IPv6 out
521 #
522 route_333_eos = VppMplsRoute(
523 self, 333, 1,
524 [VppRoutePath(self.pg0.remote_ip6,
525 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700526 labels=[])],
527 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700528 route_333_eos.add_vpp_config()
529
Neale Ranns31ed7442018-02-23 05:29:09 -0800530 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(333)])
531 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700532 self.verify_capture_ip6(self.pg0, rx, tx)
533
534 #
535 # disposed packets have an TTL expired
536 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800537 tx = self.create_stream_labelled_ip6(self.pg0,
538 [VppMplsLabel(333, ttl=64)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700539 dst_ip=self.pg1.remote_ip6,
540 hlim=1)
Neale Ranns31ed7442018-02-23 05:29:09 -0800541 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700542 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
543
544 #
545 # An MPLS xconnect - EOS label in IPv6 out w imp-null
546 #
547 route_334_eos = VppMplsRoute(
548 self, 334, 1,
549 [VppRoutePath(self.pg0.remote_ip6,
550 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700551 labels=[VppMplsLabel(3)])],
552 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700553 route_334_eos.add_vpp_config()
554
Neale Ranns31ed7442018-02-23 05:29:09 -0800555 tx = self.create_stream_labelled_ip6(self.pg0,
556 [VppMplsLabel(334, ttl=64)])
557 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700558 self.verify_capture_ip6(self.pg0, rx, tx)
559
560 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800561 # An MPLS xconnect - EOS label in IPv6 out w imp-null in uniform mode
562 #
563 route_335_eos = VppMplsRoute(
564 self, 335, 1,
565 [VppRoutePath(self.pg0.remote_ip6,
566 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700567 labels=[VppMplsLabel(3, MplsLspMode.UNIFORM)])],
568 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31ed7442018-02-23 05:29:09 -0800569 route_335_eos.add_vpp_config()
570
571 tx = self.create_stream_labelled_ip6(
572 self.pg0,
573 [VppMplsLabel(335, ttl=27, exp=4)])
574 rx = self.send_and_expect(self.pg0, tx, self.pg0)
575 self.verify_capture_ip6(self.pg0, rx, tx, ip_hlim=26, ip_dscp=0x80)
576
577 #
Neale Ranns62fe07c2017-10-31 12:28:22 -0700578 # disposed packets have an TTL expired
579 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800580 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(334)],
Neale Ranns62fe07c2017-10-31 12:28:22 -0700581 dst_ip=self.pg1.remote_ip6,
582 hlim=0)
Neale Ranns31ed7442018-02-23 05:29:09 -0800583 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns62fe07c2017-10-31 12:28:22 -0700584 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
585
586 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000587 # An MPLS xconnect - non-EOS label in IP out - an invalid configuration
588 # so this traffic should be dropped.
589 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800590 route_33_neos = VppMplsRoute(self, 33, 0,
591 [VppRoutePath(self.pg0.remote_ip4,
592 self.pg0.sw_if_index,
593 labels=[])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000594 route_33_neos.add_vpp_config()
595
Neale Ranns31ed7442018-02-23 05:29:09 -0800596 tx = self.create_stream_labelled_ip4(self.pg0,
597 [VppMplsLabel(33),
598 VppMplsLabel(99)])
599 self.send_and_assert_no_replies(
600 self.pg0, tx,
601 "MPLS non-EOS packets popped and forwarded")
Neale Rannsad422ed2016-11-02 14:20:04 +0000602
603 #
604 # A recursive EOS x-connect, which resolves through another x-connect
Neale Ranns31ed7442018-02-23 05:29:09 -0800605 # in pipe mode
Neale Rannsad422ed2016-11-02 14:20:04 +0000606 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800607 route_34_eos = VppMplsRoute(self, 34, 1,
608 [VppRoutePath("0.0.0.0",
609 0xffffffff,
610 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800611 labels=[VppMplsLabel(44),
612 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000613 route_34_eos.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700614 self.logger.info(self.vapi.cli("sh mpls fib 34"))
Neale Rannsad422ed2016-11-02 14:20:04 +0000615
Neale Ranns31ed7442018-02-23 05:29:09 -0800616 tx = self.create_stream_labelled_ip4(self.pg0,
617 [VppMplsLabel(34, ttl=3)])
618 rx = self.send_and_expect(self.pg0, tx, self.pg0)
619 self.verify_capture_labelled(self.pg0, rx, tx,
620 [VppMplsLabel(33),
621 VppMplsLabel(44),
622 VppMplsLabel(45, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000623
Neale Ranns008dbe12018-09-07 09:32:36 -0700624 self.assertEqual(route_34_eos.get_stats_to()['packets'], 257)
625 self.assertEqual(route_32_neos.get_stats_via()['packets'], 257)
626
Neale Ranns31ed7442018-02-23 05:29:09 -0800627 #
628 # A recursive EOS x-connect, which resolves through another x-connect
629 # in uniform mode
630 #
631 route_35_eos = VppMplsRoute(
632 self, 35, 1,
633 [VppRoutePath("0.0.0.0",
634 0xffffffff,
635 nh_via_label=42,
636 labels=[VppMplsLabel(44)])])
637 route_35_eos.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000638
Neale Ranns31ed7442018-02-23 05:29:09 -0800639 tx = self.create_stream_labelled_ip4(self.pg0,
640 [VppMplsLabel(35, ttl=3)])
641 rx = self.send_and_expect(self.pg0, tx, self.pg0)
642 self.verify_capture_labelled(self.pg0, rx, tx,
643 [VppMplsLabel(43, ttl=2),
644 VppMplsLabel(44, ttl=2)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000645
646 #
Matej Klottondeb69842016-12-09 15:05:46 +0100647 # A recursive non-EOS x-connect, which resolves through another
648 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000649 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800650 route_34_neos = VppMplsRoute(self, 34, 0,
651 [VppRoutePath("0.0.0.0",
652 0xffffffff,
653 nh_via_label=32,
Neale Ranns31ed7442018-02-23 05:29:09 -0800654 labels=[VppMplsLabel(44),
655 VppMplsLabel(46)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000656 route_34_neos.add_vpp_config()
657
Neale Ranns31ed7442018-02-23 05:29:09 -0800658 tx = self.create_stream_labelled_ip4(self.pg0,
659 [VppMplsLabel(34, ttl=45),
660 VppMplsLabel(99)])
661 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Matej Klottondeb69842016-12-09 15:05:46 +0100662 # it's the 2nd (counting from 0) label in the stack that is swapped
Neale Ranns31ed7442018-02-23 05:29:09 -0800663 self.verify_capture_labelled(self.pg0, rx, tx,
664 [VppMplsLabel(33),
665 VppMplsLabel(44),
666 VppMplsLabel(46, ttl=44),
667 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000668
669 #
Matej Klottondeb69842016-12-09 15:05:46 +0100670 # an recursive IP route that resolves through the recursive non-eos
671 # x-connect
Neale Rannsad422ed2016-11-02 14:20:04 +0000672 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800673 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
674 [VppRoutePath("0.0.0.0",
675 0xffffffff,
676 nh_via_label=34,
Neale Ranns31ed7442018-02-23 05:29:09 -0800677 labels=[VppMplsLabel(55)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000678 ip_10_0_0_1.add_vpp_config()
679
Neale Rannsad422ed2016-11-02 14:20:04 +0000680 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800681 rx = self.send_and_expect(self.pg0, tx, self.pg0)
682 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
683 [VppMplsLabel(33),
684 VppMplsLabel(44),
685 VppMplsLabel(46),
686 VppMplsLabel(55)])
Neale Ranns008dbe12018-09-07 09:32:36 -0700687 self.assertEqual(ip_10_0_0_1.get_stats_to()['packets'], 257)
Neale Rannsad422ed2016-11-02 14:20:04 +0000688
689 ip_10_0_0_1.remove_vpp_config()
690 route_34_neos.remove_vpp_config()
691 route_34_eos.remove_vpp_config()
692 route_33_neos.remove_vpp_config()
693 route_33_eos.remove_vpp_config()
694 route_32_neos.remove_vpp_config()
695 route_32_eos.remove_vpp_config()
696
697 def test_bind(self):
698 """ MPLS Local Label Binding test """
699
700 #
701 # Add a non-recursive route with a single out label
702 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800703 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
704 [VppRoutePath(self.pg0.remote_ip4,
705 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800706 labels=[VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000707 route_10_0_0_1.add_vpp_config()
708
709 # bind a local label to the route
Neale Ranns5a8123b2017-01-26 01:18:23 -0800710 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
Neale Rannsad422ed2016-11-02 14:20:04 +0000711 binding.add_vpp_config()
712
713 # non-EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800714 tx = self.create_stream_labelled_ip4(self.pg0,
715 [VppMplsLabel(44),
716 VppMplsLabel(99)])
717 rx = self.send_and_expect(self.pg0, tx, self.pg0)
718 self.verify_capture_labelled(self.pg0, rx, tx,
719 [VppMplsLabel(45, ttl=63),
720 VppMplsLabel(99)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000721
722 # EOS stream
Neale Ranns31ed7442018-02-23 05:29:09 -0800723 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(44)])
724 rx = self.send_and_expect(self.pg0, tx, self.pg0)
725 self.verify_capture_labelled(self.pg0, rx, tx,
726 [VppMplsLabel(45, ttl=63)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000727
728 # IP stream
Neale Rannsad422ed2016-11-02 14:20:04 +0000729 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800730 rx = self.send_and_expect(self.pg0, tx, self.pg0)
731 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000732
733 #
734 # cleanup
735 #
736 binding.remove_vpp_config()
737 route_10_0_0_1.remove_vpp_config()
738
739 def test_imposition(self):
740 """ MPLS label imposition test """
741
742 #
743 # Add a non-recursive route with a single out label
744 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800745 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
746 [VppRoutePath(self.pg0.remote_ip4,
747 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800748 labels=[VppMplsLabel(32)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000749 route_10_0_0_1.add_vpp_config()
750
751 #
752 # a stream that matches the route for 10.0.0.1
753 # PG0 is in the default table
754 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000755 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800756 rx = self.send_and_expect(self.pg0, tx, self.pg0)
757 self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000758
759 #
760 # Add a non-recursive route with a 3 out labels
761 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800762 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
763 [VppRoutePath(self.pg0.remote_ip4,
764 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800765 labels=[VppMplsLabel(32),
766 VppMplsLabel(33),
767 VppMplsLabel(34)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000768 route_10_0_0_2.add_vpp_config()
769
Neale Ranns31ed7442018-02-23 05:29:09 -0800770 tx = self.create_stream_ip4(self.pg0, "10.0.0.2",
771 ip_ttl=44, ip_dscp=0xff)
772 rx = self.send_and_expect(self.pg0, tx, self.pg0)
773 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
774 [VppMplsLabel(32),
775 VppMplsLabel(33),
776 VppMplsLabel(34)],
777 ip_ttl=43)
Neale Rannsad422ed2016-11-02 14:20:04 +0000778
Neale Ranns31ed7442018-02-23 05:29:09 -0800779 #
780 # Add a non-recursive route with a single out label in uniform mode
781 #
782 route_10_0_0_3 = VppIpRoute(
783 self, "10.0.0.3", 32,
784 [VppRoutePath(self.pg0.remote_ip4,
785 self.pg0.sw_if_index,
786 labels=[VppMplsLabel(32,
787 mode=MplsLspMode.UNIFORM)])])
788 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000789
Neale Ranns31ed7442018-02-23 05:29:09 -0800790 tx = self.create_stream_ip4(self.pg0, "10.0.0.3",
791 ip_ttl=54, ip_dscp=0xbe)
792 rx = self.send_and_expect(self.pg0, tx, self.pg0)
793 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
794 [VppMplsLabel(32, ttl=53, exp=5)])
795
796 #
797 # Add a IPv6 non-recursive route with a single out label in
798 # uniform mode
799 #
800 route_2001_3 = VppIpRoute(
801 self, "2001::3", 128,
802 [VppRoutePath(self.pg0.remote_ip6,
803 self.pg0.sw_if_index,
Neale Ranns31ed7442018-02-23 05:29:09 -0800804 labels=[VppMplsLabel(32,
Neale Ranns097fa662018-05-01 05:17:55 -0700805 mode=MplsLspMode.UNIFORM)])])
Neale Ranns31ed7442018-02-23 05:29:09 -0800806 route_2001_3.add_vpp_config()
807
808 tx = self.create_stream_ip6(self.pg0, "2001::3",
809 ip_ttl=54, ip_dscp=0xbe)
810 rx = self.send_and_expect(self.pg0, tx, self.pg0)
811 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
812 [VppMplsLabel(32, ttl=53, exp=5)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000813
814 #
Matej Klottondeb69842016-12-09 15:05:46 +0100815 # add a recursive path, with output label, via the 1 label route
Neale Rannsad422ed2016-11-02 14:20:04 +0000816 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800817 route_11_0_0_1 = VppIpRoute(self, "11.0.0.1", 32,
818 [VppRoutePath("10.0.0.1",
819 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800820 labels=[VppMplsLabel(44)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000821 route_11_0_0_1.add_vpp_config()
822
823 #
824 # a stream that matches the route for 11.0.0.1, should pick up
825 # the label stack for 11.0.0.1 and 10.0.0.1
826 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000827 tx = self.create_stream_ip4(self.pg0, "11.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -0800828 rx = self.send_and_expect(self.pg0, tx, self.pg0)
829 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
830 [VppMplsLabel(32),
831 VppMplsLabel(44)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000832
Neale Ranns008dbe12018-09-07 09:32:36 -0700833 self.assertEqual(route_11_0_0_1.get_stats_to()['packets'], 257)
834
Neale Rannsad422ed2016-11-02 14:20:04 +0000835 #
836 # add a recursive path, with 2 labels, via the 3 label route
837 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800838 route_11_0_0_2 = VppIpRoute(self, "11.0.0.2", 32,
839 [VppRoutePath("10.0.0.2",
840 0xffffffff,
Neale Ranns31ed7442018-02-23 05:29:09 -0800841 labels=[VppMplsLabel(44),
842 VppMplsLabel(45)])])
Neale Rannsad422ed2016-11-02 14:20:04 +0000843 route_11_0_0_2.add_vpp_config()
844
845 #
846 # a stream that matches the route for 11.0.0.1, should pick up
847 # the label stack for 11.0.0.1 and 10.0.0.1
848 #
Neale Rannsad422ed2016-11-02 14:20:04 +0000849 tx = self.create_stream_ip4(self.pg0, "11.0.0.2")
Neale Ranns31ed7442018-02-23 05:29:09 -0800850 rx = self.send_and_expect(self.pg0, tx, self.pg0)
851 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
852 [VppMplsLabel(32),
853 VppMplsLabel(33),
854 VppMplsLabel(34),
855 VppMplsLabel(44),
856 VppMplsLabel(45)])
Neale Rannsad422ed2016-11-02 14:20:04 +0000857
Neale Ranns008dbe12018-09-07 09:32:36 -0700858 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 257)
859
860 rx = self.send_and_expect(self.pg0, tx, self.pg0)
861 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
862 [VppMplsLabel(32),
863 VppMplsLabel(33),
864 VppMplsLabel(34),
865 VppMplsLabel(44),
866 VppMplsLabel(45)])
867
868 self.assertEqual(route_11_0_0_2.get_stats_to()['packets'], 514)
869
Neale Rannsad422ed2016-11-02 14:20:04 +0000870 #
871 # cleanup
872 #
873 route_11_0_0_2.remove_vpp_config()
874 route_11_0_0_1.remove_vpp_config()
875 route_10_0_0_2.remove_vpp_config()
876 route_10_0_0_1.remove_vpp_config()
877
Rajesh Goeld6f1c9c2019-10-06 13:17:36 +0530878 def test_imposition_fragmentation(self):
879 """ MPLS label imposition fragmentation test """
880
881 #
882 # Add a ipv4 non-recursive route with a single out label
883 #
884 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
885 [VppRoutePath(self.pg0.remote_ip4,
886 self.pg0.sw_if_index,
887 labels=[VppMplsLabel(32)])])
888 route_10_0_0_1.add_vpp_config()
889
890 #
891 # a stream that matches the route for 10.0.0.1
892 # PG0 is in the default table
893 #
894 tx = self.create_stream_ip4(self.pg0, "10.0.0.1")
895 for i in range(0, 257):
896 self.extend_packet(tx[i], 10000)
897
898 #
899 # 5 fragments per packet (257*5=1285)
900 #
901 rx = self.send_and_expect(self.pg0, tx, self.pg0, 1285)
902 self.verify_capture_fragmented_labelled_ip4(self.pg0, rx, tx,
903 [VppMplsLabel(32)])
904
905 #
906 # cleanup
907 #
908 route_10_0_0_1.remove_vpp_config()
909
Neale Ranns31ed7442018-02-23 05:29:09 -0800910 def test_tunnel_pipe(self):
911 """ MPLS Tunnel Tests - Pipe """
Neale Rannsad422ed2016-11-02 14:20:04 +0000912
913 #
914 # Create a tunnel with a single out label
915 #
Neale Ranns31ed7442018-02-23 05:29:09 -0800916 mpls_tun = VppMPLSTunnelInterface(
917 self,
918 [VppRoutePath(self.pg0.remote_ip4,
919 self.pg0.sw_if_index,
920 labels=[VppMplsLabel(44),
921 VppMplsLabel(46)])])
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800922 mpls_tun.add_vpp_config()
923 mpls_tun.admin_up()
Neale Rannsad422ed2016-11-02 14:20:04 +0000924
925 #
926 # add an unlabelled route through the new tunnel
927 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800928 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
929 [VppRoutePath("0.0.0.0",
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800930 mpls_tun._sw_if_index)])
Neale Ranns5a8123b2017-01-26 01:18:23 -0800931 route_10_0_0_3.add_vpp_config()
Neale Rannsad422ed2016-11-02 14:20:04 +0000932
933 self.vapi.cli("clear trace")
934 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
935 self.pg0.add_stream(tx)
936
937 self.pg_enable_capture(self.pg_interfaces)
938 self.pg_start()
939
940 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800941 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
942 [VppMplsLabel(44),
943 VppMplsLabel(46)])
Neale Ranns8fe8cc22016-11-01 10:05:08 +0000944
Neale Ranns8c4611b2017-05-23 03:43:47 -0700945 #
946 # add a labelled route through the new tunnel
947 #
948 route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
949 [VppRoutePath("0.0.0.0",
950 mpls_tun._sw_if_index,
951 labels=[33])])
952 route_10_0_0_4.add_vpp_config()
953
954 self.vapi.cli("clear trace")
955 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
956 self.pg0.add_stream(tx)
957
958 self.pg_enable_capture(self.pg_interfaces)
959 self.pg_start()
960
961 rx = self.pg0.get_capture()
Neale Ranns31ed7442018-02-23 05:29:09 -0800962 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
963 [VppMplsLabel(44),
964 VppMplsLabel(46),
965 VppMplsLabel(33, ttl=255)])
966
967 def test_tunnel_uniform(self):
968 """ MPLS Tunnel Tests - Uniform """
969
970 #
971 # Create a tunnel with a single out label
972 # The label stack is specified here from outer to inner
973 #
974 mpls_tun = VppMPLSTunnelInterface(
975 self,
976 [VppRoutePath(self.pg0.remote_ip4,
977 self.pg0.sw_if_index,
978 labels=[VppMplsLabel(44, ttl=32),
979 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
980 mpls_tun.add_vpp_config()
981 mpls_tun.admin_up()
982
983 #
984 # add an unlabelled route through the new tunnel
985 #
986 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
987 [VppRoutePath("0.0.0.0",
988 mpls_tun._sw_if_index)])
989 route_10_0_0_3.add_vpp_config()
990
991 self.vapi.cli("clear trace")
992 tx = self.create_stream_ip4(self.pg0, "10.0.0.3", ip_ttl=24)
993 self.pg0.add_stream(tx)
994
995 self.pg_enable_capture(self.pg_interfaces)
996 self.pg_start()
997
998 rx = self.pg0.get_capture()
999 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1000 [VppMplsLabel(44, ttl=32),
1001 VppMplsLabel(46, ttl=23)])
1002
1003 #
1004 # add a labelled route through the new tunnel
1005 #
1006 route_10_0_0_4 = VppIpRoute(
1007 self, "10.0.0.4", 32,
1008 [VppRoutePath("0.0.0.0",
1009 mpls_tun._sw_if_index,
1010 labels=[VppMplsLabel(33, ttl=47)])])
1011 route_10_0_0_4.add_vpp_config()
1012
1013 self.vapi.cli("clear trace")
1014 tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
1015 self.pg0.add_stream(tx)
1016
1017 self.pg_enable_capture(self.pg_interfaces)
1018 self.pg_start()
1019
1020 rx = self.pg0.get_capture()
1021 self.verify_capture_tunneled_ip4(self.pg0, rx, tx,
1022 [VppMplsLabel(44, ttl=32),
1023 VppMplsLabel(46, ttl=47),
1024 VppMplsLabel(33, ttl=47)])
Neale Ranns8c4611b2017-05-23 03:43:47 -07001025
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001026 def test_mpls_tunnel_many(self):
Neale Ranns097fa662018-05-01 05:17:55 -07001027 """ MPLS Multiple Tunnels """
Neale Rannsf5fa5ae2018-09-26 05:07:25 -07001028
1029 for ii in range(10):
1030 mpls_tun = VppMPLSTunnelInterface(
1031 self,
1032 [VppRoutePath(self.pg0.remote_ip4,
1033 self.pg0.sw_if_index,
1034 labels=[VppMplsLabel(44, ttl=32),
1035 VppMplsLabel(46, MplsLspMode.UNIFORM)])])
1036 mpls_tun.add_vpp_config()
1037 mpls_tun.admin_up()
1038
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001039 def test_v4_exp_null(self):
1040 """ MPLS V4 Explicit NULL test """
1041
1042 #
1043 # The first test case has an MPLS TTL of 0
1044 # all packet should be dropped
1045 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001046 tx = self.create_stream_labelled_ip4(self.pg0,
1047 [VppMplsLabel(0, ttl=0)])
1048 self.send_and_assert_no_replies(self.pg0, tx,
1049 "MPLS TTL=0 packets forwarded")
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001050
1051 #
1052 # a stream with a non-zero MPLS TTL
1053 # PG0 is in the default table
1054 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001055 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(0)])
1056 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001057 self.verify_capture_ip4(self.pg0, rx, tx)
1058
1059 #
1060 # a stream with a non-zero MPLS TTL
1061 # PG1 is in table 1
1062 # we are ensuring the post-pop lookup occurs in the VRF table
1063 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001064 tx = self.create_stream_labelled_ip4(self.pg1, [VppMplsLabel(0)])
1065 rx = self.send_and_expect(self.pg1, tx, self.pg1)
1066 self.verify_capture_ip4(self.pg1, rx, tx)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001067
1068 def test_v6_exp_null(self):
1069 """ MPLS V6 Explicit NULL test """
1070
1071 #
1072 # a stream with a non-zero MPLS TTL
1073 # PG0 is in the default table
1074 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001075 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(2)])
1076 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001077 self.verify_capture_ip6(self.pg0, rx, tx)
1078
1079 #
1080 # a stream with a non-zero MPLS TTL
1081 # PG1 is in table 1
1082 # we are ensuring the post-pop lookup occurs in the VRF table
1083 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001084 tx = self.create_stream_labelled_ip6(self.pg1, [VppMplsLabel(2)])
1085 rx = self.send_and_expect(self.pg1, tx, self.pg1)
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001086 self.verify_capture_ip6(self.pg0, rx, tx)
1087
Neale Rannscb630ff2016-12-14 13:31:29 +01001088 def test_deag(self):
1089 """ MPLS Deagg """
1090
1091 #
1092 # A de-agg route - next-hop lookup in default table
1093 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001094 route_34_eos = VppMplsRoute(self, 34, 1,
1095 [VppRoutePath("0.0.0.0",
1096 0xffffffff,
1097 nh_table_id=0)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001098 route_34_eos.add_vpp_config()
1099
1100 #
1101 # ping an interface in the default table
1102 # PG0 is in the default table
1103 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001104 tx = self.create_stream_labelled_ip4(self.pg0,
1105 [VppMplsLabel(34)],
1106 ping=1,
Neale Rannscb630ff2016-12-14 13:31:29 +01001107 ip_itf=self.pg0)
Neale Ranns31ed7442018-02-23 05:29:09 -08001108 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Rannscb630ff2016-12-14 13:31:29 +01001109 self.verify_capture_ip4(self.pg0, rx, tx, ping_resp=1)
1110
1111 #
1112 # A de-agg route - next-hop lookup in non-default table
1113 #
Neale Ranns5a8123b2017-01-26 01:18:23 -08001114 route_35_eos = VppMplsRoute(self, 35, 1,
1115 [VppRoutePath("0.0.0.0",
1116 0xffffffff,
1117 nh_table_id=1)])
Neale Rannscb630ff2016-12-14 13:31:29 +01001118 route_35_eos.add_vpp_config()
1119
1120 #
1121 # ping an interface in the non-default table
1122 # PG0 is in the default table. packet arrive labelled in the
1123 # default table and egress unlabelled in the non-default
1124 #
Klement Sekeradab231a2016-12-21 08:50:14 +01001125 tx = self.create_stream_labelled_ip4(
Neale Ranns31ed7442018-02-23 05:29:09 -08001126 self.pg0, [VppMplsLabel(35)], ping=1, ip_itf=self.pg1)
1127 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Rannscb630ff2016-12-14 13:31:29 +01001128 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1129
Neale Ranns6af1c042017-05-26 03:48:53 -07001130 #
1131 # Double pop
1132 #
1133 route_36_neos = VppMplsRoute(self, 36, 0,
1134 [VppRoutePath("0.0.0.0",
1135 0xffffffff)])
1136 route_36_neos.add_vpp_config()
1137
Neale Ranns31ed7442018-02-23 05:29:09 -08001138 tx = self.create_stream_labelled_ip4(self.pg0,
1139 [VppMplsLabel(36),
1140 VppMplsLabel(35)],
Neale Ranns6af1c042017-05-26 03:48:53 -07001141 ping=1, ip_itf=self.pg1)
Neale Ranns31ed7442018-02-23 05:29:09 -08001142 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns6af1c042017-05-26 03:48:53 -07001143 self.verify_capture_ip4(self.pg1, rx, tx, ping_resp=1)
1144
1145 route_36_neos.remove_vpp_config()
Neale Rannscb630ff2016-12-14 13:31:29 +01001146 route_35_eos.remove_vpp_config()
1147 route_34_eos.remove_vpp_config()
Neale Ranns8fe8cc22016-11-01 10:05:08 +00001148
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001149 def test_interface_rx(self):
1150 """ MPLS Interface Receive """
1151
1152 #
1153 # Add a non-recursive route that will forward the traffic
1154 # post-interface-rx
1155 #
1156 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1157 table_id=1,
1158 paths=[VppRoutePath(self.pg1.remote_ip4,
1159 self.pg1.sw_if_index)])
1160 route_10_0_0_1.add_vpp_config()
1161
1162 #
1163 # An interface receive label that maps traffic to RX on interface
1164 # pg1
1165 # by injecting the packet in on pg0, which is in table 0
1166 # doing an interface-rx on pg1 and matching a route in table 1
1167 # if the packet egresses, then we must have swapped to pg1
1168 # so as to have matched the route in table 1
1169 #
Neale Ranns097fa662018-05-01 05:17:55 -07001170 route_34_eos = VppMplsRoute(
1171 self, 34, 1,
1172 [VppRoutePath("0.0.0.0",
1173 self.pg1.sw_if_index,
1174 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001175 route_34_eos.add_vpp_config()
1176
1177 #
1178 # ping an interface in the default table
1179 # PG0 is in the default table
1180 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001181 tx = self.create_stream_labelled_ip4(self.pg0,
1182 [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001183 dst_ip="10.0.0.1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001184 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001185 self.verify_capture_ip4(self.pg1, rx, tx)
1186
1187 def test_mcast_mid_point(self):
1188 """ MPLS Multicast Mid Point """
1189
1190 #
1191 # Add a non-recursive route that will forward the traffic
1192 # post-interface-rx
1193 #
1194 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1195 table_id=1,
1196 paths=[VppRoutePath(self.pg1.remote_ip4,
1197 self.pg1.sw_if_index)])
1198 route_10_0_0_1.add_vpp_config()
1199
1200 #
1201 # Add a mcast entry that replicate to pg2 and pg3
1202 # and replicate to a interface-rx (like a bud node would)
1203 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001204 route_3400_eos = VppMplsRoute(
1205 self, 3400, 1,
1206 [VppRoutePath(self.pg2.remote_ip4,
1207 self.pg2.sw_if_index,
1208 labels=[VppMplsLabel(3401)]),
1209 VppRoutePath(self.pg3.remote_ip4,
1210 self.pg3.sw_if_index,
1211 labels=[VppMplsLabel(3402)]),
1212 VppRoutePath("0.0.0.0",
1213 self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001214 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX)],
Neale Ranns31ed7442018-02-23 05:29:09 -08001215 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001216 route_3400_eos.add_vpp_config()
1217
1218 #
1219 # ping an interface in the default table
1220 # PG0 is in the default table
1221 #
1222 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001223 tx = self.create_stream_labelled_ip4(self.pg0,
1224 [VppMplsLabel(3400, ttl=64)],
1225 n=257,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001226 dst_ip="10.0.0.1")
1227 self.pg0.add_stream(tx)
1228
1229 self.pg_enable_capture(self.pg_interfaces)
1230 self.pg_start()
1231
1232 rx = self.pg1.get_capture(257)
1233 self.verify_capture_ip4(self.pg1, rx, tx)
1234
1235 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001236 self.verify_capture_labelled(self.pg2, rx, tx,
1237 [VppMplsLabel(3401, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001238 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001239 self.verify_capture_labelled(self.pg3, rx, tx,
1240 [VppMplsLabel(3402, ttl=63)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001241
1242 def test_mcast_head(self):
1243 """ MPLS Multicast Head-end """
1244
1245 #
1246 # Create a multicast tunnel with two replications
1247 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001248 mpls_tun = VppMPLSTunnelInterface(
1249 self,
1250 [VppRoutePath(self.pg2.remote_ip4,
1251 self.pg2.sw_if_index,
1252 labels=[VppMplsLabel(42)]),
1253 VppRoutePath(self.pg3.remote_ip4,
1254 self.pg3.sw_if_index,
1255 labels=[VppMplsLabel(43)])],
1256 is_multicast=1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001257 mpls_tun.add_vpp_config()
1258 mpls_tun.admin_up()
1259
1260 #
1261 # add an unlabelled route through the new tunnel
1262 #
1263 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1264 [VppRoutePath("0.0.0.0",
1265 mpls_tun._sw_if_index)])
1266 route_10_0_0_3.add_vpp_config()
1267
1268 self.vapi.cli("clear trace")
1269 tx = self.create_stream_ip4(self.pg0, "10.0.0.3")
1270 self.pg0.add_stream(tx)
1271
1272 self.pg_enable_capture(self.pg_interfaces)
1273 self.pg_start()
1274
1275 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001276 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001277 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001278 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001279
1280 #
1281 # An an IP multicast route via the tunnel
1282 # A (*,G).
1283 # one accepting interface, pg0, 1 forwarding interface via the tunnel
1284 #
1285 route_232_1_1_1 = VppIpMRoute(
1286 self,
1287 "0.0.0.0",
1288 "232.1.1.1", 32,
1289 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1290 [VppMRoutePath(self.pg0.sw_if_index,
1291 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
1292 VppMRoutePath(mpls_tun._sw_if_index,
1293 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1294 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001295 self.logger.info(self.vapi.cli("sh ip mfib index 0"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001296
1297 self.vapi.cli("clear trace")
1298 tx = self.create_stream_ip4(self.pg0, "232.1.1.1")
1299 self.pg0.add_stream(tx)
1300
1301 self.pg_enable_capture(self.pg_interfaces)
1302 self.pg_start()
1303
1304 rx = self.pg2.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001305 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(42)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001306 rx = self.pg3.get_capture(257)
Neale Ranns31ed7442018-02-23 05:29:09 -08001307 self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [VppMplsLabel(43)])
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001308
Neale Ranns31426c62017-05-24 10:32:58 -07001309 def test_mcast_ip4_tail(self):
1310 """ MPLS IPv4 Multicast Tail """
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001311
1312 #
1313 # Add a multicast route that will forward the traffic
1314 # post-disposition
1315 #
1316 route_232_1_1_1 = VppIpMRoute(
1317 self,
1318 "0.0.0.0",
1319 "232.1.1.1", 32,
1320 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1321 table_id=1,
1322 paths=[VppMRoutePath(self.pg1.sw_if_index,
1323 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
1324 route_232_1_1_1.add_vpp_config()
1325
1326 #
1327 # An interface receive label that maps traffic to RX on interface
1328 # pg1
1329 # by injecting the packet in on pg0, which is in table 0
1330 # doing an rpf-id and matching a route in table 1
1331 # if the packet egresses, then we must have matched the route in
1332 # table 1
1333 #
Neale Ranns097fa662018-05-01 05:17:55 -07001334 route_34_eos = VppMplsRoute(
1335 self, 34, 1,
1336 [VppRoutePath("0.0.0.0",
1337 0xffffffff,
1338 nh_table_id=1,
1339 rpf_id=55)],
1340 is_multicast=1,
1341 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001342
1343 route_34_eos.add_vpp_config()
1344
1345 #
1346 # Drop due to interface lookup miss
1347 #
1348 self.vapi.cli("clear trace")
Neale Ranns31ed7442018-02-23 05:29:09 -08001349 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001350 dst_ip="232.1.1.1", n=1)
1351 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop none")
1352
1353 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001354 # set the RPF-ID of the entry to match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001355 #
1356 route_232_1_1_1.update_rpf_id(55)
Neale Ranns097fa662018-05-01 05:17:55 -07001357 self.logger.info(self.vapi.cli("sh ip mfib index 1 232.1.1.1"))
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001358
Neale Ranns31ed7442018-02-23 05:29:09 -08001359 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
1360 dst_ip="232.1.1.1")
1361 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001362 self.verify_capture_ip4(self.pg1, rx, tx)
1363
1364 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001365 # disposed packets have an invalid IPv4 checksum
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001366 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001367 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001368 dst_ip="232.1.1.1", n=65,
1369 chksum=1)
1370 self.send_and_assert_no_replies(self.pg0, tx, "Invalid Checksum")
1371
1372 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001373 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001374 #
1375 route_232_1_1_1.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001376 tx = self.create_stream_labelled_ip4(self.pg0, [VppMplsLabel(34)],
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001377 dst_ip="232.1.1.1")
1378 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1379
Neale Ranns31426c62017-05-24 10:32:58 -07001380 def test_mcast_ip6_tail(self):
1381 """ MPLS IPv6 Multicast Tail """
1382
1383 #
1384 # Add a multicast route that will forward the traffic
1385 # post-disposition
1386 #
1387 route_ff = VppIpMRoute(
1388 self,
1389 "::",
1390 "ff01::1", 32,
1391 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
1392 table_id=1,
1393 paths=[VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001394 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
1395 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns31426c62017-05-24 10:32:58 -07001396 route_ff.add_vpp_config()
1397
1398 #
1399 # An interface receive label that maps traffic to RX on interface
1400 # pg1
1401 # by injecting the packet in on pg0, which is in table 0
1402 # doing an rpf-id and matching a route in table 1
1403 # if the packet egresses, then we must have matched the route in
1404 # table 1
1405 #
1406 route_34_eos = VppMplsRoute(
1407 self, 34, 1,
1408 [VppRoutePath("::",
Neale Ranns097fa662018-05-01 05:17:55 -07001409 0xffffffff,
Neale Ranns31426c62017-05-24 10:32:58 -07001410 nh_table_id=1,
Neale Ranns097fa662018-05-01 05:17:55 -07001411 rpf_id=55)],
1412 is_multicast=1,
1413 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
Neale Ranns31426c62017-05-24 10:32:58 -07001414
1415 route_34_eos.add_vpp_config()
1416
1417 #
1418 # Drop due to interface lookup miss
1419 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001420 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001421 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001422 self.send_and_assert_no_replies(self.pg0, tx, "RPF Miss")
Neale Ranns31426c62017-05-24 10:32:58 -07001423
1424 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001425 # set the RPF-ID of the entry to match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001426 #
1427 route_ff.update_rpf_id(55)
1428
Neale Ranns31ed7442018-02-23 05:29:09 -08001429 tx = self.create_stream_labelled_ip6(self.pg0, [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001430 dst_ip="ff01::1")
Neale Ranns31ed7442018-02-23 05:29:09 -08001431 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns31426c62017-05-24 10:32:58 -07001432 self.verify_capture_ip6(self.pg1, rx, tx)
1433
1434 #
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001435 # disposed packets have hop-limit = 1
1436 #
Neale Ranns31ed7442018-02-23 05:29:09 -08001437 tx = self.create_stream_labelled_ip6(self.pg0,
1438 [VppMplsLabel(34)],
1439 dst_ip="ff01::1",
1440 hlim=1)
1441 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns52fae862018-01-08 04:41:42 -08001442 self.verify_capture_ip6_icmp(self.pg0, rx, tx)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001443
1444 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001445 # set the RPF-ID of the entry to not match the input packet's
Neale Ranns31426c62017-05-24 10:32:58 -07001446 #
1447 route_ff.update_rpf_id(56)
Neale Ranns31ed7442018-02-23 05:29:09 -08001448 tx = self.create_stream_labelled_ip6(self.pg0,
1449 [VppMplsLabel(34)],
Neale Ranns31426c62017-05-24 10:32:58 -07001450 dst_ip="ff01::1")
1451 self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56")
1452
Neale Rannsd5d7b962019-08-04 03:30:56 -07001453 def test_6pe(self):
1454 """ MPLS 6PE """
1455
1456 #
1457 # Add a non-recursive route with a single out label
1458 #
1459 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1460 [VppRoutePath(self.pg0.remote_ip4,
1461 self.pg0.sw_if_index,
1462 labels=[VppMplsLabel(45)])])
1463 route_10_0_0_1.add_vpp_config()
1464
1465 # bind a local label to the route
1466 binding = VppMplsIpBind(self, 44, "10.0.0.1", 32)
1467 binding.add_vpp_config()
1468
1469 #
1470 # a labelled v6 route that resolves through the v4
1471 #
1472 route_2001_3 = VppIpRoute(
1473 self, "2001::3", 128,
1474 [VppRoutePath("10.0.0.1",
1475 INVALID_INDEX,
1476 labels=[VppMplsLabel(32)])])
1477 route_2001_3.add_vpp_config()
1478
1479 tx = self.create_stream_ip6(self.pg0, "2001::3")
1480 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1481
1482 self.verify_capture_labelled_ip6(self.pg0, rx, tx,
1483 [VppMplsLabel(45),
1484 VppMplsLabel(32)])
1485
1486 #
1487 # and a v4 recursive via the v6
1488 #
1489 route_20_3 = VppIpRoute(
1490 self, "20.0.0.3", 32,
1491 [VppRoutePath("2001::3",
1492 INVALID_INDEX,
1493 labels=[VppMplsLabel(99)])])
1494 route_20_3.add_vpp_config()
1495
1496 tx = self.create_stream_ip4(self.pg0, "20.0.0.3")
1497 rx = self.send_and_expect(self.pg0, tx, self.pg0)
1498
1499 self.verify_capture_labelled_ip4(self.pg0, rx, tx,
1500 [VppMplsLabel(45),
1501 VppMplsLabel(32),
1502 VppMplsLabel(99)])
1503
Neale Ranns180279b2017-03-16 15:49:09 -04001504
1505class TestMPLSDisabled(VppTestCase):
1506 """ MPLS disabled """
1507
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001508 @classmethod
1509 def setUpClass(cls):
1510 super(TestMPLSDisabled, cls).setUpClass()
1511
1512 @classmethod
1513 def tearDownClass(cls):
1514 super(TestMPLSDisabled, cls).tearDownClass()
1515
Neale Ranns180279b2017-03-16 15:49:09 -04001516 def setUp(self):
1517 super(TestMPLSDisabled, self).setUp()
1518
1519 # create 2 pg interfaces
1520 self.create_pg_interfaces(range(2))
1521
Neale Ranns15002542017-09-10 04:39:11 -07001522 self.tbl = VppMplsTable(self, 0)
1523 self.tbl.add_vpp_config()
1524
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001525 # PG0 is MPLS enabled
Neale Ranns180279b2017-03-16 15:49:09 -04001526 self.pg0.admin_up()
1527 self.pg0.config_ip4()
1528 self.pg0.resolve_arp()
1529 self.pg0.enable_mpls()
1530
1531 # PG 1 is not MPLS enabled
1532 self.pg1.admin_up()
1533
1534 def tearDown(self):
Neale Ranns180279b2017-03-16 15:49:09 -04001535 for i in self.pg_interfaces:
1536 i.unconfig_ip4()
1537 i.admin_down()
1538
Neale Ranns15002542017-09-10 04:39:11 -07001539 self.pg0.disable_mpls()
1540 super(TestMPLSDisabled, self).tearDown()
1541
Neale Ranns180279b2017-03-16 15:49:09 -04001542 def test_mpls_disabled(self):
1543 """ MPLS Disabled """
1544
1545 tx = (Ether(src=self.pg1.remote_mac,
1546 dst=self.pg1.local_mac) /
1547 MPLS(label=32, ttl=64) /
1548 IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
1549 UDP(sport=1234, dport=1234) /
1550 Raw('\xa5' * 100))
1551
1552 #
1553 # A simple MPLS xconnect - eos label in label out
1554 #
1555 route_32_eos = VppMplsRoute(self, 32, 1,
1556 [VppRoutePath(self.pg0.remote_ip4,
1557 self.pg0.sw_if_index,
1558 labels=[33])])
1559 route_32_eos.add_vpp_config()
1560
1561 #
1562 # PG1 does not forward IP traffic
1563 #
1564 self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled")
1565
1566 #
1567 # MPLS enable PG1
1568 #
1569 self.pg1.enable_mpls()
1570
1571 #
1572 # Now we get packets through
1573 #
1574 self.pg1.add_stream(tx)
1575 self.pg_enable_capture(self.pg_interfaces)
1576 self.pg_start()
1577
1578 rx = self.pg0.get_capture(1)
1579
1580 #
1581 # Disable PG1
1582 #
1583 self.pg1.disable_mpls()
1584
1585 #
1586 # PG1 does not forward IP traffic
1587 #
1588 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1589 self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
1590
1591
Neale Rannsf12a83f2017-04-18 09:09:40 -07001592class TestMPLSPIC(VppTestCase):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001593 """ MPLS Prefix-Independent Convergence (PIC) edge convergence """
Neale Rannsf12a83f2017-04-18 09:09:40 -07001594
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001595 @classmethod
1596 def setUpClass(cls):
1597 super(TestMPLSPIC, cls).setUpClass()
1598
1599 @classmethod
1600 def tearDownClass(cls):
1601 super(TestMPLSPIC, cls).tearDownClass()
1602
Neale Rannsf12a83f2017-04-18 09:09:40 -07001603 def setUp(self):
1604 super(TestMPLSPIC, self).setUp()
1605
1606 # create 2 pg interfaces
1607 self.create_pg_interfaces(range(4))
1608
Neale Ranns15002542017-09-10 04:39:11 -07001609 mpls_tbl = VppMplsTable(self, 0)
1610 mpls_tbl.add_vpp_config()
1611 tbl4 = VppIpTable(self, 1)
1612 tbl4.add_vpp_config()
1613 tbl6 = VppIpTable(self, 1, is_ip6=1)
1614 tbl6.add_vpp_config()
1615
Neale Rannsf12a83f2017-04-18 09:09:40 -07001616 # core links
1617 self.pg0.admin_up()
1618 self.pg0.config_ip4()
1619 self.pg0.resolve_arp()
1620 self.pg0.enable_mpls()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001621
Neale Rannsf12a83f2017-04-18 09:09:40 -07001622 self.pg1.admin_up()
1623 self.pg1.config_ip4()
1624 self.pg1.resolve_arp()
1625 self.pg1.enable_mpls()
1626
1627 # VRF (customer facing) link
1628 self.pg2.admin_up()
1629 self.pg2.set_table_ip4(1)
1630 self.pg2.config_ip4()
1631 self.pg2.resolve_arp()
1632 self.pg2.set_table_ip6(1)
1633 self.pg2.config_ip6()
1634 self.pg2.resolve_ndp()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001635
Neale Rannsf12a83f2017-04-18 09:09:40 -07001636 self.pg3.admin_up()
1637 self.pg3.set_table_ip4(1)
1638 self.pg3.config_ip4()
1639 self.pg3.resolve_arp()
1640 self.pg3.set_table_ip6(1)
1641 self.pg3.config_ip6()
1642 self.pg3.resolve_ndp()
1643
1644 def tearDown(self):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001645 self.pg0.disable_mpls()
Neale Ranns15002542017-09-10 04:39:11 -07001646 self.pg1.disable_mpls()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001647 for i in self.pg_interfaces:
1648 i.unconfig_ip4()
1649 i.unconfig_ip6()
1650 i.set_table_ip4(0)
1651 i.set_table_ip6(0)
1652 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001653 super(TestMPLSPIC, self).tearDown()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001654
1655 def test_mpls_ibgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001656 """ MPLS iBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001657
1658 1) setup many iBGP VPN routes via a pair of iBGP peers.
1659 2) Check EMCP forwarding to these peers
1660 3) withdraw the IGP route to one of these peers.
1661 4) check forwarding continues to the remaining peer
1662 """
1663
1664 #
1665 # IGP+LDP core routes
1666 #
1667 core_10_0_0_45 = VppIpRoute(self, "10.0.0.45", 32,
1668 [VppRoutePath(self.pg0.remote_ip4,
1669 self.pg0.sw_if_index,
1670 labels=[45])])
1671 core_10_0_0_45.add_vpp_config()
1672
1673 core_10_0_0_46 = VppIpRoute(self, "10.0.0.46", 32,
1674 [VppRoutePath(self.pg1.remote_ip4,
1675 self.pg1.sw_if_index,
1676 labels=[46])])
1677 core_10_0_0_46.add_vpp_config()
1678
1679 #
1680 # Lot's of VPN routes. We need more the 64 so VPP will build
1681 # the fast convergence indirection
1682 #
1683 vpn_routes = []
1684 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001685 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001686 dst = "192.168.1.%d" % ii
Neale Ranns097fa662018-05-01 05:17:55 -07001687 vpn_routes.append(VppIpRoute(
1688 self, dst, 32,
1689 [VppRoutePath(
1690 "10.0.0.45",
1691 0xffffffff,
1692 labels=[145],
1693 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST),
1694 VppRoutePath(
1695 "10.0.0.46",
1696 0xffffffff,
1697 labels=[146],
1698 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_HOST)],
1699 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001700 vpn_routes[ii].add_vpp_config()
1701
1702 pkts.append(Ether(dst=self.pg2.local_mac,
1703 src=self.pg2.remote_mac) /
1704 IP(src=self.pg2.remote_ip4, dst=dst) /
1705 UDP(sport=1234, dport=1234) /
1706 Raw('\xa5' * 100))
1707
1708 #
1709 # Send the packet stream (one pkt to each VPN route)
1710 # - expect a 50-50 split of the traffic
1711 #
1712 self.pg2.add_stream(pkts)
1713 self.pg_enable_capture(self.pg_interfaces)
1714 self.pg_start()
1715
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001716 rx0 = self.pg0._get_capture(NUM_PKTS)
1717 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001718
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001719 # not testing the LB hashing algorithm so we're not concerned
Neale Rannsf12a83f2017-04-18 09:09:40 -07001720 # with the split ratio, just as long as neither is 0
1721 self.assertNotEqual(0, len(rx0))
1722 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001723 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1724 "Expected all (%s) packets across both ECMP paths. "
1725 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001726
1727 #
1728 # use a test CLI command to stop the FIB walk process, this
1729 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001730 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001731 #
1732 self.vapi.ppcli("test fib-walk-process disable")
1733
1734 #
1735 # Withdraw one of the IGP routes
1736 #
1737 core_10_0_0_46.remove_vpp_config()
1738
1739 #
1740 # now all packets should be forwarded through the remaining peer
1741 #
1742 self.vapi.ppcli("clear trace")
1743 self.pg2.add_stream(pkts)
1744 self.pg_enable_capture(self.pg_interfaces)
1745 self.pg_start()
1746
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001747 rx0 = self.pg0.get_capture(NUM_PKTS)
1748 self.assertEqual(len(pkts), len(rx0),
1749 "Expected all (%s) packets across single path. "
1750 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001751
1752 #
1753 # enable the FIB walk process to converge the FIB
1754 #
1755 self.vapi.ppcli("test fib-walk-process enable")
1756
1757 #
1758 # packets should still be forwarded through the remaining peer
1759 #
1760 self.pg2.add_stream(pkts)
1761 self.pg_enable_capture(self.pg_interfaces)
1762 self.pg_start()
1763
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001764 rx0 = self.pg0.get_capture(NUM_PKTS)
1765 self.assertEqual(len(pkts), len(rx0),
1766 "Expected all (%s) packets across single path. "
1767 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001768
1769 #
1770 # Add the IGP route back and we return to load-balancing
1771 #
1772 core_10_0_0_46.add_vpp_config()
1773
1774 self.pg2.add_stream(pkts)
1775 self.pg_enable_capture(self.pg_interfaces)
1776 self.pg_start()
1777
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001778 rx0 = self.pg0._get_capture(NUM_PKTS)
1779 rx1 = self.pg1._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001780 self.assertNotEqual(0, len(rx0))
1781 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001782 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1783 "Expected all (%s) packets across both ECMP paths. "
1784 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001785
1786 def test_mpls_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001787 """ MPLS eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001788
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001789 1) setup many eBGP VPN routes via a pair of eBGP peers.
Neale Rannsf12a83f2017-04-18 09:09:40 -07001790 2) Check EMCP forwarding to these peers
1791 3) withdraw one eBGP path - expect LB across remaining eBGP
1792 """
1793
1794 #
1795 # Lot's of VPN routes. We need more the 64 so VPP will build
1796 # the fast convergence indirection
1797 #
1798 vpn_routes = []
1799 vpn_bindings = []
1800 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001801 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001802 dst = "192.168.1.%d" % ii
1803 local_label = 1600 + ii
Neale Ranns097fa662018-05-01 05:17:55 -07001804 vpn_routes.append(VppIpRoute(
1805 self, dst, 32,
1806 [VppRoutePath(
1807 self.pg2.remote_ip4,
1808 0xffffffff,
1809 nh_table_id=1,
1810 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1811 VppRoutePath(
1812 self.pg3.remote_ip4,
1813 0xffffffff,
1814 nh_table_id=1,
1815 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1816 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001817 vpn_routes[ii].add_vpp_config()
1818
1819 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 32,
1820 ip_table_id=1))
1821 vpn_bindings[ii].add_vpp_config()
1822
1823 pkts.append(Ether(dst=self.pg0.local_mac,
1824 src=self.pg0.remote_mac) /
1825 MPLS(label=local_label, ttl=64) /
1826 IP(src=self.pg0.remote_ip4, dst=dst) /
1827 UDP(sport=1234, dport=1234) /
1828 Raw('\xa5' * 100))
1829
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001830 #
1831 # Send the packet stream (one pkt to each VPN route)
1832 # - expect a 50-50 split of the traffic
1833 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001834 self.pg0.add_stream(pkts)
1835 self.pg_enable_capture(self.pg_interfaces)
1836 self.pg_start()
1837
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001838 rx0 = self.pg2._get_capture(NUM_PKTS)
1839 rx1 = self.pg3._get_capture(NUM_PKTS)
1840
1841 # not testing the LB hashing algorithm so we're not concerned
1842 # with the split ratio, just as long as neither is 0
Neale Rannsf12a83f2017-04-18 09:09:40 -07001843 self.assertNotEqual(0, len(rx0))
1844 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001845 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1846 "Expected all (%s) packets across both ECMP paths. "
1847 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001848
1849 #
1850 # use a test CLI command to stop the FIB walk process, this
1851 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001852 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001853 #
1854 self.vapi.ppcli("test fib-walk-process disable")
1855
1856 #
1857 # withdraw the connected prefix on the interface.
1858 #
1859 self.pg2.unconfig_ip4()
1860
1861 #
1862 # now all packets should be forwarded through the remaining peer
1863 #
1864 self.pg0.add_stream(pkts)
1865 self.pg_enable_capture(self.pg_interfaces)
1866 self.pg_start()
1867
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001868 rx0 = self.pg3.get_capture(NUM_PKTS)
1869 self.assertEqual(len(pkts), len(rx0),
1870 "Expected all (%s) packets across single path. "
1871 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001872
1873 #
1874 # enable the FIB walk process to converge the FIB
1875 #
1876 self.vapi.ppcli("test fib-walk-process enable")
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001877
1878 #
1879 # packets should still be forwarded through the remaining peer
1880 #
Neale Rannsf12a83f2017-04-18 09:09:40 -07001881 self.pg0.add_stream(pkts)
1882 self.pg_enable_capture(self.pg_interfaces)
1883 self.pg_start()
1884
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001885 rx0 = self.pg3.get_capture(NUM_PKTS)
1886 self.assertEqual(len(pkts), len(rx0),
1887 "Expected all (%s) packets across single path. "
1888 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001889
1890 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001891 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07001892 #
1893 self.pg2.config_ip4()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001894 self.pg2.resolve_arp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07001895
1896 self.pg0.add_stream(pkts)
1897 self.pg_enable_capture(self.pg_interfaces)
1898 self.pg_start()
1899
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001900 rx0 = self.pg2._get_capture(NUM_PKTS)
1901 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001902 self.assertNotEqual(0, len(rx0))
1903 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001904 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1905 "Expected all (%s) packets across both ECMP paths. "
1906 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001907
1908 def test_mpls_v6_ebgp_pic(self):
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001909 """ MPLSv6 eBGP Prefix-Independent Convergence (PIC) edge convergence
Neale Rannsf12a83f2017-04-18 09:09:40 -07001910
1911 1) setup many eBGP VPNv6 routes via a pair of eBGP peers
1912 2) Check EMCP forwarding to these peers
1913 3) withdraw one eBGP path - expect LB across remaining eBGP
1914 """
1915
1916 #
1917 # Lot's of VPN routes. We need more the 64 so VPP will build
1918 # the fast convergence indirection
1919 #
1920 vpn_routes = []
1921 vpn_bindings = []
1922 pkts = []
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001923 for ii in range(NUM_PKTS):
Neale Rannsf12a83f2017-04-18 09:09:40 -07001924 dst = "3000::%d" % ii
1925 local_label = 1600 + ii
Neale Rannsda78f952017-05-24 09:15:43 -07001926 vpn_routes.append(VppIpRoute(
1927 self, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001928 [VppRoutePath(
1929 self.pg2.remote_ip6,
1930 0xffffffff,
1931 nh_table_id=1,
1932 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED),
1933 VppRoutePath(
1934 self.pg3.remote_ip6,
1935 0xffffffff,
1936 nh_table_id=1,
1937 flags=FibPathFlags.FIB_PATH_FLAG_RESOLVE_VIA_ATTACHED)],
1938 table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001939 vpn_routes[ii].add_vpp_config()
1940
1941 vpn_bindings.append(VppMplsIpBind(self, local_label, dst, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001942 ip_table_id=1))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001943 vpn_bindings[ii].add_vpp_config()
1944
1945 pkts.append(Ether(dst=self.pg0.local_mac,
1946 src=self.pg0.remote_mac) /
1947 MPLS(label=local_label, ttl=64) /
1948 IPv6(src=self.pg0.remote_ip6, dst=dst) /
1949 UDP(sport=1234, dport=1234) /
1950 Raw('\xa5' * 100))
Neale Ranns097fa662018-05-01 05:17:55 -07001951 self.logger.info(self.vapi.cli("sh ip6 fib %s" % dst))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001952
1953 self.pg0.add_stream(pkts)
1954 self.pg_enable_capture(self.pg_interfaces)
1955 self.pg_start()
1956
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001957 rx0 = self.pg2._get_capture(NUM_PKTS)
1958 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07001959 self.assertNotEqual(0, len(rx0))
1960 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001961 self.assertEqual(len(pkts), len(rx0) + len(rx1),
1962 "Expected all (%s) packets across both ECMP paths. "
1963 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001964
1965 #
1966 # use a test CLI command to stop the FIB walk process, this
1967 # will prevent the FIB converging the VPN routes and thus allow
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001968 # us to probe the interim (post-fail, pre-converge) state
Neale Rannsf12a83f2017-04-18 09:09:40 -07001969 #
1970 self.vapi.ppcli("test fib-walk-process disable")
1971
1972 #
1973 # withdraw the connected prefix on the interface.
1974 # and shutdown the interface so the ND cache is flushed.
1975 #
1976 self.pg2.unconfig_ip6()
1977 self.pg2.admin_down()
1978
1979 #
1980 # now all packets should be forwarded through the remaining peer
1981 #
1982 self.pg0.add_stream(pkts)
1983 self.pg_enable_capture(self.pg_interfaces)
1984 self.pg_start()
1985
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001986 rx0 = self.pg3.get_capture(NUM_PKTS)
1987 self.assertEqual(len(pkts), len(rx0),
1988 "Expected all (%s) packets across single path. "
1989 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07001990
1991 #
1992 # enable the FIB walk process to converge the FIB
1993 #
1994 self.vapi.ppcli("test fib-walk-process enable")
1995 self.pg0.add_stream(pkts)
1996 self.pg_enable_capture(self.pg_interfaces)
1997 self.pg_start()
1998
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04001999 rx0 = self.pg3.get_capture(NUM_PKTS)
2000 self.assertEqual(len(pkts), len(rx0),
2001 "Expected all (%s) packets across single path. "
2002 "rx0: %s." % (len(pkts), len(rx0)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002003
2004 #
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002005 # put the connected routes back
Neale Rannsf12a83f2017-04-18 09:09:40 -07002006 #
2007 self.pg2.admin_up()
2008 self.pg2.config_ip6()
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002009 self.pg2.resolve_ndp()
Neale Rannsf12a83f2017-04-18 09:09:40 -07002010
2011 self.pg0.add_stream(pkts)
2012 self.pg_enable_capture(self.pg_interfaces)
2013 self.pg_start()
2014
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002015 rx0 = self.pg2._get_capture(NUM_PKTS)
2016 rx1 = self.pg3._get_capture(NUM_PKTS)
Neale Rannsf12a83f2017-04-18 09:09:40 -07002017 self.assertNotEqual(0, len(rx0))
2018 self.assertNotEqual(0, len(rx1))
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002019 self.assertEqual(len(pkts), len(rx0) + len(rx1),
2020 "Expected all (%s) packets across both ECMP paths. "
2021 "rx0: %s rx1: %s." % (len(pkts), len(rx0), len(rx1)))
Neale Rannsf12a83f2017-04-18 09:09:40 -07002022
2023
Neale Rannsda78f952017-05-24 09:15:43 -07002024class TestMPLSL2(VppTestCase):
2025 """ MPLS-L2 """
2026
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002027 @classmethod
2028 def setUpClass(cls):
2029 super(TestMPLSL2, cls).setUpClass()
2030
2031 @classmethod
2032 def tearDownClass(cls):
2033 super(TestMPLSL2, cls).tearDownClass()
2034
Neale Rannsda78f952017-05-24 09:15:43 -07002035 def setUp(self):
2036 super(TestMPLSL2, self).setUp()
2037
2038 # create 2 pg interfaces
2039 self.create_pg_interfaces(range(2))
2040
Neale Ranns15002542017-09-10 04:39:11 -07002041 # create the default MPLS table
2042 self.tables = []
2043 tbl = VppMplsTable(self, 0)
2044 tbl.add_vpp_config()
2045 self.tables.append(tbl)
2046
Neale Rannsda78f952017-05-24 09:15:43 -07002047 # use pg0 as the core facing interface
2048 self.pg0.admin_up()
2049 self.pg0.config_ip4()
2050 self.pg0.resolve_arp()
2051 self.pg0.enable_mpls()
2052
Neale Ranns15002542017-09-10 04:39:11 -07002053 # use the other 2 for customer facing L2 links
Neale Rannsda78f952017-05-24 09:15:43 -07002054 for i in self.pg_interfaces[1:]:
2055 i.admin_up()
2056
2057 def tearDown(self):
Neale Rannsda78f952017-05-24 09:15:43 -07002058 for i in self.pg_interfaces[1:]:
2059 i.admin_down()
2060
2061 self.pg0.disable_mpls()
2062 self.pg0.unconfig_ip4()
2063 self.pg0.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07002064 super(TestMPLSL2, self).tearDown()
Neale Rannsda78f952017-05-24 09:15:43 -07002065
Neale Ranns31ed7442018-02-23 05:29:09 -08002066 def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels):
Neale Rannsda78f952017-05-24 09:15:43 -07002067 capture = verify_filter(capture, sent)
2068
2069 self.assertEqual(len(capture), len(sent))
2070
2071 for i in range(len(capture)):
2072 tx = sent[i]
2073 rx = capture[i]
2074
2075 # the MPLS TTL is 255 since it enters a new tunnel
Neale Ranns31ed7442018-02-23 05:29:09 -08002076 verify_mpls_stack(self, rx, mpls_labels)
Neale Rannsda78f952017-05-24 09:15:43 -07002077
2078 tx_eth = tx[Ether]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07002079 rx_eth = Ether(scapy.compat.raw(rx[MPLS].payload))
Neale Rannsda78f952017-05-24 09:15:43 -07002080
2081 self.assertEqual(rx_eth.src, tx_eth.src)
2082 self.assertEqual(rx_eth.dst, tx_eth.dst)
2083
2084 def test_vpws(self):
2085 """ Virtual Private Wire Service """
2086
2087 #
2088 # Create an MPLS tunnel that pushes 1 label
Neale Ranns31ed7442018-02-23 05:29:09 -08002089 # For Ethernet over MPLS the uniform mode is irrelevant since ttl/cos
2090 # information is not in the packet, but we test it works anyway
Neale Rannsda78f952017-05-24 09:15:43 -07002091 #
Neale Ranns31ed7442018-02-23 05:29:09 -08002092 mpls_tun_1 = VppMPLSTunnelInterface(
2093 self,
2094 [VppRoutePath(self.pg0.remote_ip4,
2095 self.pg0.sw_if_index,
2096 labels=[VppMplsLabel(42, MplsLspMode.UNIFORM)])],
2097 is_l2=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002098 mpls_tun_1.add_vpp_config()
2099 mpls_tun_1.admin_up()
2100
2101 #
2102 # Create a label entry to for 55 that does L2 input to the tunnel
2103 #
2104 route_55_eos = VppMplsRoute(
2105 self, 55, 1,
2106 [VppRoutePath("0.0.0.0",
2107 mpls_tun_1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002108 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2109 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2110 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Rannsda78f952017-05-24 09:15:43 -07002111 route_55_eos.add_vpp_config()
2112
2113 #
2114 # Cross-connect the tunnel with one of the customers L2 interfaces
2115 #
2116 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
2117 mpls_tun_1.sw_if_index,
2118 enable=1)
2119 self.vapi.sw_interface_set_l2_xconnect(mpls_tun_1.sw_if_index,
2120 self.pg1.sw_if_index,
2121 enable=1)
2122
2123 #
2124 # inject a packet from the core
2125 #
2126 pcore = (Ether(dst=self.pg0.local_mac,
2127 src=self.pg0.remote_mac) /
2128 MPLS(label=55, ttl=64) /
2129 Ether(dst="00:00:de:ad:ba:be",
2130 src="00:00:de:ad:be:ef") /
2131 IP(src="10.10.10.10", dst="11.11.11.11") /
2132 UDP(sport=1234, dport=1234) /
2133 Raw('\xa5' * 100))
2134
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002135 tx0 = pcore * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002136 rx0 = self.send_and_expect(self.pg0, tx0, self.pg1)
2137 payload = pcore[MPLS].payload
Neale Rannsda78f952017-05-24 09:15:43 -07002138
Neale Ranns31ed7442018-02-23 05:29:09 -08002139 self.assertEqual(rx0[0][Ether].dst, payload[Ether].dst)
2140 self.assertEqual(rx0[0][Ether].src, payload[Ether].src)
Neale Rannsda78f952017-05-24 09:15:43 -07002141
2142 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07002143 # Inject a packet from the customer/L2 side
Neale Rannsda78f952017-05-24 09:15:43 -07002144 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002145 tx1 = pcore[MPLS].payload * NUM_PKTS
Neale Ranns31ed7442018-02-23 05:29:09 -08002146 rx1 = self.send_and_expect(self.pg1, tx1, self.pg0)
Neale Rannsda78f952017-05-24 09:15:43 -07002147
Neale Ranns31ed7442018-02-23 05:29:09 -08002148 self.verify_capture_tunneled_ethernet(rx1, tx1, [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002149
2150 def test_vpls(self):
2151 """ Virtual Private LAN Service """
2152 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002153 # Create a L2 MPLS tunnels
Neale Rannsda78f952017-05-24 09:15:43 -07002154 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002155 mpls_tun1 = VppMPLSTunnelInterface(
Neale Ranns31ed7442018-02-23 05:29:09 -08002156 self,
2157 [VppRoutePath(self.pg0.remote_ip4,
2158 self.pg0.sw_if_index,
2159 labels=[VppMplsLabel(42)])],
2160 is_l2=1)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002161 mpls_tun1.add_vpp_config()
2162 mpls_tun1.admin_up()
2163
2164 mpls_tun2 = VppMPLSTunnelInterface(
2165 self,
2166 [VppRoutePath(self.pg0.remote_ip4,
2167 self.pg0.sw_if_index,
2168 labels=[VppMplsLabel(43)])],
2169 is_l2=1)
2170 mpls_tun2.add_vpp_config()
2171 mpls_tun2.admin_up()
Neale Rannsda78f952017-05-24 09:15:43 -07002172
2173 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002174 # Create a label entries, 55 and 56, that do L2 input to the tunnel
2175 # the latter includes a Psuedo Wire Control Word
Neale Rannsda78f952017-05-24 09:15:43 -07002176 #
2177 route_55_eos = VppMplsRoute(
2178 self, 55, 1,
2179 [VppRoutePath("0.0.0.0",
Neale Ranns1dbcf302019-07-19 11:44:53 +00002180 mpls_tun1.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07002181 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2182 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2183 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
Neale Ranns1dbcf302019-07-19 11:44:53 +00002184
2185 route_56_eos = VppMplsRoute(
2186 self, 56, 1,
2187 [VppRoutePath("0.0.0.0",
2188 mpls_tun2.sw_if_index,
2189 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
2190 flags=FibPathFlags.FIB_PATH_FLAG_POP_PW_CW,
2191 proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)],
2192 eos_proto=FibPathProto.FIB_PATH_NH_PROTO_ETHERNET)
2193
2194 # move me
2195 route_56_eos.add_vpp_config()
Neale Rannsda78f952017-05-24 09:15:43 -07002196 route_55_eos.add_vpp_config()
2197
Neale Ranns1dbcf302019-07-19 11:44:53 +00002198 self.logger.info(self.vapi.cli("sh mpls fib 56"))
2199
Neale Rannsda78f952017-05-24 09:15:43 -07002200 #
2201 # add to tunnel to the customers bridge-domain
2202 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002203 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002204 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1)
2205 self.vapi.sw_interface_set_l2_bridge(
2206 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1)
Ole Troana5b2eec2019-03-11 19:23:25 +01002207 self.vapi.sw_interface_set_l2_bridge(
2208 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
Neale Rannsda78f952017-05-24 09:15:43 -07002209
2210 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002211 # Packet from host on the customer interface to each host
2212 # reachable over the core, and vice-versa
Neale Rannsda78f952017-05-24 09:15:43 -07002213 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002214 p_cust1 = (Ether(dst="00:00:de:ad:ba:b1",
2215 src="00:00:de:ad:be:ef") /
2216 IP(src="10.10.10.10", dst="11.11.11.11") /
2217 UDP(sport=1234, dport=1234) /
2218 Raw('\xa5' * 100))
2219 p_cust2 = (Ether(dst="00:00:de:ad:ba:b2",
2220 src="00:00:de:ad:be:ef") /
2221 IP(src="10.10.10.10", dst="11.11.11.12") /
2222 UDP(sport=1234, dport=1234) /
2223 Raw('\xa5' * 100))
2224 p_core1 = (Ether(dst=self.pg0.local_mac,
2225 src=self.pg0.remote_mac) /
2226 MPLS(label=55, ttl=64) /
2227 Ether(src="00:00:de:ad:ba:b1",
2228 dst="00:00:de:ad:be:ef") /
2229 IP(dst="10.10.10.10", src="11.11.11.11") /
2230 UDP(sport=1234, dport=1234) /
2231 Raw('\xa5' * 100))
2232 p_core2 = (Ether(dst=self.pg0.local_mac,
2233 src=self.pg0.remote_mac) /
2234 MPLS(label=56, ttl=64) /
2235 Raw('\x01' * 4) / # PW CW
2236 Ether(src="00:00:de:ad:ba:b2",
2237 dst="00:00:de:ad:be:ef") /
2238 IP(dst="10.10.10.10", src="11.11.11.12") /
2239 UDP(sport=1234, dport=1234) /
2240 Raw('\xa5' * 100))
Neale Rannsda78f952017-05-24 09:15:43 -07002241
2242 #
2243 # The BD is learning, so send in one of each packet to learn
2244 #
Neale Rannsda78f952017-05-24 09:15:43 -07002245
Neale Ranns1dbcf302019-07-19 11:44:53 +00002246 # 2 packets due to BD flooding
2247 rx = self.send_and_expect(self.pg1, p_cust1, self.pg0, n_rx=2)
2248 rx = self.send_and_expect(self.pg1, p_cust2, self.pg0, n_rx=2)
Neale Rannsda78f952017-05-24 09:15:43 -07002249
Neale Ranns1dbcf302019-07-19 11:44:53 +00002250 # we've learnt this so expect it be be forwarded not flooded
2251 rx = self.send_and_expect(self.pg0, [p_core1], self.pg1)
2252 self.assertEqual(rx[0][Ether].dst, p_cust1[Ether].src)
2253 self.assertEqual(rx[0][Ether].src, p_cust1[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002254
Neale Ranns1dbcf302019-07-19 11:44:53 +00002255 rx = self.send_and_expect(self.pg0, [p_core2], self.pg1)
2256 self.assertEqual(rx[0][Ether].dst, p_cust2[Ether].src)
2257 self.assertEqual(rx[0][Ether].src, p_cust2[Ether].dst)
Neale Rannsda78f952017-05-24 09:15:43 -07002258
2259 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002260 # now a stream in each direction from each host
Neale Rannsda78f952017-05-24 09:15:43 -07002261 #
Neale Ranns1dbcf302019-07-19 11:44:53 +00002262 rx = self.send_and_expect(self.pg1, p_cust1 * NUM_PKTS, self.pg0)
2263 self.verify_capture_tunneled_ethernet(rx, p_cust1 * NUM_PKTS,
Neale Ranns31ed7442018-02-23 05:29:09 -08002264 [VppMplsLabel(42)])
Neale Rannsda78f952017-05-24 09:15:43 -07002265
Neale Ranns1dbcf302019-07-19 11:44:53 +00002266 rx = self.send_and_expect(self.pg1, p_cust2 * NUM_PKTS, self.pg0)
2267 self.verify_capture_tunneled_ethernet(rx, p_cust2 * NUM_PKTS,
2268 [VppMplsLabel(43)])
2269
2270 rx = self.send_and_expect(self.pg0, p_core1 * NUM_PKTS, self.pg1)
2271 rx = self.send_and_expect(self.pg0, p_core2 * NUM_PKTS, self.pg1)
2272
Neale Rannsda78f952017-05-24 09:15:43 -07002273 #
2274 # remove interfaces from customers bridge-domain
2275 #
Ole Troana5b2eec2019-03-11 19:23:25 +01002276 self.vapi.sw_interface_set_l2_bridge(
Neale Ranns1dbcf302019-07-19 11:44:53 +00002277 rx_sw_if_index=mpls_tun1.sw_if_index, bd_id=1, enable=0)
2278 self.vapi.sw_interface_set_l2_bridge(
2279 rx_sw_if_index=mpls_tun2.sw_if_index, bd_id=1, enable=0)
Ole Troana5b2eec2019-03-11 19:23:25 +01002280 self.vapi.sw_interface_set_l2_bridge(
2281 rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
Neale Rannsda78f952017-05-24 09:15:43 -07002282
Paul Vinciguerra80b5e4f2019-05-09 15:53:10 -04002283
Neale Ranns8fe8cc22016-11-01 10:05:08 +00002284if __name__ == '__main__':
2285 unittest.main(testRunner=VppTestRunner)