blob: d3d12cc26bb90ea7cff4685874e517002968218d [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns177bbdc2016-11-15 09:46:51 +00002
3import unittest
Neale Ranns177bbdc2016-11-15 09:46:51 +00004
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07005import scapy.compat
Neale Ranns177bbdc2016-11-15 09:46:51 +00006from scapy.packet import Raw
Klement Sekera9225dee2016-12-12 08:36:58 +01007from scapy.layers.l2 import Ether, Dot1Q, GRE
Neale Ranns177bbdc2016-11-15 09:46:51 +00008from scapy.layers.inet import IP, UDP
Klement Sekera65cc8c02016-12-18 15:49:54 +01009from scapy.layers.inet6 import IPv6
Neale Ranns177bbdc2016-11-15 09:46:51 +000010from scapy.volatile import RandMAC, RandIP
11
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080012from framework import VppTestCase, VppTestRunner
Paul Vinciguerra95c0ca42019-03-28 13:07:00 -070013from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
Neale Ranns5a8844b2019-04-16 07:15:35 +000014from vpp_gre_interface import VppGreInterface
Neale Ranns5f8f6172019-04-18 10:23:56 +000015from vpp_nhrp import VppNhrp
Paul Vinciguerraa279d9c2019-02-28 09:00:09 -080016from vpp_ip import DpoProto
Neale Ranns097fa662018-05-01 05:17:55 -070017from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
Klement Sekera9225dee2016-12-12 08:36:58 +010018from util import ppp, ppc
Neale Ranns5a8844b2019-04-16 07:15:35 +000019from vpp_papi import VppEnum
John Loa43ccae2018-02-13 17:15:23 -050020
21
Jakub Grajciarf03beca2019-05-24 08:25:03 +020022class TestGREInputNodes(VppTestCase):
23 """ GRE Input Nodes Test Case """
24
25 def setUp(self):
26 super(TestGREInputNodes, self).setUp()
27
28 # create 3 pg interfaces - set one in a non-default table.
29 self.create_pg_interfaces(range(1))
30
31 for i in self.pg_interfaces:
32 i.admin_up()
33 i.config_ip4()
34
35 def tearDown(self):
36 for i in self.pg_interfaces:
37 i.unconfig_ip4()
38 i.admin_down()
39 super(TestGREInputNodes, self).tearDown()
40
41 def test_gre_input_node(self):
42 """ GRE gre input nodes not registerd unless configured """
43 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
44 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
45 GRE())
46
47 self.pg0.add_stream(pkt)
48 self.pg_start()
49 # no tunnel created, gre-input not registered
50 err = self.statistics.get_counter(
51 '/err/ip4-input/unknown ip protocol')[0]
52 self.assertEqual(err, 1)
53 err_count = err
54
55 # create gre tunnel
56 gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
57 gre_if.add_vpp_config()
58
59 self.pg0.add_stream(pkt)
60 self.pg_start()
61 # tunnel created, gre-input registered
62 err = self.statistics.get_counter(
63 '/err/ip4-input/unknown ip protocol')[0]
64 # expect no new errors
65 self.assertEqual(err, err_count)
66
67
Neale Ranns177bbdc2016-11-15 09:46:51 +000068class TestGRE(VppTestCase):
69 """ GRE Test Case """
70
71 @classmethod
72 def setUpClass(cls):
73 super(TestGRE, cls).setUpClass()
74
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070075 @classmethod
76 def tearDownClass(cls):
77 super(TestGRE, cls).tearDownClass()
78
Neale Ranns177bbdc2016-11-15 09:46:51 +000079 def setUp(self):
80 super(TestGRE, self).setUp()
81
Ciara Loftus7eac9162016-09-30 15:47:03 +010082 # create 3 pg interfaces - set one in a non-default table.
Neale Ranns5f8f6172019-04-18 10:23:56 +000083 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -070084
85 self.tbl = VppIpTable(self, 1)
86 self.tbl.add_vpp_config()
Neale Ranns177bbdc2016-11-15 09:46:51 +000087 self.pg1.set_table_ip4(1)
Ciara Loftus7eac9162016-09-30 15:47:03 +010088
Neale Ranns177bbdc2016-11-15 09:46:51 +000089 for i in self.pg_interfaces:
90 i.admin_up()
Ciara Loftus7eac9162016-09-30 15:47:03 +010091
92 self.pg0.config_ip4()
93 self.pg0.resolve_arp()
94 self.pg1.config_ip4()
95 self.pg1.resolve_arp()
96 self.pg2.config_ip6()
97 self.pg2.resolve_ndp()
Neale Ranns5f8f6172019-04-18 10:23:56 +000098 self.pg3.config_ip4()
99 self.pg3.resolve_arp()
100 self.pg4.config_ip4()
101 self.pg4.resolve_arp()
Neale Ranns177bbdc2016-11-15 09:46:51 +0000102
103 def tearDown(self):
Neale Ranns4008ac92017-02-13 23:20:04 -0800104 for i in self.pg_interfaces:
105 i.unconfig_ip4()
106 i.unconfig_ip6()
107 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700108 self.pg1.set_table_ip4(0)
109 super(TestGRE, self).tearDown()
Neale Ranns177bbdc2016-11-15 09:46:51 +0000110
111 def create_stream_ip4(self, src_if, src_ip, dst_ip):
112 pkts = []
113 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100114 info = self.create_packet_info(src_if, src_if)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000115 payload = self.info_to_payload(info)
116 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
117 IP(src=src_ip, dst=dst_ip) /
118 UDP(sport=1234, dport=1234) /
119 Raw(payload))
120 info.data = p.copy()
121 pkts.append(p)
122 return pkts
123
Ciara Loftus7eac9162016-09-30 15:47:03 +0100124 def create_stream_ip6(self, src_if, src_ip, dst_ip):
125 pkts = []
126 for i in range(0, 257):
127 info = self.create_packet_info(src_if, src_if)
128 payload = self.info_to_payload(info)
129 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
130 IPv6(src=src_ip, 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 Ranns177bbdc2016-11-15 09:46:51 +0000137 def create_tunnel_stream_4o4(self, src_if,
138 tunnel_src, tunnel_dst,
139 src_ip, dst_ip):
140 pkts = []
141 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100142 info = self.create_packet_info(src_if, src_if)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000143 payload = self.info_to_payload(info)
144 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
145 IP(src=tunnel_src, dst=tunnel_dst) /
146 GRE() /
147 IP(src=src_ip, dst=dst_ip) /
148 UDP(sport=1234, dport=1234) /
149 Raw(payload))
150 info.data = p.copy()
151 pkts.append(p)
152 return pkts
153
154 def create_tunnel_stream_6o4(self, src_if,
155 tunnel_src, tunnel_dst,
156 src_ip, dst_ip):
157 pkts = []
158 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100159 info = self.create_packet_info(src_if, src_if)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000160 payload = self.info_to_payload(info)
161 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
162 IP(src=tunnel_src, dst=tunnel_dst) /
163 GRE() /
164 IPv6(src=src_ip, dst=dst_ip) /
165 UDP(sport=1234, dport=1234) /
166 Raw(payload))
167 info.data = p.copy()
168 pkts.append(p)
169 return pkts
170
Ciara Loftus7eac9162016-09-30 15:47:03 +0100171 def create_tunnel_stream_6o6(self, src_if,
172 tunnel_src, tunnel_dst,
173 src_ip, dst_ip):
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=tunnel_src, dst=tunnel_dst) /
180 GRE() /
181 IPv6(src=src_ip, dst=dst_ip) /
182 UDP(sport=1234, dport=1234) /
183 Raw(payload))
184 info.data = p.copy()
185 pkts.append(p)
186 return pkts
187
Neale Ranns177bbdc2016-11-15 09:46:51 +0000188 def create_tunnel_stream_l2o4(self, src_if,
189 tunnel_src, tunnel_dst):
190 pkts = []
191 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100192 info = self.create_packet_info(src_if, src_if)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000193 payload = self.info_to_payload(info)
194 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
195 IP(src=tunnel_src, dst=tunnel_dst) /
196 GRE() /
197 Ether(dst=RandMAC('*:*:*:*:*:*'),
198 src=RandMAC('*:*:*:*:*:*')) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700199 IP(src=scapy.compat.raw(RandIP()),
200 dst=scapy.compat.raw(RandIP())) /
Neale Ranns177bbdc2016-11-15 09:46:51 +0000201 UDP(sport=1234, dport=1234) /
202 Raw(payload))
203 info.data = p.copy()
204 pkts.append(p)
205 return pkts
206
207 def create_tunnel_stream_vlano4(self, src_if,
208 tunnel_src, tunnel_dst, vlan):
209 pkts = []
210 for i in range(0, 257):
Klement Sekeradab231a2016-12-21 08:50:14 +0100211 info = self.create_packet_info(src_if, src_if)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000212 payload = self.info_to_payload(info)
213 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
214 IP(src=tunnel_src, dst=tunnel_dst) /
215 GRE() /
216 Ether(dst=RandMAC('*:*:*:*:*:*'),
217 src=RandMAC('*:*:*:*:*:*')) /
218 Dot1Q(vlan=vlan) /
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700219 IP(src=scapy.compat.raw(RandIP()),
220 dst=scapy.compat.raw(RandIP())) /
Neale Ranns177bbdc2016-11-15 09:46:51 +0000221 UDP(sport=1234, dport=1234) /
222 Raw(payload))
223 info.data = p.copy()
224 pkts.append(p)
225 return pkts
226
Neale Ranns177bbdc2016-11-15 09:46:51 +0000227 def verify_tunneled_4o4(self, src_if, capture, sent,
228 tunnel_src, tunnel_dst):
229
Neale Ranns177bbdc2016-11-15 09:46:51 +0000230 self.assertEqual(len(capture), len(sent))
231
232 for i in range(len(capture)):
233 try:
234 tx = sent[i]
235 rx = capture[i]
236
237 tx_ip = tx[IP]
238 rx_ip = rx[IP]
239
240 self.assertEqual(rx_ip.src, tunnel_src)
241 self.assertEqual(rx_ip.dst, tunnel_dst)
242
243 rx_gre = rx[GRE]
244 rx_ip = rx_gre[IP]
245
246 self.assertEqual(rx_ip.src, tx_ip.src)
247 self.assertEqual(rx_ip.dst, tx_ip.dst)
248 # IP processing post pop has decremented the TTL
249 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
250
251 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100252 self.logger.error(ppp("Rx:", rx))
253 self.logger.error(ppp("Tx:", tx))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000254 raise
255
Ciara Loftus7eac9162016-09-30 15:47:03 +0100256 def verify_tunneled_6o6(self, src_if, capture, sent,
257 tunnel_src, tunnel_dst):
258
259 self.assertEqual(len(capture), len(sent))
260
261 for i in range(len(capture)):
262 try:
263 tx = sent[i]
264 rx = capture[i]
265
266 tx_ip = tx[IPv6]
267 rx_ip = rx[IPv6]
268
269 self.assertEqual(rx_ip.src, tunnel_src)
270 self.assertEqual(rx_ip.dst, tunnel_dst)
271
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700272 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
Ciara Loftus7eac9162016-09-30 15:47:03 +0100273 rx_ip = rx_gre[IPv6]
274
275 self.assertEqual(rx_ip.src, tx_ip.src)
276 self.assertEqual(rx_ip.dst, tx_ip.dst)
277
278 except:
279 self.logger.error(ppp("Rx:", rx))
280 self.logger.error(ppp("Tx:", tx))
281 raise
282
Neale Ranns2646c802018-09-19 04:55:32 -0700283 def verify_tunneled_4o6(self, src_if, capture, sent,
284 tunnel_src, tunnel_dst):
285
286 self.assertEqual(len(capture), len(sent))
287
288 for i in range(len(capture)):
289 try:
290 tx = sent[i]
291 rx = capture[i]
292
293 rx_ip = rx[IPv6]
294
295 self.assertEqual(rx_ip.src, tunnel_src)
296 self.assertEqual(rx_ip.dst, tunnel_dst)
297
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700298 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
Neale Ranns2646c802018-09-19 04:55:32 -0700299 tx_ip = tx[IP]
300 rx_ip = rx_gre[IP]
301
302 self.assertEqual(rx_ip.src, tx_ip.src)
303 self.assertEqual(rx_ip.dst, tx_ip.dst)
304
305 except:
306 self.logger.error(ppp("Rx:", rx))
307 self.logger.error(ppp("Tx:", tx))
308 raise
309
310 def verify_tunneled_6o4(self, src_if, capture, sent,
311 tunnel_src, tunnel_dst):
312
313 self.assertEqual(len(capture), len(sent))
314
315 for i in range(len(capture)):
316 try:
317 tx = sent[i]
318 rx = capture[i]
319
320 rx_ip = rx[IP]
321
322 self.assertEqual(rx_ip.src, tunnel_src)
323 self.assertEqual(rx_ip.dst, tunnel_dst)
324
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700325 rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload))
Neale Ranns2646c802018-09-19 04:55:32 -0700326 rx_ip = rx_gre[IPv6]
327 tx_ip = tx[IPv6]
328
329 self.assertEqual(rx_ip.src, tx_ip.src)
330 self.assertEqual(rx_ip.dst, tx_ip.dst)
331
332 except:
333 self.logger.error(ppp("Rx:", rx))
334 self.logger.error(ppp("Tx:", tx))
335 raise
336
Neale Ranns177bbdc2016-11-15 09:46:51 +0000337 def verify_tunneled_l2o4(self, src_if, capture, sent,
338 tunnel_src, tunnel_dst):
Neale Ranns177bbdc2016-11-15 09:46:51 +0000339 self.assertEqual(len(capture), len(sent))
340
341 for i in range(len(capture)):
342 try:
343 tx = sent[i]
344 rx = capture[i]
345
346 tx_ip = tx[IP]
347 rx_ip = rx[IP]
348
349 self.assertEqual(rx_ip.src, tunnel_src)
350 self.assertEqual(rx_ip.dst, tunnel_dst)
351
352 rx_gre = rx[GRE]
353 rx_l2 = rx_gre[Ether]
354 rx_ip = rx_l2[IP]
355 tx_gre = tx[GRE]
356 tx_l2 = tx_gre[Ether]
357 tx_ip = tx_l2[IP]
358
359 self.assertEqual(rx_ip.src, tx_ip.src)
360 self.assertEqual(rx_ip.dst, tx_ip.dst)
361 # bridged, not L3 forwarded, so no TTL decrement
362 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
363
364 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100365 self.logger.error(ppp("Rx:", rx))
366 self.logger.error(ppp("Tx:", tx))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000367 raise
368
369 def verify_tunneled_vlano4(self, src_if, capture, sent,
370 tunnel_src, tunnel_dst, vlan):
371 try:
Neale Ranns177bbdc2016-11-15 09:46:51 +0000372 self.assertEqual(len(capture), len(sent))
373 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100374 ppc("Unexpected packets captured:", capture)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000375 raise
376
377 for i in range(len(capture)):
378 try:
379 tx = sent[i]
380 rx = capture[i]
381
382 tx_ip = tx[IP]
383 rx_ip = rx[IP]
384
385 self.assertEqual(rx_ip.src, tunnel_src)
386 self.assertEqual(rx_ip.dst, tunnel_dst)
387
388 rx_gre = rx[GRE]
389 rx_l2 = rx_gre[Ether]
390 rx_vlan = rx_l2[Dot1Q]
391 rx_ip = rx_l2[IP]
392
393 self.assertEqual(rx_vlan.vlan, vlan)
394
395 tx_gre = tx[GRE]
396 tx_l2 = tx_gre[Ether]
397 tx_ip = tx_l2[IP]
398
399 self.assertEqual(rx_ip.src, tx_ip.src)
400 self.assertEqual(rx_ip.dst, tx_ip.dst)
401 # bridged, not L3 forwarded, so no TTL decrement
402 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
403
404 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100405 self.logger.error(ppp("Rx:", rx))
406 self.logger.error(ppp("Tx:", tx))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000407 raise
408
409 def verify_decapped_4o4(self, src_if, capture, sent):
Neale Ranns177bbdc2016-11-15 09:46:51 +0000410 self.assertEqual(len(capture), len(sent))
411
412 for i in range(len(capture)):
413 try:
414 tx = sent[i]
415 rx = capture[i]
416
417 tx_ip = tx[IP]
418 rx_ip = rx[IP]
419 tx_gre = tx[GRE]
420 tx_ip = tx_gre[IP]
421
422 self.assertEqual(rx_ip.src, tx_ip.src)
423 self.assertEqual(rx_ip.dst, tx_ip.dst)
424 # IP processing post pop has decremented the TTL
425 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
426
427 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100428 self.logger.error(ppp("Rx:", rx))
429 self.logger.error(ppp("Tx:", tx))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000430 raise
431
432 def verify_decapped_6o4(self, src_if, capture, sent):
Neale Ranns177bbdc2016-11-15 09:46:51 +0000433 self.assertEqual(len(capture), len(sent))
434
435 for i in range(len(capture)):
436 try:
437 tx = sent[i]
438 rx = capture[i]
439
440 tx_ip = tx[IP]
441 rx_ip = rx[IPv6]
442 tx_gre = tx[GRE]
443 tx_ip = tx_gre[IPv6]
444
445 self.assertEqual(rx_ip.src, tx_ip.src)
446 self.assertEqual(rx_ip.dst, tx_ip.dst)
447 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
448
449 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100450 self.logger.error(ppp("Rx:", rx))
451 self.logger.error(ppp("Tx:", tx))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000452 raise
453
454 def test_gre(self):
Ciara Loftus7eac9162016-09-30 15:47:03 +0100455 """ GRE IPv4 tunnel Tests """
Neale Ranns177bbdc2016-11-15 09:46:51 +0000456
457 #
458 # Create an L3 GRE tunnel.
459 # - set it admin up
460 # - assign an IP Addres
461 # - Add a route via the tunnel
462 #
463 gre_if = VppGreInterface(self,
464 self.pg0.local_ip4,
465 "1.1.1.2")
466 gre_if.add_vpp_config()
467
468 #
469 # The double create (create the same tunnel twice) should fail,
470 # and we should still be able to use the original
471 #
472 try:
473 gre_if.add_vpp_config()
474 except Exception:
475 pass
476 else:
477 self.fail("Double GRE tunnel add does not fail")
478
479 gre_if.admin_up()
480 gre_if.config_ip4()
481
Neale Ranns5a8123b2017-01-26 01:18:23 -0800482 route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
483 [VppRoutePath("0.0.0.0",
484 gre_if.sw_if_index)])
Neale Ranns177bbdc2016-11-15 09:46:51 +0000485
486 route_via_tun.add_vpp_config()
487
488 #
489 # Send a packet stream that is routed into the tunnel
Jim Thompsonf324dec2019-04-08 03:22:21 -0500490 # - they are all dropped since the tunnel's destintation IP
Neale Ranns177bbdc2016-11-15 09:46:51 +0000491 # is unresolved - or resolves via the default route - which
492 # which is a drop.
493 #
494 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
Neale Ranns177bbdc2016-11-15 09:46:51 +0000495
Neale Ranns55882252018-11-29 08:48:37 +0000496 self.send_and_assert_no_replies(self.pg0, tx)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000497
498 #
499 # Add a route that resolves the tunnel's destination
500 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800501 route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
502 [VppRoutePath(self.pg0.remote_ip4,
503 self.pg0.sw_if_index)])
Neale Ranns177bbdc2016-11-15 09:46:51 +0000504 route_tun_dst.add_vpp_config()
505
506 #
507 # Send a packet stream that is routed into the tunnel
508 # - packets are GRE encapped
509 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000510 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
Neale Ranns55882252018-11-29 08:48:37 +0000511 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000512 self.verify_tunneled_4o4(self.pg0, rx, tx,
513 self.pg0.local_ip4, "1.1.1.2")
514
515 #
516 # Send tunneled packets that match the created tunnel and
517 # are decapped and forwarded
518 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000519 tx = self.create_tunnel_stream_4o4(self.pg0,
520 "1.1.1.2",
521 self.pg0.local_ip4,
522 self.pg0.local_ip4,
523 self.pg0.remote_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000524 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000525 self.verify_decapped_4o4(self.pg0, rx, tx)
526
527 #
528 # Send tunneled packets that do not match the tunnel's src
529 #
530 self.vapi.cli("clear trace")
531 tx = self.create_tunnel_stream_4o4(self.pg0,
532 "1.1.1.3",
533 self.pg0.local_ip4,
534 self.pg0.local_ip4,
535 self.pg0.remote_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000536 self.send_and_assert_no_replies(
537 self.pg0, tx,
Klement Sekera9225dee2016-12-12 08:36:58 +0100538 remark="GRE packets forwarded despite no SRC address match")
Neale Ranns177bbdc2016-11-15 09:46:51 +0000539
540 #
541 # Configure IPv6 on the PG interface so we can route IPv6
542 # packets
543 #
544 self.pg0.config_ip6()
545 self.pg0.resolve_ndp()
546
547 #
548 # Send IPv6 tunnel encapslated packets
549 # - dropped since IPv6 is not enabled on the tunnel
550 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000551 tx = self.create_tunnel_stream_6o4(self.pg0,
552 "1.1.1.2",
553 self.pg0.local_ip4,
554 self.pg0.local_ip6,
555 self.pg0.remote_ip6)
Neale Ranns55882252018-11-29 08:48:37 +0000556 self.send_and_assert_no_replies(self.pg0, tx,
557 "IPv6 GRE packets forwarded "
558 "despite IPv6 not enabled on tunnel")
Neale Ranns177bbdc2016-11-15 09:46:51 +0000559
560 #
561 # Enable IPv6 on the tunnel
562 #
563 gre_if.config_ip6()
564
565 #
566 # Send IPv6 tunnel encapslated packets
567 # - forwarded since IPv6 is enabled on the tunnel
568 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000569 tx = self.create_tunnel_stream_6o4(self.pg0,
570 "1.1.1.2",
571 self.pg0.local_ip4,
572 self.pg0.local_ip6,
573 self.pg0.remote_ip6)
Neale Ranns55882252018-11-29 08:48:37 +0000574 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000575 self.verify_decapped_6o4(self.pg0, rx, tx)
576
577 #
Neale Ranns2646c802018-09-19 04:55:32 -0700578 # Send v6 packets for v4 encap
579 #
580 route6_via_tun = VppIpRoute(
581 self, "2001::1", 128,
582 [VppRoutePath("::",
583 gre_if.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -0700584 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns2646c802018-09-19 04:55:32 -0700585 route6_via_tun.add_vpp_config()
586
587 tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
588 rx = self.send_and_expect(self.pg0, tx, self.pg0)
589
590 self.verify_tunneled_6o4(self.pg0, rx, tx,
591 self.pg0.local_ip4, "1.1.1.2")
592
593 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000594 # test case cleanup
595 #
596 route_tun_dst.remove_vpp_config()
597 route_via_tun.remove_vpp_config()
Neale Ranns2646c802018-09-19 04:55:32 -0700598 route6_via_tun.remove_vpp_config()
Neale Ranns177bbdc2016-11-15 09:46:51 +0000599 gre_if.remove_vpp_config()
600
601 self.pg0.unconfig_ip6()
602
Ciara Loftus7eac9162016-09-30 15:47:03 +0100603 def test_gre6(self):
604 """ GRE IPv6 tunnel Tests """
605
Neale Ranns8716e6b2017-12-13 02:47:27 -0800606 self.pg1.config_ip6()
607 self.pg1.resolve_ndp()
608
Ciara Loftus7eac9162016-09-30 15:47:03 +0100609 #
610 # Create an L3 GRE tunnel.
611 # - set it admin up
612 # - assign an IP Address
613 # - Add a route via the tunnel
614 #
Neale Ranns5a8844b2019-04-16 07:15:35 +0000615 gre_if = VppGreInterface(self,
616 self.pg2.local_ip6,
617 "1002::1")
Ciara Loftus7eac9162016-09-30 15:47:03 +0100618 gre_if.add_vpp_config()
619 gre_if.admin_up()
620 gre_if.config_ip6()
621
Neale Ranns097fa662018-05-01 05:17:55 -0700622 route_via_tun = VppIpRoute(self, "4004::1", 128,
623 [VppRoutePath("0::0",
624 gre_if.sw_if_index)])
Ciara Loftus7eac9162016-09-30 15:47:03 +0100625
626 route_via_tun.add_vpp_config()
627
628 #
629 # Send a packet stream that is routed into the tunnel
Jim Thompsonf324dec2019-04-08 03:22:21 -0500630 # - they are all dropped since the tunnel's destintation IP
Ciara Loftus7eac9162016-09-30 15:47:03 +0100631 # is unresolved - or resolves via the default route - which
632 # which is a drop.
633 #
634 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
Neale Ranns55882252018-11-29 08:48:37 +0000635 self.send_and_assert_no_replies(
636 self.pg2, tx,
637 "GRE packets forwarded without DIP resolved")
Ciara Loftus7eac9162016-09-30 15:47:03 +0100638
639 #
640 # Add a route that resolves the tunnel's destination
641 #
Neale Ranns097fa662018-05-01 05:17:55 -0700642 route_tun_dst = VppIpRoute(self, "1002::1", 128,
643 [VppRoutePath(self.pg2.remote_ip6,
644 self.pg2.sw_if_index)])
Ciara Loftus7eac9162016-09-30 15:47:03 +0100645 route_tun_dst.add_vpp_config()
646
647 #
648 # Send a packet stream that is routed into the tunnel
649 # - packets are GRE encapped
650 #
Ciara Loftus7eac9162016-09-30 15:47:03 +0100651 tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
Neale Ranns55882252018-11-29 08:48:37 +0000652 rx = self.send_and_expect(self.pg2, tx, self.pg2)
Ciara Loftus7eac9162016-09-30 15:47:03 +0100653 self.verify_tunneled_6o6(self.pg2, rx, tx,
654 self.pg2.local_ip6, "1002::1")
655
656 #
Neale Ranns8716e6b2017-12-13 02:47:27 -0800657 # Test decap. decapped packets go out pg1
658 #
659 tx = self.create_tunnel_stream_6o6(self.pg2,
660 "1002::1",
661 self.pg2.local_ip6,
662 "2001::1",
663 self.pg1.remote_ip6)
Neale Ranns55882252018-11-29 08:48:37 +0000664 rx = self.send_and_expect(self.pg2, tx, self.pg1)
Neale Ranns8716e6b2017-12-13 02:47:27 -0800665
666 #
667 # RX'd packet is UDP over IPv6, test the GRE header is gone.
668 #
669 self.assertFalse(rx[0].haslayer(GRE))
670 self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
671
672 #
Neale Ranns2646c802018-09-19 04:55:32 -0700673 # Send v4 over v6
674 #
675 route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
676 [VppRoutePath("0.0.0.0",
677 gre_if.sw_if_index)])
678 route4_via_tun.add_vpp_config()
679
680 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
681 rx = self.send_and_expect(self.pg0, tx, self.pg2)
682
683 self.verify_tunneled_4o6(self.pg0, rx, tx,
684 self.pg2.local_ip6, "1002::1")
685
686 #
Ciara Loftus7eac9162016-09-30 15:47:03 +0100687 # test case cleanup
688 #
689 route_tun_dst.remove_vpp_config()
690 route_via_tun.remove_vpp_config()
Neale Ranns2646c802018-09-19 04:55:32 -0700691 route4_via_tun.remove_vpp_config()
Ciara Loftus7eac9162016-09-30 15:47:03 +0100692 gre_if.remove_vpp_config()
693
694 self.pg2.unconfig_ip6()
Neale Ranns8716e6b2017-12-13 02:47:27 -0800695 self.pg1.unconfig_ip6()
Ciara Loftus7eac9162016-09-30 15:47:03 +0100696
Neale Ranns177bbdc2016-11-15 09:46:51 +0000697 def test_gre_vrf(self):
698 """ GRE tunnel VRF Tests """
699
700 #
701 # Create an L3 GRE tunnel whose destination is in the non-default
702 # table. The underlay is thus non-default - the overlay is still
703 # the default.
704 # - set it admin up
705 # - assign an IP Addres
706 #
707 gre_if = VppGreInterface(self, self.pg1.local_ip4,
708 "2.2.2.2",
Neale Ranns5f8f6172019-04-18 10:23:56 +0000709 outer_table_id=1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000710 gre_if.add_vpp_config()
711 gre_if.admin_up()
712 gre_if.config_ip4()
713
714 #
715 # Add a route via the tunnel - in the overlay
716 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800717 route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
718 [VppRoutePath("0.0.0.0",
719 gre_if.sw_if_index)])
Neale Ranns177bbdc2016-11-15 09:46:51 +0000720 route_via_tun.add_vpp_config()
721
722 #
723 # Add a route that resolves the tunnel's destination - in the
724 # underlay table
725 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800726 route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
727 paths=[VppRoutePath(self.pg1.remote_ip4,
728 self.pg1.sw_if_index)])
Neale Ranns177bbdc2016-11-15 09:46:51 +0000729 route_tun_dst.add_vpp_config()
730
731 #
732 # Send a packet stream that is routed into the tunnel
733 # packets are sent in on pg0 which is in the default table
734 # - packets are GRE encapped
735 #
736 self.vapi.cli("clear trace")
737 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
Neale Ranns55882252018-11-29 08:48:37 +0000738 rx = self.send_and_expect(self.pg0, tx, self.pg1)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000739 self.verify_tunneled_4o4(self.pg1, rx, tx,
740 self.pg1.local_ip4, "2.2.2.2")
741
742 #
743 # Send tunneled packets that match the created tunnel and
744 # are decapped and forwarded. This tests the decap lookup
745 # does not happen in the encap table
746 #
747 self.vapi.cli("clear trace")
748 tx = self.create_tunnel_stream_4o4(self.pg1,
749 "2.2.2.2",
750 self.pg1.local_ip4,
751 self.pg0.local_ip4,
752 self.pg0.remote_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000753 rx = self.send_and_expect(self.pg1, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000754 self.verify_decapped_4o4(self.pg0, rx, tx)
755
756 #
Neale Ranns743ee3e2018-11-29 08:24:38 +0000757 # Send tunneled packets that match the created tunnel
Neale Ranns33ce60d2017-12-14 08:51:32 -0800758 # but arrive on an interface that is not in the tunnel's
Neale Ranns743ee3e2018-11-29 08:24:38 +0000759 # encap VRF, these are dropped.
760 # IP enable the interface so they aren't dropped due to
761 # IP not being enabled.
Neale Ranns33ce60d2017-12-14 08:51:32 -0800762 #
Neale Ranns743ee3e2018-11-29 08:24:38 +0000763 self.pg2.config_ip4()
Neale Ranns33ce60d2017-12-14 08:51:32 -0800764 self.vapi.cli("clear trace")
765 tx = self.create_tunnel_stream_4o4(self.pg2,
766 "2.2.2.2",
767 self.pg1.local_ip4,
768 self.pg0.local_ip4,
769 self.pg0.remote_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000770 rx = self.send_and_assert_no_replies(
771 self.pg2, tx,
772 "GRE decap packets in wrong VRF")
Neale Ranns33ce60d2017-12-14 08:51:32 -0800773
Neale Ranns743ee3e2018-11-29 08:24:38 +0000774 self.pg2.unconfig_ip4()
775
Neale Ranns33ce60d2017-12-14 08:51:32 -0800776 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000777 # test case cleanup
778 #
779 route_tun_dst.remove_vpp_config()
780 route_via_tun.remove_vpp_config()
781 gre_if.remove_vpp_config()
782
783 def test_gre_l2(self):
784 """ GRE tunnel L2 Tests """
785
786 #
787 # Add routes to resolve the tunnel destinations
788 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800789 route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
790 [VppRoutePath(self.pg0.remote_ip4,
791 self.pg0.sw_if_index)])
792 route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
793 [VppRoutePath(self.pg0.remote_ip4,
794 self.pg0.sw_if_index)])
Neale Ranns177bbdc2016-11-15 09:46:51 +0000795
796 route_tun1_dst.add_vpp_config()
797 route_tun2_dst.add_vpp_config()
798
799 #
800 # Create 2 L2 GRE tunnels and x-connect them
801 #
802 gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
803 "2.2.2.2",
Neale Ranns5a8844b2019-04-16 07:15:35 +0000804 type=(VppEnum.vl_api_gre_tunnel_type_t.
805 GRE_API_TUNNEL_TYPE_TEB))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000806 gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
807 "2.2.2.3",
Neale Ranns5a8844b2019-04-16 07:15:35 +0000808 type=(VppEnum.vl_api_gre_tunnel_type_t.
809 GRE_API_TUNNEL_TYPE_TEB))
Neale Ranns177bbdc2016-11-15 09:46:51 +0000810 gre_if1.add_vpp_config()
811 gre_if2.add_vpp_config()
812
813 gre_if1.admin_up()
814 gre_if2.admin_up()
815
816 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
817 gre_if2.sw_if_index,
818 enable=1)
819 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
820 gre_if1.sw_if_index,
821 enable=1)
822
823 #
824 # Send in tunnel encapped L2. expect out tunnel encapped L2
825 # in both directions
826 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000827 tx = self.create_tunnel_stream_l2o4(self.pg0,
828 "2.2.2.2",
829 self.pg0.local_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000830 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000831 self.verify_tunneled_l2o4(self.pg0, rx, tx,
832 self.pg0.local_ip4,
833 "2.2.2.3")
834
Neale Ranns177bbdc2016-11-15 09:46:51 +0000835 tx = self.create_tunnel_stream_l2o4(self.pg0,
836 "2.2.2.3",
837 self.pg0.local_ip4)
Neale Ranns55882252018-11-29 08:48:37 +0000838 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000839 self.verify_tunneled_l2o4(self.pg0, rx, tx,
840 self.pg0.local_ip4,
841 "2.2.2.2")
842
843 self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
844 gre_if2.sw_if_index,
845 enable=0)
846 self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
847 gre_if1.sw_if_index,
848 enable=0)
849
850 #
851 # Create a VLAN sub-interfaces on the GRE TEB interfaces
852 # then x-connect them
853 #
854 gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
855 gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
856
857 # gre_if_11.add_vpp_config()
858 # gre_if_12.add_vpp_config()
859
860 gre_if_11.admin_up()
861 gre_if_12.admin_up()
862
863 self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
864 gre_if_12.sw_if_index,
865 enable=1)
866 self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
867 gre_if_11.sw_if_index,
868 enable=1)
869
870 #
871 # Configure both to pop thier respective VLAN tags,
872 # so that during the x-coonect they will subsequently push
873 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100874 self.vapi.l2_interface_vlan_tag_rewrite(
875 sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
876 push_dot1q=12)
877 self.vapi.l2_interface_vlan_tag_rewrite(
878 sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
879 push_dot1q=11)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000880
881 #
882 # Send traffic in both directiond - expect the VLAN tags to
883 # be swapped.
884 #
Neale Ranns177bbdc2016-11-15 09:46:51 +0000885 tx = self.create_tunnel_stream_vlano4(self.pg0,
886 "2.2.2.2",
887 self.pg0.local_ip4,
888 11)
Neale Ranns55882252018-11-29 08:48:37 +0000889 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000890 self.verify_tunneled_vlano4(self.pg0, rx, tx,
891 self.pg0.local_ip4,
892 "2.2.2.3",
893 12)
894
Neale Ranns177bbdc2016-11-15 09:46:51 +0000895 tx = self.create_tunnel_stream_vlano4(self.pg0,
896 "2.2.2.3",
897 self.pg0.local_ip4,
898 12)
Neale Ranns55882252018-11-29 08:48:37 +0000899 rx = self.send_and_expect(self.pg0, tx, self.pg0)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000900 self.verify_tunneled_vlano4(self.pg0, rx, tx,
901 self.pg0.local_ip4,
902 "2.2.2.2",
903 11)
904
905 #
906 # Cleanup Test resources
907 #
908 gre_if_11.remove_vpp_config()
909 gre_if_12.remove_vpp_config()
910 gre_if1.remove_vpp_config()
911 gre_if2.remove_vpp_config()
912 route_tun1_dst.add_vpp_config()
913 route_tun2_dst.add_vpp_config()
914
Neale Ranns521a8d72018-12-06 13:46:49 +0000915 def test_gre_loop(self):
916 """ GRE tunnel loop Tests """
917
918 #
919 # Create an L3 GRE tunnel.
920 # - set it admin up
921 # - assign an IP Addres
922 #
923 gre_if = VppGreInterface(self,
924 self.pg0.local_ip4,
925 "1.1.1.2")
926 gre_if.add_vpp_config()
927 gre_if.admin_up()
928 gre_if.config_ip4()
929
930 #
931 # add a route to the tunnel's destination that points
932 # through the tunnel, hence forming a loop in the forwarding
933 # graph
934 #
935 route_dst = VppIpRoute(self, "1.1.1.2", 32,
936 [VppRoutePath("0.0.0.0",
937 gre_if.sw_if_index)])
938 route_dst.add_vpp_config()
939
940 #
941 # packets to the tunnels destination should be dropped
942 #
943 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
944 self.send_and_assert_no_replies(self.pg2, tx)
945
946 self.logger.info(self.vapi.ppcli("sh adj 7"))
947
948 #
949 # break the loop
950 #
951 route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
952 self.pg1.sw_if_index)])
953 route_dst.add_vpp_config()
954
955 rx = self.send_and_expect(self.pg0, tx, self.pg1)
956
957 #
958 # a good route throught the tunnel to check it restacked
959 #
960 route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
961 [VppRoutePath("0.0.0.0",
962 gre_if.sw_if_index)])
963 route_via_tun_2.add_vpp_config()
964
965 tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
966 rx = self.send_and_expect(self.pg0, tx, self.pg1)
967 self.verify_tunneled_4o4(self.pg1, rx, tx,
968 self.pg0.local_ip4, "1.1.1.2")
969
970 #
971 # cleanup
972 #
973 route_via_tun_2.remove_vpp_config()
974 gre_if.remove_vpp_config()
975
Neale Ranns5f8f6172019-04-18 10:23:56 +0000976 def test_mgre(self):
977 """ mGRE IPv4 tunnel Tests """
978
979 for itf in self.pg_interfaces[3:]:
980 #
981 # one underlay nh for each overlay/tunnel peer
982 #
983 itf.generate_remote_hosts(4)
984 itf.configure_ipv4_neighbors()
985
986 #
987 # Create an L3 GRE tunnel.
988 # - set it admin up
989 # - assign an IP Addres
990 # - Add a route via the tunnel
991 #
992 gre_if = VppGreInterface(self,
993 itf.local_ip4,
994 "0.0.0.0",
995 mode=(VppEnum.vl_api_gre_tunnel_mode_t.
996 GRE_API_TUNNEL_MODE_MP))
997 gre_if.add_vpp_config()
998 gre_if.admin_up()
999 gre_if.config_ip4()
1000 gre_if.generate_remote_hosts(4)
1001
1002 #
1003 # for-each peer
1004 #
1005 for ii in range(1, 4):
1006 route_addr = "4.4.4.%d" % ii
1007
1008 #
1009 # route traffic via the peer
1010 #
1011 route_via_tun = VppIpRoute(
1012 self, route_addr, 32,
1013 [VppRoutePath(gre_if._remote_hosts[ii].ip4,
1014 gre_if.sw_if_index)])
1015 route_via_tun.add_vpp_config()
1016
1017 #
1018 # Add a NHRP entry resolves the peer
1019 #
1020 nhrp = VppNhrp(self, gre_if,
1021 gre_if._remote_hosts[ii].ip4,
1022 itf._remote_hosts[ii].ip4)
1023 nhrp.add_vpp_config()
1024
1025 #
1026 # Send a packet stream that is routed into the tunnel
1027 # - packets are GRE encapped
1028 #
1029 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr)
1030 rx = self.send_and_expect(self.pg0, tx, itf)
1031 self.verify_tunneled_4o4(self.pg0, rx, tx,
1032 itf.local_ip4,
1033 gre_if._remote_hosts[ii].ip4)
1034
1035 #
1036 # delete and re-add the NHRP
1037 #
1038 nhrp.remove_vpp_config()
1039 self.send_and_assert_no_replies(self.pg0, tx)
1040
1041 nhrp.add_vpp_config()
1042 rx = self.send_and_expect(self.pg0, tx, itf)
1043 self.verify_tunneled_4o4(self.pg0, rx, tx,
1044 itf.local_ip4,
1045 gre_if._remote_hosts[ii].ip4)
1046
Neale Ranns177bbdc2016-11-15 09:46:51 +00001047
1048if __name__ == '__main__':
1049 unittest.main(testRunner=VppTestRunner)