blob: 736d8f7bc4c500ba3ac5b1f75f81d14889745594 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08002import binascii
Matej Klotton16a14cd2016-12-07 15:09:13 +01003import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02004import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01005import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02006
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07007import scapy.compat
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08008from scapy.contrib.mpls import MPLS
9from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
Neale Rannsaa7cfd02022-03-24 12:28:42 +000010from scapy.layers.inet6 import IPv6
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080011from scapy.layers.l2 import Ether, Dot1Q, ARP
12from scapy.packet import Raw
13from six import moves
14
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000015from framework import tag_fixme_vpp_workers
Damjan Marionf56b77a2016-10-03 19:44:57 +020016from framework import VppTestCase, VppTestRunner
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080017from util import ppp
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020018from vpp_ip_route import (
19 VppIpRoute,
20 VppRoutePath,
21 VppIpMRoute,
22 VppMRoutePath,
23 VppMplsIpBind,
24 VppMplsTable,
25 VppIpTable,
26 FibPathType,
27 find_route,
28 VppIpInterfaceAddress,
29 find_route_in_dump,
30 find_mroute_in_dump,
31)
Neale Ranns8f5fef22020-12-21 08:29:34 +000032from vpp_ip import VppIpPuntPolicer, VppIpPuntRedirect, VppIpPathMtu
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080033from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Klement Sekerafd1f56a2021-11-22 21:25:57 +010034from vpp_papi import vpp_papi, VppEnum
Neale Ranns0b6a8572019-10-30 17:34:14 +000035from vpp_neighbor import VppNeighbor
Neale Ranns9efcee62019-11-26 19:30:08 +000036from vpp_lo_interface import VppLoInterface
Brian Russellc8f3cdf2021-01-19 16:57:42 +000037from vpp_policer import VppPolicer, PolicerAction
Damjan Marionf56b77a2016-10-03 19:44:57 +020038
Paul Vinciguerra4271c972019-05-14 13:25:49 -040039NUM_PKTS = 67
40
Damjan Marionf56b77a2016-10-03 19:44:57 +020041
Klement Sekeraf62ae122016-10-11 11:47:09 +020042class TestIPv4(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020043 """IPv4 Test Case"""
Damjan Marionf56b77a2016-10-03 19:44:57 +020044
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070045 @classmethod
46 def setUpClass(cls):
47 super(TestIPv4, cls).setUpClass()
48
49 @classmethod
50 def tearDownClass(cls):
51 super(TestIPv4, cls).tearDownClass()
52
Klement Sekeraf62ae122016-10-11 11:47:09 +020053 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010054 """
55 Perform test setup before test case.
56
57 **Config:**
58 - create 3 pg interfaces
59 - untagged pg0 interface
60 - Dot1Q subinterface on pg1
61 - Dot1AD subinterface on pg2
62 - setup interfaces:
63 - put it into UP state
64 - set IPv4 addresses
65 - resolve neighbor address using ARP
66 - configure 200 fib entries
67
68 :ivar list interfaces: pg interfaces and subinterfaces.
69 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010070 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020071 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020072
Klement Sekeraf62ae122016-10-11 11:47:09 +020073 # create 3 pg interfaces
74 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020075
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 # create 2 subinterfaces for pg1 and pg2
77 self.sub_interfaces = [
78 VppDot1QSubint(self, self.pg1, 100),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020079 VppDot1ADSubint(self, self.pg2, 200, 300, 400),
80 ]
Damjan Marionf56b77a2016-10-03 19:44:57 +020081
Klement Sekeraf62ae122016-10-11 11:47:09 +020082 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
83 self.flows = dict()
84 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
85 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
86 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020087
Klement Sekeraf62ae122016-10-11 11:47:09 +020088 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020089 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020090
Klement Sekeraf62ae122016-10-11 11:47:09 +020091 self.interfaces = list(self.pg_interfaces)
92 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020093
Klement Sekeraf62ae122016-10-11 11:47:09 +020094 # setup all interfaces
95 for i in self.interfaces:
96 i.admin_up()
97 i.config_ip4()
98 i.resolve_arp()
99
Matej Klotton86d87c42016-11-11 11:38:55 +0100100 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200101
102 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100103 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200104 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700105
106 def show_commands_at_teardown(self):
Neale Rannscbe25aa2019-09-30 10:53:31 +0000107 self.logger.info(self.vapi.cli("show ip4 neighbors"))
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700108 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200109
Jan Geletye6c78ee2018-06-26 12:24:03 +0200110 def modify_packet(self, src_if, packet_size, pkt):
111 """Add load, set destination IP and extend packet to required packet
112 size for defined interface.
113
114 :param VppInterface src_if: Interface to create packet for.
115 :param int packet_size: Required packet size.
116 :param Scapy pkt: Packet to be modified.
117 """
Ole Troan6ed154f2019-10-15 19:31:55 +0200118 dst_if_idx = int(packet_size / 10 % 2)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200119 dst_if = self.flows[src_if][dst_if_idx]
120 info = self.create_packet_info(src_if, dst_if)
121 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200122 p = pkt / Raw(payload)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200123 p[IP].dst = dst_if.remote_ip4
124 info.data = p.copy()
125 if isinstance(src_if, VppSubInterface):
126 p = src_if.add_dot1_layer(p)
127 self.extend_packet(p, packet_size)
128
129 return p
130
131 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100132 """Create input packet stream for defined interface.
133
134 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100135 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200136 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200137 pkt_tmpl = (
138 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
139 / IP(src=src_if.remote_ip4)
140 / UDP(sport=1234, dport=1234)
141 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200142
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200143 pkts = [
144 self.modify_packet(src_if, i, pkt_tmpl)
145 for i in moves.range(
146 self.pg_if_packet_sizes[0], self.pg_if_packet_sizes[1], 10
147 )
148 ]
149 pkts_b = [
150 self.modify_packet(src_if, i, pkt_tmpl)
151 for i in moves.range(
152 self.pg_if_packet_sizes[1] + hdr_ext,
153 self.pg_if_packet_sizes[2] + hdr_ext,
154 50,
155 )
156 ]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200157 pkts.extend(pkts_b)
158
Damjan Marionf56b77a2016-10-03 19:44:57 +0200159 return pkts
160
Klement Sekeraf62ae122016-10-11 11:47:09 +0200161 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100162 """Verify captured input packet stream for defined interface.
163
164 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200165 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100166 :param list capture: Captured packet stream.
167 """
168 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200169 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200170 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200171 last_info[i.sw_if_index] = None
172 is_sub_if = False
173 dst_sw_if_index = dst_if.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200174 if hasattr(dst_if, "parent"):
Klement Sekeraf62ae122016-10-11 11:47:09 +0200175 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200176 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200177 if is_sub_if:
178 # Check VLAN tags and Ethernet header
179 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200180 self.assertTrue(Dot1Q not in packet)
181 try:
182 ip = packet[IP]
183 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800184 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200185 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200186 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100187 self.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200188 "Got packet on port %s: src=%u (id=%u)"
189 % (dst_if.name, payload_info.src, packet_index)
190 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200191 next_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200192 payload_info.src, dst_sw_if_index, last_info[payload_info.src]
193 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200194 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200195 self.assertTrue(next_info is not None)
196 self.assertEqual(packet_index, next_info.index)
197 saved_packet = next_info.data
198 # Check standard fields
199 self.assertEqual(ip.src, saved_packet[IP].src)
200 self.assertEqual(ip.dst, saved_packet[IP].dst)
201 self.assertEqual(udp.sport, saved_packet[UDP].sport)
202 self.assertEqual(udp.dport, saved_packet[UDP].dport)
203 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100204 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200205 raise
206 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200207 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200208 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index]
209 )
210 self.assertTrue(
211 remaining_packet is None,
212 "Interface %s: Packet expected from interface %s "
213 "didn't arrive" % (dst_if.name, i.name),
214 )
Damjan Marionf56b77a2016-10-03 19:44:57 +0200215
216 def test_fib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 """IPv4 FIB test
Matej Klotton86d87c42016-11-11 11:38:55 +0100218
219 Test scenario:
220
221 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200222 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100223 - Send and verify received packets on each interface.
224 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200225
Jan Geletye6c78ee2018-06-26 12:24:03 +0200226 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200227 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200228
Klement Sekeraf62ae122016-10-11 11:47:09 +0200229 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200230 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200231 i.parent.add_stream(pkts)
232
233 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200234 self.pg_start()
235
Klement Sekeraf62ae122016-10-11 11:47:09 +0200236 pkts = self.pg0.get_capture()
237 self.verify_capture(self.pg0, pkts)
238
239 for i in self.sub_interfaces:
240 pkts = i.parent.get_capture()
241 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200242
243
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400244class TestIPv4RouteLookup(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200245 """IPv4 Route Lookup Test Case"""
246
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400247 routes = []
248
249 def route_lookup(self, prefix, exact):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200250 return self.vapi.api(
251 self.vapi.papi.ip_route_lookup,
252 {
253 "table_id": 0,
254 "exact": exact,
255 "prefix": prefix,
256 },
257 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400258
259 @classmethod
260 def setUpClass(cls):
261 super(TestIPv4RouteLookup, cls).setUpClass()
262
263 @classmethod
264 def tearDownClass(cls):
265 super(TestIPv4RouteLookup, cls).tearDownClass()
266
267 def setUp(self):
268 super(TestIPv4RouteLookup, self).setUp()
269
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 drop_nh = VppRoutePath(
271 "127.0.0.1", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP
272 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400273
274 # Add 3 routes
275 r = VppIpRoute(self, "1.1.0.0", 16, [drop_nh])
276 r.add_vpp_config()
277 self.routes.append(r)
278
279 r = VppIpRoute(self, "1.1.1.0", 24, [drop_nh])
280 r.add_vpp_config()
281 self.routes.append(r)
282
283 r = VppIpRoute(self, "1.1.1.1", 32, [drop_nh])
284 r.add_vpp_config()
285 self.routes.append(r)
286
287 def tearDown(self):
288 # Remove the routes we added
289 for r in self.routes:
290 r.remove_vpp_config()
291
292 super(TestIPv4RouteLookup, self).tearDown()
293
294 def test_exact_match(self):
295 # Verify we find the host route
296 prefix = "1.1.1.1/32"
297 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200298 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400299
300 # Verify we find a middle prefix route
301 prefix = "1.1.1.0/24"
302 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400304
305 # Verify we do not find an available LPM.
306 with self.vapi.assert_negative_api_retval():
307 self.route_lookup("1.1.1.2/32", True)
308
309 def test_longest_prefix_match(self):
310 # verify we find lpm
311 lpm_prefix = "1.1.1.0/24"
312 result = self.route_lookup("1.1.1.2/32", False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200313 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400314
315 # Verify we find the exact when not requested
316 result = self.route_lookup(lpm_prefix, False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200317 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400318
319 # Can't seem to delete the default route so no negative LPM test.
320
321
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500322class TestIPv4IfAddrRoute(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200323 """IPv4 Interface Addr Route Test Case"""
Matthew G Smith88d29a92019-07-17 10:01:17 -0500324
325 @classmethod
326 def setUpClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500327 super(TestIPv4IfAddrRoute, cls).setUpClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500328
329 @classmethod
330 def tearDownClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500331 super(TestIPv4IfAddrRoute, cls).tearDownClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500332
333 def setUp(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500334 super(TestIPv4IfAddrRoute, self).setUp()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500335
336 # create 1 pg interface
337 self.create_pg_interfaces(range(1))
338
339 for i in self.pg_interfaces:
340 i.admin_up()
341 i.config_ip4()
342 i.resolve_arp()
343
344 def tearDown(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500345 super(TestIPv4IfAddrRoute, self).tearDown()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500346 for i in self.pg_interfaces:
347 i.unconfig_ip4()
348 i.admin_down()
349
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500350 def test_ipv4_ifaddrs_same_prefix(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200351 """IPv4 Interface Addresses Same Prefix test
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500352
353 Test scenario:
354
355 - Verify no route in FIB for prefix 10.10.10.0/24
356 - Configure IPv4 address 10.10.10.10/24 on an interface
357 - Verify route in FIB for prefix 10.10.10.0/24
358 - Configure IPv4 address 10.10.10.20/24 on an interface
359 - Delete 10.10.10.10/24 from interface
360 - Verify route in FIB for prefix 10.10.10.0/24
361 - Delete 10.10.10.20/24 from interface
362 - Verify no route in FIB for prefix 10.10.10.0/24
363 """
364
365 # create two addresses, verify route not present
Neale Rannsefd7bc22019-11-11 08:32:34 +0000366 if_addr1 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.10", 24)
367 if_addr2 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.20", 24)
368 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500369 self.assertFalse(find_route(self, "10.10.10.10", 32))
370 self.assertFalse(find_route(self, "10.10.10.20", 32))
371 self.assertFalse(find_route(self, "10.10.10.255", 32))
372 self.assertFalse(find_route(self, "10.10.10.0", 32))
373
374 # configure first address, verify route present
375 if_addr1.add_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000376 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500377 self.assertTrue(find_route(self, "10.10.10.10", 32))
378 self.assertFalse(find_route(self, "10.10.10.20", 32))
379 self.assertTrue(find_route(self, "10.10.10.255", 32))
380 self.assertTrue(find_route(self, "10.10.10.0", 32))
381
382 # configure second address, delete first, verify route not removed
383 if_addr2.add_vpp_config()
384 if_addr1.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000385 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
386 self.assertTrue(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500387 self.assertFalse(find_route(self, "10.10.10.10", 32))
388 self.assertTrue(find_route(self, "10.10.10.20", 32))
389 self.assertTrue(find_route(self, "10.10.10.255", 32))
390 self.assertTrue(find_route(self, "10.10.10.0", 32))
391
392 # delete second address, verify route removed
393 if_addr2.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000394 self.assertFalse(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500395 self.assertFalse(find_route(self, "10.10.10.10", 32))
396 self.assertFalse(find_route(self, "10.10.10.20", 32))
397 self.assertFalse(find_route(self, "10.10.10.255", 32))
398 self.assertFalse(find_route(self, "10.10.10.0", 32))
399
Matthew G Smith88d29a92019-07-17 10:01:17 -0500400 def test_ipv4_ifaddr_route(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 """IPv4 Interface Address Route test
Matthew G Smith88d29a92019-07-17 10:01:17 -0500402
403 Test scenario:
404
405 - Create loopback
406 - Configure IPv4 address on loopback
407 - Verify that address is not in the FIB
408 - Bring loopback up
409 - Verify that address is in the FIB now
410 - Bring loopback down
411 - Verify that address is not in the FIB anymore
412 - Bring loopback up
413 - Configure IPv4 address on loopback
414 - Verify that address is in the FIB now
415 """
416
417 # create a loopback and configure IPv4
418 loopbacks = self.create_loopback_interfaces(1)
419 lo_if = self.lo_interfaces[0]
420
421 lo_if.local_ip4_prefix_len = 32
422 lo_if.config_ip4()
423
424 # The intf was down when addr was added -> entry not in FIB
425 fib4_dump = self.vapi.ip_route_dump(0)
426 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
427
428 # When intf is brought up, entry is added
429 lo_if.admin_up()
430 fib4_dump = self.vapi.ip_route_dump(0)
431 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
432
433 # When intf is brought down, entry is removed
434 lo_if.admin_down()
435 fib4_dump = self.vapi.ip_route_dump(0)
436 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
437
438 # Remove addr, bring up interface, re-add -> entry in FIB
439 lo_if.unconfig_ip4()
440 lo_if.admin_up()
441 lo_if.config_ip4()
442 fib4_dump = self.vapi.ip_route_dump(0)
443 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
444
yedgdbd366b2020-05-14 10:51:53 +0800445 def test_ipv4_ifaddr_del(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200446 """Delete an interface address that does not exist"""
yedgdbd366b2020-05-14 10:51:53 +0800447
448 loopbacks = self.create_loopback_interfaces(1)
449 lo = self.lo_interfaces[0]
450
451 lo.config_ip4()
452 lo.admin_up()
453
454 #
455 # try and remove pg0's subnet from lo
456 #
457 with self.vapi.assert_negative_api_retval():
458 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 sw_if_index=lo.sw_if_index, prefix=self.pg0.local_ip4_prefix, is_add=0
460 )
yedgdbd366b2020-05-14 10:51:53 +0800461
Matthew G Smith88d29a92019-07-17 10:01:17 -0500462
Jan Geletye6c78ee2018-06-26 12:24:03 +0200463class TestICMPEcho(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 """ICMP Echo Test Case"""
Jan Geletye6c78ee2018-06-26 12:24:03 +0200465
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700466 @classmethod
467 def setUpClass(cls):
468 super(TestICMPEcho, cls).setUpClass()
469
470 @classmethod
471 def tearDownClass(cls):
472 super(TestICMPEcho, cls).tearDownClass()
473
Jan Geletye6c78ee2018-06-26 12:24:03 +0200474 def setUp(self):
475 super(TestICMPEcho, self).setUp()
476
477 # create 1 pg interface
478 self.create_pg_interfaces(range(1))
479
480 for i in self.pg_interfaces:
481 i.admin_up()
482 i.config_ip4()
483 i.resolve_arp()
484
485 def tearDown(self):
486 super(TestICMPEcho, self).tearDown()
487 for i in self.pg_interfaces:
488 i.unconfig_ip4()
489 i.admin_down()
490
491 def test_icmp_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200492 """VPP replies to ICMP Echo Request
Jan Geletye6c78ee2018-06-26 12:24:03 +0200493
494 Test scenario:
495
496 - Receive ICMP Echo Request message on pg0 interface.
497 - Check outgoing ICMP Echo Reply message on pg0 interface.
498 """
499
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200500 icmp_id = 0xB
Jan Geletye6c78ee2018-06-26 12:24:03 +0200501 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200502 icmp_load = b"\x0a" * 18
503 p_echo_request = (
504 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
505 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
506 / ICMP(id=icmp_id, seq=icmp_seq)
507 / Raw(load=icmp_load)
508 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200509
510 self.pg0.add_stream(p_echo_request)
511 self.pg_enable_capture(self.pg_interfaces)
512 self.pg_start()
513
514 rx = self.pg0.get_capture(1)
515 rx = rx[0]
516 ether = rx[Ether]
517 ipv4 = rx[IP]
518 icmp = rx[ICMP]
519
520 self.assertEqual(ether.src, self.pg0.local_mac)
521 self.assertEqual(ether.dst, self.pg0.remote_mac)
522
523 self.assertEqual(ipv4.src, self.pg0.local_ip4)
524 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
525
526 self.assertEqual(icmptypes[icmp.type], "echo-reply")
527 self.assertEqual(icmp.id, icmp_id)
528 self.assertEqual(icmp.seq, icmp_seq)
529 self.assertEqual(icmp[Raw].load, icmp_load)
530
531
Matej Klotton16a14cd2016-12-07 15:09:13 +0100532class TestIPv4FibCrud(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200533 """FIB - add/update/delete - ip4 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100534
535 Test scenario:
536 - add 1k,
537 - del 100,
538 - add new 1k,
539 - del 1.5k
540
Klement Sekerada505f62017-01-04 12:58:53 +0100541 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100542 """
543
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200544 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100545 """
546
547 :param start_dest_addr:
548 :param next_hop_addr:
549 :param count:
550 :return list: added ips with 32 prefix
551 """
Neale Ranns097fa662018-05-01 05:17:55 -0700552 routes = []
553 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200554 r = VppIpRoute(
555 self,
556 start_dest_addr % (i + start),
557 32,
558 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
559 )
Neale Ranns097fa662018-05-01 05:17:55 -0700560 r.add_vpp_config()
561 routes.append(r)
562 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100563
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200564 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100565
Neale Ranns097fa662018-05-01 05:17:55 -0700566 routes = []
567 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200568 r = VppIpRoute(
569 self,
570 start_dest_addr % (i + start),
571 32,
572 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
573 )
Neale Ranns097fa662018-05-01 05:17:55 -0700574 r.remove_vpp_config()
575 routes.append(r)
576 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100577
Neale Ranns097fa662018-05-01 05:17:55 -0700578 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100579 pkts = []
580
581 for _ in range(count):
Neale Rannsefd7bc22019-11-11 08:32:34 +0000582 dst_addr = random.choice(routes).prefix.network_address
Klement Sekeradab231a2016-12-21 08:50:14 +0100583 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100584 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200585 p = (
586 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
587 / IP(src=src_if.remote_ip4, dst=str(dst_addr))
588 / UDP(sport=1234, dport=1234)
589 / Raw(payload)
590 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100591 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100592 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
593 pkts.append(p)
594
595 return pkts
596
597 def _find_ip_match(self, find_in, pkt):
598 for p in find_in:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200599 if self.payload_to_info(p[Raw]) == self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100600 if p[IP].src != pkt[IP].src:
601 break
602 if p[IP].dst != pkt[IP].dst:
603 break
604 if p[UDP].sport != pkt[UDP].sport:
605 break
606 if p[UDP].dport != pkt[UDP].dport:
607 break
608 return p
609 return None
610
Matej Klotton16a14cd2016-12-07 15:09:13 +0100611 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
612 self.assertEqual(len(received_pkts), len(expected_pkts))
613 to_verify = list(expected_pkts)
614 for p in received_pkts:
615 self.assertEqual(p.src, dst_interface.local_mac)
616 self.assertEqual(p.dst, dst_interface.remote_mac)
617 x = self._find_ip_match(to_verify, p)
618 to_verify.remove(x)
619 self.assertListEqual(to_verify, [])
620
Neale Ranns097fa662018-05-01 05:17:55 -0700621 def verify_route_dump(self, routes):
622 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200623 self.assertTrue(
624 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
625 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100626
Neale Ranns097fa662018-05-01 05:17:55 -0700627 def verify_not_in_route_dump(self, routes):
628 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200629 self.assertFalse(
630 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
631 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100632
633 @classmethod
634 def setUpClass(cls):
635 """
636 #. Create and initialize 3 pg interfaces.
637 #. initialize class attributes configured_routes and deleted_routes
638 to store information between tests.
639 """
640 super(TestIPv4FibCrud, cls).setUpClass()
641
642 try:
643 # create 3 pg interfaces
644 cls.create_pg_interfaces(range(3))
645
646 cls.interfaces = list(cls.pg_interfaces)
647
648 # setup all interfaces
649 for i in cls.interfaces:
650 i.admin_up()
651 i.config_ip4()
652 i.resolve_arp()
653
654 cls.configured_routes = []
655 cls.deleted_routes = []
656 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
657
658 except Exception:
659 super(TestIPv4FibCrud, cls).tearDownClass()
660 raise
661
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700662 @classmethod
663 def tearDownClass(cls):
664 super(TestIPv4FibCrud, cls).tearDownClass()
665
Matej Klotton16a14cd2016-12-07 15:09:13 +0100666 def setUp(self):
667 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100668 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100669
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800670 self.configured_routes = []
671 self.deleted_routes = []
672
Matej Klotton16a14cd2016-12-07 15:09:13 +0100673 def test_1_add_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200674 """Add 1k routes"""
Matej Klotton16a14cd2016-12-07 15:09:13 +0100675
Neale Ranns097fa662018-05-01 05:17:55 -0700676 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200677 self.configured_routes.extend(
678 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
679 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100680
Neale Ranns097fa662018-05-01 05:17:55 -0700681 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100682
683 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200684 self.pg1, self.pg0, self.configured_routes, 100
685 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100686 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200687 self.pg2, self.pg0, self.configured_routes, 100
688 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100689 self.pg1.add_stream(self.stream_1)
690 self.pg2.add_stream(self.stream_2)
691
692 self.pg_enable_capture(self.pg_interfaces)
693 self.pg_start()
694
Klement Sekeradab231a2016-12-21 08:50:14 +0100695 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100696 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
697
Matej Klotton16a14cd2016-12-07 15:09:13 +0100698 def test_2_del_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200699 """Delete 100 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100700
701 - delete 10 routes check with traffic script.
702 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800703 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200704 self.configured_routes.extend(
705 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
706 )
707 self.deleted_routes.extend(
708 self.unconfig_fib_many_to_one(
709 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
710 )
711 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100712 for x in self.deleted_routes:
713 self.configured_routes.remove(x)
714
Neale Ranns097fa662018-05-01 05:17:55 -0700715 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100716
717 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200718 self.pg1, self.pg0, self.configured_routes, 100
719 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100720 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200721 self.pg2, self.pg0, self.configured_routes, 100
722 )
723 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
724 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100725 self.pg1.add_stream(self.stream_1 + self.stream_3)
726 self.pg2.add_stream(self.stream_2 + self.stream_4)
727 self.pg_enable_capture(self.pg_interfaces)
728 self.pg_start()
729
Klement Sekeradab231a2016-12-21 08:50:14 +0100730 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100731 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
732
733 def test_3_add_new_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200734 """Add 1k routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100735
736 - re-add 5 routes check with traffic script.
737 - add 100 routes check with traffic script.
738 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800739 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200740 self.configured_routes.extend(
741 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
742 )
743 self.deleted_routes.extend(
744 self.unconfig_fib_many_to_one(
745 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
746 )
747 )
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800748 for x in self.deleted_routes:
749 self.configured_routes.remove(x)
750
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200751 tmp = self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 5, start=10)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100752 self.configured_routes.extend(tmp)
753 for x in tmp:
754 self.deleted_routes.remove(x)
755
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200756 self.configured_routes.extend(
757 self.config_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
758 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100759
Neale Ranns097fa662018-05-01 05:17:55 -0700760 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100761
762 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200763 self.pg1, self.pg0, self.configured_routes, 300
764 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100765 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200766 self.pg2, self.pg0, self.configured_routes, 300
767 )
768 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
769 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100770
771 self.pg1.add_stream(self.stream_1 + self.stream_3)
772 self.pg2.add_stream(self.stream_2 + self.stream_4)
773 self.pg_enable_capture(self.pg_interfaces)
774 self.pg_start()
775
Klement Sekeradab231a2016-12-21 08:50:14 +0100776 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100777 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
778
Neale Ranns097fa662018-05-01 05:17:55 -0700779 # delete 5 routes check with traffic script.
780 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200781 self.deleted_routes.extend(
782 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 15)
783 )
784 self.deleted_routes.extend(
785 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 85)
786 )
787 self.deleted_routes.extend(
788 self.unconfig_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
789 )
Neale Ranns097fa662018-05-01 05:17:55 -0700790 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100791
792
Neale Ranns37be7362017-02-21 17:30:26 -0800793class TestIPNull(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200794 """IPv4 routes via NULL"""
Neale Ranns37be7362017-02-21 17:30:26 -0800795
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700796 @classmethod
797 def setUpClass(cls):
798 super(TestIPNull, cls).setUpClass()
799
800 @classmethod
801 def tearDownClass(cls):
802 super(TestIPNull, cls).tearDownClass()
803
Neale Ranns37be7362017-02-21 17:30:26 -0800804 def setUp(self):
805 super(TestIPNull, self).setUp()
806
807 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700808 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800809
810 for i in self.pg_interfaces:
811 i.admin_up()
812 i.config_ip4()
813 i.resolve_arp()
814
815 def tearDown(self):
816 super(TestIPNull, self).tearDown()
817 for i in self.pg_interfaces:
818 i.unconfig_ip4()
819 i.admin_down()
820
821 def test_ip_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200822 """IP NULL route"""
Neale Ranns37be7362017-02-21 17:30:26 -0800823
824 #
825 # A route via IP NULL that will reply with ICMP unreachables
826 #
Neale Ranns097fa662018-05-01 05:17:55 -0700827 ip_unreach = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200828 self,
829 "10.0.0.1",
830 32,
831 [
832 VppRoutePath(
833 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH
834 )
835 ],
836 )
Neale Ranns37be7362017-02-21 17:30:26 -0800837 ip_unreach.add_vpp_config()
838
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200839 p_unreach = (
840 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
841 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
842 / UDP(sport=1234, dport=1234)
843 / Raw(b"\xa5" * 100)
844 )
Neale Ranns37be7362017-02-21 17:30:26 -0800845 self.pg0.add_stream(p_unreach)
846 self.pg_enable_capture(self.pg_interfaces)
847 self.pg_start()
848
849 rx = self.pg0.get_capture(1)
850 rx = rx[0]
851 icmp = rx[ICMP]
852
853 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
854 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
855 self.assertEqual(icmp.src, self.pg0.remote_ip4)
856 self.assertEqual(icmp.dst, "10.0.0.1")
857
858 #
859 # ICMP replies are rate limited. so sit and spin.
860 #
861 self.sleep(1)
862
863 #
864 # A route via IP NULL that will reply with ICMP prohibited
865 #
Neale Ranns097fa662018-05-01 05:17:55 -0700866 ip_prohibit = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200867 self,
868 "10.0.0.2",
869 32,
870 [
871 VppRoutePath(
872 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT
873 )
874 ],
875 )
Neale Ranns37be7362017-02-21 17:30:26 -0800876 ip_prohibit.add_vpp_config()
877
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200878 p_prohibit = (
879 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
880 / IP(src=self.pg0.remote_ip4, dst="10.0.0.2")
881 / UDP(sport=1234, dport=1234)
882 / Raw(b"\xa5" * 100)
883 )
Neale Ranns37be7362017-02-21 17:30:26 -0800884
885 self.pg0.add_stream(p_prohibit)
886 self.pg_enable_capture(self.pg_interfaces)
887 self.pg_start()
888
889 rx = self.pg0.get_capture(1)
890
891 rx = rx[0]
892 icmp = rx[ICMP]
893
894 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
895 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
896 self.assertEqual(icmp.src, self.pg0.remote_ip4)
897 self.assertEqual(icmp.dst, "10.0.0.2")
898
Neale Ranns3b93be52018-09-07 01:48:54 -0700899 def test_ip_drop(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200900 """IP Drop Routes"""
Neale Ranns3b93be52018-09-07 01:48:54 -0700901
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200902 p = (
903 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
904 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
905 / UDP(sport=1234, dport=1234)
906 / Raw(b"\xa5" * 100)
907 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700908
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200909 r1 = VppIpRoute(
910 self,
911 "1.1.1.0",
912 24,
913 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
914 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700915 r1.add_vpp_config()
916
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400917 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700918
919 #
920 # insert a more specific as a drop
921 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200922 r2 = VppIpRoute(
923 self,
924 "1.1.1.1",
925 32,
926 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP)],
927 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700928 r2.add_vpp_config()
929
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400930 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700931 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400932 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700933
Neale Ranns37be7362017-02-21 17:30:26 -0800934
Neale Ranns180279b2017-03-16 15:49:09 -0400935class TestIPDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200936 """IPv4 disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -0400937
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700938 @classmethod
939 def setUpClass(cls):
940 super(TestIPDisabled, cls).setUpClass()
941
942 @classmethod
943 def tearDownClass(cls):
944 super(TestIPDisabled, cls).tearDownClass()
945
Neale Ranns180279b2017-03-16 15:49:09 -0400946 def setUp(self):
947 super(TestIPDisabled, self).setUp()
948
949 # create 2 pg interfaces
950 self.create_pg_interfaces(range(2))
951
952 # PG0 is IP enalbed
953 self.pg0.admin_up()
954 self.pg0.config_ip4()
955 self.pg0.resolve_arp()
956
957 # PG 1 is not IP enabled
958 self.pg1.admin_up()
959
960 def tearDown(self):
961 super(TestIPDisabled, self).tearDown()
962 for i in self.pg_interfaces:
963 i.unconfig_ip4()
964 i.admin_down()
965
Neale Ranns180279b2017-03-16 15:49:09 -0400966 def test_ip_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200967 """IP Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -0400968
Neale Ranns990f6942020-10-20 07:20:17 +0000969 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
970 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
971
Neale Ranns180279b2017-03-16 15:49:09 -0400972 #
973 # An (S,G).
974 # one accepting interface, pg0, 2 forwarding interfaces
975 #
976 route_232_1_1_1 = VppIpMRoute(
977 self,
978 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200979 "232.1.1.1",
980 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000981 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200982 [
983 VppMRoutePath(
984 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
985 ),
986 VppMRoutePath(
987 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
988 ),
989 ],
990 )
Neale Ranns180279b2017-03-16 15:49:09 -0400991 route_232_1_1_1.add_vpp_config()
992
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200993 pu = (
994 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
995 / IP(src="10.10.10.10", dst=self.pg0.remote_ip4)
996 / UDP(sport=1234, dport=1234)
997 / Raw(b"\xa5" * 100)
998 )
999 pm = (
1000 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1001 / IP(src="10.10.10.10", dst="232.1.1.1")
1002 / UDP(sport=1234, dport=1234)
1003 / Raw(b"\xa5" * 100)
1004 )
Neale Ranns180279b2017-03-16 15:49:09 -04001005
1006 #
1007 # PG1 does not forward IP traffic
1008 #
1009 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1010 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1011
1012 #
1013 # IP enable PG1
1014 #
1015 self.pg1.config_ip4()
1016
1017 #
1018 # Now we get packets through
1019 #
1020 self.pg1.add_stream(pu)
1021 self.pg_enable_capture(self.pg_interfaces)
1022 self.pg_start()
1023 rx = self.pg0.get_capture(1)
1024
1025 self.pg1.add_stream(pm)
1026 self.pg_enable_capture(self.pg_interfaces)
1027 self.pg_start()
1028 rx = self.pg0.get_capture(1)
1029
1030 #
1031 # Disable PG1
1032 #
1033 self.pg1.unconfig_ip4()
1034
1035 #
1036 # PG1 does not forward IP traffic
1037 #
1038 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1039 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1040
1041
Neale Ranns9a69a602017-03-26 10:56:33 -07001042class TestIPSubNets(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001043 """IPv4 Subnets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001044
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001045 @classmethod
1046 def setUpClass(cls):
1047 super(TestIPSubNets, cls).setUpClass()
1048
1049 @classmethod
1050 def tearDownClass(cls):
1051 super(TestIPSubNets, cls).tearDownClass()
1052
Neale Ranns9a69a602017-03-26 10:56:33 -07001053 def setUp(self):
1054 super(TestIPSubNets, self).setUp()
1055
1056 # create a 2 pg interfaces
1057 self.create_pg_interfaces(range(2))
1058
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001059 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -07001060 self.pg0.admin_up()
1061
1062 # pg1 is setup normally
1063 self.pg1.admin_up()
1064 self.pg1.config_ip4()
1065 self.pg1.resolve_arp()
1066
1067 def tearDown(self):
1068 super(TestIPSubNets, self).tearDown()
1069 for i in self.pg_interfaces:
1070 i.admin_down()
1071
Neale Ranns9a69a602017-03-26 10:56:33 -07001072 def test_ip_sub_nets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001073 """IP Sub Nets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001074
1075 #
1076 # Configure a covering route to forward so we know
1077 # when we are dropping
1078 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001079 cover_route = VppIpRoute(
1080 self,
1081 "10.0.0.0",
1082 8,
1083 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1084 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001085 cover_route.add_vpp_config()
1086
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001087 p = (
1088 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1089 / IP(dst="10.10.10.10", src=self.pg0.local_ip4)
1090 / UDP(sport=1234, dport=1234)
1091 / Raw(b"\xa5" * 100)
1092 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001093
1094 self.pg1.add_stream(p)
1095 self.pg_enable_capture(self.pg_interfaces)
1096 self.pg_start()
1097 rx = self.pg1.get_capture(1)
1098
1099 #
1100 # Configure some non-/24 subnets on an IP interface
1101 #
1102 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1103
Ole Troan9a475372019-03-05 16:58:24 +01001104 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001105 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16"
1106 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001107
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001108 pn = (
1109 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1110 / IP(dst="10.10.0.0", src=self.pg0.local_ip4)
1111 / UDP(sport=1234, dport=1234)
1112 / Raw(b"\xa5" * 100)
1113 )
1114 pb = (
1115 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1116 / IP(dst="10.10.255.255", src=self.pg0.local_ip4)
1117 / UDP(sport=1234, dport=1234)
1118 / Raw(b"\xa5" * 100)
1119 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001120
1121 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
1122 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
1123
1124 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001125 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001126 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16", is_add=0
1127 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001128
Neale Ranns9a69a602017-03-26 10:56:33 -07001129 self.pg1.add_stream(pn)
1130 self.pg_enable_capture(self.pg_interfaces)
1131 self.pg_start()
1132 rx = self.pg1.get_capture(1)
1133 self.pg1.add_stream(pb)
1134 self.pg_enable_capture(self.pg_interfaces)
1135 self.pg_start()
1136 rx = self.pg1.get_capture(1)
1137
1138 #
1139 # A /31 is a special case where the 'other-side' is an attached host
1140 # packets to that peer generate ARP requests
1141 #
1142 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1143
Ole Troan9a475372019-03-05 16:58:24 +01001144 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001145 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31"
1146 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001147
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001148 pn = (
1149 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1150 / IP(dst="10.10.10.11", src=self.pg0.local_ip4)
1151 / UDP(sport=1234, dport=1234)
1152 / Raw(b"\xa5" * 100)
1153 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001154
1155 self.pg1.add_stream(pn)
1156 self.pg_enable_capture(self.pg_interfaces)
1157 self.pg_start()
1158 rx = self.pg0.get_capture(1)
1159 rx[ARP]
1160
1161 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001162 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001163 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31", is_add=0
1164 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001165
Neale Ranns9a69a602017-03-26 10:56:33 -07001166 self.pg1.add_stream(pn)
1167 self.pg_enable_capture(self.pg_interfaces)
1168 self.pg_start()
1169 rx = self.pg1.get_capture(1)
1170
1171
Neale Ranns227038a2017-04-21 01:07:59 -07001172class TestIPLoadBalance(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001173 """IPv4 Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001174
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001175 @classmethod
1176 def setUpClass(cls):
1177 super(TestIPLoadBalance, cls).setUpClass()
1178
1179 @classmethod
1180 def tearDownClass(cls):
1181 super(TestIPLoadBalance, cls).tearDownClass()
1182
Neale Ranns227038a2017-04-21 01:07:59 -07001183 def setUp(self):
1184 super(TestIPLoadBalance, self).setUp()
1185
1186 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -07001187 mpls_tbl = VppMplsTable(self, 0)
1188 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -07001189
1190 for i in self.pg_interfaces:
1191 i.admin_up()
1192 i.config_ip4()
1193 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -07001194 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001195
1196 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -07001197 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -07001198 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001199 i.unconfig_ip4()
1200 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001201 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -07001202
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001203 def total_len(self, rxs):
1204 n = 0
1205 for rx in rxs:
1206 n += len(rx)
1207 return n
1208
Neale Ranns227038a2017-04-21 01:07:59 -07001209 def test_ip_load_balance(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001210 """IP Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001211
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001212 fhc = VppEnum.vl_api_ip_flow_hash_config_t
1213 af = VppEnum.vl_api_address_family_t
1214
Neale Ranns227038a2017-04-21 01:07:59 -07001215 #
1216 # An array of packets that differ only in the destination port
1217 #
Neale Ranns71275e32017-05-25 12:38:58 -07001218 port_ip_pkts = []
1219 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001220
1221 #
1222 # An array of packets that differ only in the source address
1223 #
Neale Ranns71275e32017-05-25 12:38:58 -07001224 src_ip_pkts = []
1225 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001226
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001227 for ii in range(NUM_PKTS):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001228 port_ip_hdr = (
1229 IP(dst="10.0.0.1", src="20.0.0.1")
1230 / UDP(sport=1234, dport=1234 + ii)
1231 / Raw(b"\xa5" * 100)
1232 )
1233 port_ip_pkts.append(
1234 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)
1235 )
1236 port_mpls_pkts.append(
1237 (
1238 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1239 / MPLS(label=66, ttl=2)
1240 / port_ip_hdr
1241 )
1242 )
Neale Ranns71275e32017-05-25 12:38:58 -07001243
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001244 src_ip_hdr = (
1245 IP(dst="10.0.0.1", src="20.0.0.%d" % ii)
1246 / UDP(sport=1234, dport=1234)
1247 / Raw(b"\xa5" * 100)
1248 )
1249 src_ip_pkts.append(
1250 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)
1251 )
1252 src_mpls_pkts.append(
1253 (
1254 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1255 / MPLS(label=66, ttl=2)
1256 / src_ip_hdr
1257 )
1258 )
Neale Ranns227038a2017-04-21 01:07:59 -07001259
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001260 route_10_0_0_1 = VppIpRoute(
1261 self,
1262 "10.0.0.1",
1263 32,
1264 [
1265 VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index),
1266 VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index),
1267 ],
1268 )
Neale Ranns227038a2017-04-21 01:07:59 -07001269 route_10_0_0_1.add_vpp_config()
1270
Neale Ranns71275e32017-05-25 12:38:58 -07001271 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1272 binding.add_vpp_config()
1273
Neale Ranns227038a2017-04-21 01:07:59 -07001274 #
1275 # inject the packet on pg0 - expect load-balancing across the 2 paths
1276 # - since the default hash config is to use IP src,dst and port
1277 # src,dst
1278 # We are not going to ensure equal amounts of packets across each link,
1279 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001280 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001281 # balancing. So instead just ensure there is traffic on each link.
1282 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001283 rx = self.send_and_expect_load_balancing(
1284 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1285 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001286 n_ip_pg0 = len(rx[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001287 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1288 self.send_and_expect_load_balancing(
1289 self.pg0, port_mpls_pkts, [self.pg1, self.pg2]
1290 )
1291 rx = self.send_and_expect_load_balancing(
1292 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1293 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001294 n_mpls_pg0 = len(rx[0])
1295
1296 #
1297 # change the router ID and expect the distribution changes
1298 #
1299 self.vapi.set_ip_flow_hash_router_id(router_id=0x11111111)
1300
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001301 rx = self.send_and_expect_load_balancing(
1302 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1303 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001304 self.assertNotEqual(n_ip_pg0, len(rx[0]))
1305
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001306 rx = self.send_and_expect_load_balancing(
1307 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1308 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001309 self.assertNotEqual(n_mpls_pg0, len(rx[0]))
Neale Ranns227038a2017-04-21 01:07:59 -07001310
1311 #
1312 # change the flow hash config so it's only IP src,dst
1313 # - now only the stream with differing source address will
1314 # load-balance
1315 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001316 self.vapi.set_ip_flow_hash_v2(
1317 af=af.ADDRESS_IP4,
1318 table_id=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001319 flow_hash_config=(
1320 fhc.IP_API_FLOW_HASH_SRC_IP
1321 | fhc.IP_API_FLOW_HASH_DST_IP
1322 | fhc.IP_API_FLOW_HASH_PROTO
1323 ),
1324 )
Neale Ranns227038a2017-04-21 01:07:59 -07001325
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001326 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1327 self.send_and_expect_load_balancing(
1328 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1329 )
Neale Ranns227038a2017-04-21 01:07:59 -07001330
Neale Ranns699bea22022-02-17 09:22:16 +00001331 self.send_and_expect_only(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001332
1333 #
1334 # change the flow hash config back to defaults
1335 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001336 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, proto=1, sport=1, dport=1)
Neale Ranns227038a2017-04-21 01:07:59 -07001337
1338 #
1339 # Recursive prefixes
1340 # - testing that 2 stages of load-balancing occurs and there is no
1341 # polarisation (i.e. only 2 of 4 paths are used)
1342 #
1343 port_pkts = []
1344 src_pkts = []
1345
1346 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001347 port_pkts.append(
1348 (
1349 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1350 / IP(dst="1.1.1.1", src="20.0.0.1")
1351 / UDP(sport=1234, dport=1234 + ii)
1352 / Raw(b"\xa5" * 100)
1353 )
1354 )
1355 src_pkts.append(
1356 (
1357 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1358 / IP(dst="1.1.1.1", src="20.0.0.%d" % ii)
1359 / UDP(sport=1234, dport=1234)
1360 / Raw(b"\xa5" * 100)
1361 )
1362 )
Neale Ranns227038a2017-04-21 01:07:59 -07001363
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001364 route_10_0_0_2 = VppIpRoute(
1365 self,
1366 "10.0.0.2",
1367 32,
1368 [
1369 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1370 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1371 ],
1372 )
Neale Ranns227038a2017-04-21 01:07:59 -07001373 route_10_0_0_2.add_vpp_config()
1374
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001375 route_1_1_1_1 = VppIpRoute(
1376 self,
1377 "1.1.1.1",
1378 32,
1379 [
1380 VppRoutePath("10.0.0.2", 0xFFFFFFFF),
1381 VppRoutePath("10.0.0.1", 0xFFFFFFFF),
1382 ],
1383 )
Neale Ranns227038a2017-04-21 01:07:59 -07001384 route_1_1_1_1.add_vpp_config()
1385
1386 #
1387 # inject the packet on pg0 - expect load-balancing across all 4 paths
1388 #
1389 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001390 self.send_and_expect_load_balancing(
1391 self.pg0, port_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1392 )
1393 self.send_and_expect_load_balancing(
1394 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1395 )
Neale Ranns227038a2017-04-21 01:07:59 -07001396
Neale Ranns42e6b092017-07-31 02:56:03 -07001397 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001398 # bring down pg1 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001399 #
1400 self.pg1.link_down()
1401
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001402 rx = self.send_and_expect_load_balancing(
1403 self.pg0, src_pkts, [self.pg2, self.pg3, self.pg4]
1404 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001405 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001406
1407 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001408 # bring down pg2 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001409 #
1410 self.pg2.link_down()
1411
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001412 rx = self.send_and_expect_load_balancing(
1413 self.pg0, src_pkts, [self.pg3, self.pg4]
1414 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001415 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001416
1417 #
1418 # bring the links back up - expect LB over all again
1419 #
1420 self.pg1.link_up()
1421 self.pg2.link_up()
1422
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001423 rx = self.send_and_expect_load_balancing(
1424 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1425 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001426 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001427
1428 #
1429 # The same link-up/down but this time admin state
1430 #
1431 self.pg1.admin_down()
1432 self.pg2.admin_down()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 rx = self.send_and_expect_load_balancing(
1434 self.pg0, src_pkts, [self.pg3, self.pg4]
1435 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001436 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001437 self.pg1.admin_up()
1438 self.pg2.admin_up()
1439 self.pg1.resolve_arp()
1440 self.pg2.resolve_arp()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001441 rx = self.send_and_expect_load_balancing(
1442 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1443 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001444 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001445
1446 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001447 # Recursive prefixes
1448 # - testing that 2 stages of load-balancing, no choices
1449 #
1450 port_pkts = []
1451
1452 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001453 port_pkts.append(
1454 (
1455 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1456 / IP(dst="1.1.1.2", src="20.0.0.2")
1457 / UDP(sport=1234, dport=1234 + ii)
1458 / Raw(b"\xa5" * 100)
1459 )
1460 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001461
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001462 route_10_0_0_3 = VppIpRoute(
1463 self,
1464 "10.0.0.3",
1465 32,
1466 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
1467 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001468 route_10_0_0_3.add_vpp_config()
1469
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001470 route_1_1_1_2 = VppIpRoute(
1471 self, "1.1.1.2", 32, [VppRoutePath("10.0.0.3", 0xFFFFFFFF)]
1472 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001473 route_1_1_1_2.add_vpp_config()
1474
1475 #
Neale Ranns63480742019-03-13 06:41:52 -07001476 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001477 #
1478 self.vapi.cli("clear trace")
Neale Ranns699bea22022-02-17 09:22:16 +00001479 self.send_and_expect_only(self.pg0, port_pkts, self.pg3)
Neale Ranns42e6b092017-07-31 02:56:03 -07001480
Neale Ranns63480742019-03-13 06:41:52 -07001481 #
1482 # Add a LB route in the presence of a down link - expect no
1483 # packets over the down link
1484 #
1485 self.pg3.link_down()
1486
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001487 route_10_0_0_3 = VppIpRoute(
1488 self,
1489 "10.0.0.3",
1490 32,
1491 [
1492 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1493 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1494 ],
1495 )
Neale Ranns63480742019-03-13 06:41:52 -07001496 route_10_0_0_3.add_vpp_config()
1497
1498 port_pkts = []
1499 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001500 port_pkts.append(
1501 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1502 / IP(dst="10.0.0.3", src="20.0.0.2")
1503 / UDP(sport=1234, dport=1234 + ii)
1504 / Raw(b"\xa5" * 100)
1505 )
Neale Ranns63480742019-03-13 06:41:52 -07001506
Neale Ranns699bea22022-02-17 09:22:16 +00001507 self.send_and_expect_only(self.pg0, port_pkts, self.pg4)
Neale Ranns63480742019-03-13 06:41:52 -07001508
1509 # bring the link back up
1510 self.pg3.link_up()
1511
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001512 rx = self.send_and_expect_load_balancing(
1513 self.pg0, port_pkts, [self.pg3, self.pg4]
1514 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001515 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001516
Neale Ranns30d0fd42017-05-30 07:30:04 -07001517
1518class TestIPVlan0(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001519 """IPv4 VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001520
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001521 @classmethod
1522 def setUpClass(cls):
1523 super(TestIPVlan0, cls).setUpClass()
1524
1525 @classmethod
1526 def tearDownClass(cls):
1527 super(TestIPVlan0, cls).tearDownClass()
1528
Neale Ranns30d0fd42017-05-30 07:30:04 -07001529 def setUp(self):
1530 super(TestIPVlan0, self).setUp()
1531
1532 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001533 mpls_tbl = VppMplsTable(self, 0)
1534 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001535
1536 for i in self.pg_interfaces:
1537 i.admin_up()
1538 i.config_ip4()
1539 i.resolve_arp()
1540 i.enable_mpls()
1541
1542 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001543 for i in self.pg_interfaces:
1544 i.disable_mpls()
1545 i.unconfig_ip4()
1546 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001547 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001548
Neale Ranns30d0fd42017-05-30 07:30:04 -07001549 def test_ip_vlan_0(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001550 """IP VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001551
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 pkts = (
1553 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1554 / Dot1Q(vlan=0)
1555 / IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4)
1556 / UDP(sport=1234, dport=1234)
1557 / Raw(b"\xa5" * 100)
1558 ) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001559
1560 #
1561 # Expect that packets sent on VLAN-0 are forwarded on the
1562 # main interface.
1563 #
1564 self.send_and_expect(self.pg0, pkts, self.pg1)
1565
1566
Brian Russell318fdb82021-01-19 16:56:32 +00001567class IPPuntSetup(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001568 """Setup for IPv4 Punt Police/Redirect"""
Neale Rannsd91c1db2017-07-31 02:30:50 -07001569
Brian Russell318fdb82021-01-19 16:56:32 +00001570 def punt_setup(self):
Pavel Kotucek609e1212018-11-27 09:59:44 +01001571 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001572
1573 for i in self.pg_interfaces:
1574 i.admin_up()
1575 i.config_ip4()
1576 i.resolve_arp()
1577
Neale Ranns68577d22019-06-04 13:31:23 +00001578 # use UDP packet that have a port we need to explicitly
1579 # register to get punted.
1580 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1581 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1582 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1583 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001584 "type": pt_l4,
1585 "punt": {
1586 "l4": {
1587 "af": af_ip4,
1588 "protocol": udp_proto,
1589 "port": 1234,
Neale Ranns68577d22019-06-04 13:31:23 +00001590 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001591 },
Neale Ranns68577d22019-06-04 13:31:23 +00001592 }
1593
1594 self.vapi.set_punt(is_add=1, punt=punt_udp)
1595
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001596 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
1597 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001598 "type": pt_l4,
1599 "punt": {
1600 "l4": {
1601 "af": af_ip6,
1602 "protocol": udp_proto,
1603 "port": 1236,
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001604 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001605 },
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001606 }
1607
1608 self.vapi.set_punt(is_add=1, punt=punt_udp)
1609
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001610 self.pkt = (
1611 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1612 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1613 / UDP(sport=1234, dport=1234)
1614 / Raw(b"\xa5" * 100)
1615 )
Neale Rannsd91c1db2017-07-31 02:30:50 -07001616
Brian Russell318fdb82021-01-19 16:56:32 +00001617 def punt_teardown(self):
1618 for i in self.pg_interfaces:
1619 i.unconfig_ip4()
1620 i.admin_down()
1621
1622
1623class TestIPPunt(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001624 """IPv4 Punt Police/Redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001625
1626 def setUp(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001627 super().setUp()
1628 super().punt_setup()
Brian Russell318fdb82021-01-19 16:56:32 +00001629
1630 def tearDown(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001631 super().punt_teardown()
1632 super().tearDown()
1633
1634 def test_ip_punt_api_validation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001635 """IP punt API parameter validation"""
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001636
1637 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001638 punt = {
1639 "rx_sw_if_index": self.pg0.sw_if_index,
1640 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1641 "n_paths": 1000000,
1642 "paths": [],
1643 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001644
1645 with self.assertRaises(vpp_papi.VPPIOError):
1646 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
1647
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001648 punt = {
1649 "rx_sw_if_index": self.pg0.sw_if_index,
1650 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1651 "n_paths": 0,
1652 "paths": [],
1653 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001654
1655 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
Brian Russell318fdb82021-01-19 16:56:32 +00001656
1657 def test_ip_punt(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001658 """IP punt police and redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001659
1660 pkts = self.pkt * 1025
Neale Rannsd91c1db2017-07-31 02:30:50 -07001661
1662 #
1663 # Configure a punt redirect via pg1.
1664 #
Ole Troan0bcad322018-12-11 13:04:01 +01001665 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001666 ip_punt_redirect = VppIpPuntRedirect(
1667 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1668 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001669 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001670
1671 self.send_and_expect(self.pg0, pkts, self.pg1)
1672
1673 #
1674 # add a policer
1675 #
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001676 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1)
1677 policer.add_vpp_config()
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001678 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1679 ip_punt_policer.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001680
1681 self.vapi.cli("clear trace")
1682 self.pg0.add_stream(pkts)
1683 self.pg_enable_capture(self.pg_interfaces)
1684 self.pg_start()
1685
1686 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001687 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001688 # but not equal to the number sent, since some were policed
1689 #
1690 rx = self.pg1._get_capture(1)
Brian Russelle9887262021-01-27 14:45:22 +00001691
1692 stats = policer.get_stats()
1693
1694 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001695 self.assertGreater(stats["conform_packets"], 0)
1696 self.assertEqual(stats["exceed_packets"], 0)
1697 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00001698
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001699 self.assertGreater(len(rx), 0)
1700 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001701
1702 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001703 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001704 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001705 ip_punt_policer.remove_vpp_config()
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001706 policer.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001707 self.send_and_expect(self.pg0, pkts, self.pg1)
1708
1709 #
1710 # remove the redirect. expect full drop.
1711 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001712 ip_punt_redirect.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001713 self.send_and_assert_no_replies(self.pg0, pkts, "IP no punt config")
Neale Rannsd91c1db2017-07-31 02:30:50 -07001714
1715 #
1716 # Add a redirect that is not input port selective
1717 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001718 ip_punt_redirect = VppIpPuntRedirect(
1719 self, 0xFFFFFFFF, self.pg1.sw_if_index, nh_addr
1720 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001721 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001722 self.send_and_expect(self.pg0, pkts, self.pg1)
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001723 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001724
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001725 def test_ip_punt_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001726 """IP punt/local with VRFs"""
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001727
1728 # use a punt redirect to test if for-us packets are accepted
1729 pkts = self.pkt * 1025
1730
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001731 vlans_pg0 = [VppDot1QSubint(self, self.pg0, v) for v in range(100, 104)]
1732 vlans_pg1 = [VppDot1QSubint(self, self.pg1, v) for v in range(100, 104)]
1733 tbl4 = [VppIpTable(self, v).add_vpp_config() for v in range(100, 104)]
1734 tbl6 = [VppIpTable(self, v, True).add_vpp_config() for v in range(100, 104)]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001735
1736 for v in vlans_pg0 + vlans_pg1:
1737 v.admin_up()
1738 v.set_table_ip4(v.vlan)
1739 v.set_table_ip6(v.vlan)
1740 v.config_ip4()
1741 v.config_ip6()
1742 v.resolve_arp()
1743 v.resolve_ndp()
1744
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001745 [
1746 VppIpPuntRedirect(
1747 self,
1748 vlans_pg0[i].sw_if_index,
1749 vlans_pg1[i].sw_if_index,
1750 vlans_pg1[i].remote_ip4,
1751 ).add_vpp_config()
1752 for i in range(4)
1753 ]
1754 [
1755 VppIpPuntRedirect(
1756 self,
1757 vlans_pg0[i].sw_if_index,
1758 vlans_pg1[i].sw_if_index,
1759 vlans_pg1[i].remote_ip6,
1760 ).add_vpp_config()
1761 for i in range(4)
1762 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001763
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001764 pkts = [
1765 (
1766 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1767 / Dot1Q(vlan=i.vlan)
1768 / IP(src=i.remote_ip4, dst=i.local_ip4)
1769 / UDP(sport=1234, dport=1234)
1770 / Raw(b"\xa5" * 100)
1771 )
1772 for i in vlans_pg0
1773 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001774
1775 self.send_and_expect(self.pg0, pkts, self.pg1)
1776
1777 #
1778 # IPv4
1779 #
1780
1781 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001782 pkts = [
1783 (
1784 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1785 / Dot1Q(vlan=i.vlan)
1786 / IP(src="1.1.1.1", dst=i.local_ip4)
1787 / UDP(sport=1234, dport=1234)
1788 / Raw(b"\xa5" * 100)
1789 )
1790 for i in vlans_pg0
1791 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001792 # single and dual loop
1793 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1794 self.send_and_assert_no_replies(self.pg0, pkts)
1795
Neale Rannse22a7042022-08-09 03:03:29 +00001796 self.assert_error_counter_equal("/err/ip4-local/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001797
1798 # using the same source in different tables, should reject
1799 # for the table that the source is not present in
1800 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001801 pkts = [
1802 (
1803 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1804 / Dot1Q(vlan=i.vlan)
1805 / IP(src=vlans_pg0[0].remote_ip4, dst=i.local_ip4)
1806 / UDP(sport=1234, dport=1234)
1807 / Raw(b"\xa5" * 100)
1808 )
1809 for i in vlans_pg0
1810 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001811 # single loop accept and drop
1812 # followed by both in the same frame/loop
1813 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1814 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1815 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1816
1817 # using the same source in different tables, should reject
1818 # for the table that the source is not present in
1819 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001820 pkts = [
1821 (
1822 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1823 / Dot1Q(vlan=i.vlan)
1824 / IP(src=vlans_pg0[3].remote_ip4, dst=i.local_ip4)
1825 / UDP(sport=1234, dport=1234)
1826 / Raw(b"\xa5" * 100)
1827 )
1828 for i in vlans_pg0
1829 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001830
1831 # single loop accept and drop
1832 # followed by both in the same frame/loop
1833 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1834 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1835 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1836
1837 #
1838 # IPv6
1839 #
1840
1841 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001842 pkts = [
1843 (
1844 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1845 / Dot1Q(vlan=i.vlan)
1846 / IPv6(src="1::1", dst=i.local_ip6)
1847 / UDP(sport=1236, dport=1236)
1848 / Raw(b"\xa5" * 100)
1849 )
1850 for i in vlans_pg0
1851 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001852 # single and dual loop
1853 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1854 self.send_and_assert_no_replies(self.pg0, pkts)
1855
Neale Rannse22a7042022-08-09 03:03:29 +00001856 self.assert_error_counter_equal("/err/ip6-input/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001857
1858 # using the same source in different tables, should reject
1859 # for the table that the source is not present in
1860 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001861 pkts = [
1862 (
1863 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1864 / Dot1Q(vlan=i.vlan)
1865 / IPv6(src=vlans_pg0[0].remote_ip6, dst=i.local_ip6)
1866 / UDP(sport=1236, dport=1236)
1867 / Raw(b"\xa5" * 100)
1868 )
1869 for i in vlans_pg0
1870 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001871 # single loop accept and drop
1872 # followed by both in the same frame/loop
1873 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1874 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1875 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1876
1877 # using the same source in different tables, should reject
1878 # for the table that the source is not present in
1879 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001880 pkts = [
1881 (
1882 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1883 / Dot1Q(vlan=i.vlan)
1884 / IPv6(src=vlans_pg0[3].remote_ip6, dst=i.local_ip6)
1885 / UDP(sport=1236, dport=1236)
1886 / Raw(b"\xa5" * 100)
1887 )
1888 for i in vlans_pg0
1889 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001890
1891 # single loop accept and drop
1892 # followed by both in the same frame/loop
1893 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1894 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1895 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1896
1897 for v in vlans_pg0 + vlans_pg1:
1898 v.unconfig_ip4()
1899 v.unconfig_ip6()
1900 v.set_table_ip4(0)
1901 v.set_table_ip6(0)
1902
Pavel Kotucek609e1212018-11-27 09:59:44 +01001903 def test_ip_punt_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001904 """IP4 punt redirect dump"""
Pavel Kotucek609e1212018-11-27 09:59:44 +01001905
1906 #
1907 # Configure a punt redirects
1908 #
Ole Troan0bcad322018-12-11 13:04:01 +01001909 nh_address = self.pg3.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001910 ipr_03 = VppIpPuntRedirect(
1911 self, self.pg0.sw_if_index, self.pg3.sw_if_index, nh_address
1912 )
1913 ipr_13 = VppIpPuntRedirect(
1914 self, self.pg1.sw_if_index, self.pg3.sw_if_index, nh_address
1915 )
1916 ipr_23 = VppIpPuntRedirect(
1917 self, self.pg2.sw_if_index, self.pg3.sw_if_index, "0.0.0.0"
1918 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001919 ipr_03.add_vpp_config()
1920 ipr_13.add_vpp_config()
1921 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01001922
1923 #
1924 # Dump pg0 punt redirects
1925 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001926 self.assertTrue(ipr_03.query_vpp_config())
1927 self.assertTrue(ipr_13.query_vpp_config())
1928 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01001929
1930 #
1931 # Dump punt redirects for all interfaces
1932 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001933 punts = self.vapi.ip_punt_redirect_dump(0xFFFFFFFF)
Pavel Kotucek609e1212018-11-27 09:59:44 +01001934 self.assertEqual(len(punts), 3)
1935 for p in punts:
1936 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001937 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001938 self.assertEqual(str(punts[2].punt.nh), "0.0.0.0")
Pavel Kotucek609e1212018-11-27 09:59:44 +01001939
Neale Rannsd91c1db2017-07-31 02:30:50 -07001940
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001941class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001942 """IPv4 Punt Policer thread handoff"""
1943
Klement Sekera8d815022021-03-15 16:58:10 +01001944 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001945
1946 def setUp(self):
1947 super(TestIPPuntHandoff, self).setUp()
1948 super(TestIPPuntHandoff, self).punt_setup()
1949
1950 def tearDown(self):
1951 super(TestIPPuntHandoff, self).punt_teardown()
1952 super(TestIPPuntHandoff, self).tearDown()
1953
1954 def test_ip_punt_policer_handoff(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001955 """IP4 punt policer thread handoff"""
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001956 pkts = self.pkt * NUM_PKTS
1957
1958 #
1959 # Configure a punt redirect via pg1.
1960 #
1961 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001962 ip_punt_redirect = VppIpPuntRedirect(
1963 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1964 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001965 ip_punt_redirect.add_vpp_config()
1966
1967 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001968 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
1969 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001970 #
1971 # This policer drops no packets, we are just
1972 # testing that they get to the right thread.
1973 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001974 policer = VppPolicer(
1975 self,
1976 "ip4-punt",
1977 400,
1978 0,
1979 10,
1980 0,
1981 1,
1982 0,
1983 0,
1984 False,
1985 action_tx,
1986 action_tx,
1987 action_tx,
1988 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001989 policer.add_vpp_config()
1990 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1991 ip_punt_policer.add_vpp_config()
1992
1993 for worker in [0, 1]:
1994 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00001995 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001996
Brian Russelle9887262021-01-27 14:45:22 +00001997 # Combined stats, all threads
1998 stats = policer.get_stats()
1999
2000 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002001 self.assertGreater(stats["conform_packets"], 0)
2002 self.assertEqual(stats["exceed_packets"], 0)
2003 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002004
2005 # Worker 0, should have done all the policing
2006 stats0 = policer.get_stats(worker=0)
2007 self.assertEqual(stats, stats0)
2008
2009 # Worker 1, should have handed everything off
2010 stats1 = policer.get_stats(worker=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002011 self.assertEqual(stats1["conform_packets"], 0)
2012 self.assertEqual(stats1["exceed_packets"], 0)
2013 self.assertEqual(stats1["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002014
Brian Russellbb983142021-02-10 13:56:06 +00002015 # Bind the policer to worker 1 and repeat
2016 policer.bind_vpp_config(1, True)
2017 for worker in [0, 1]:
2018 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2019 self.logger.debug(self.vapi.cli("show trace max 100"))
2020
2021 # The 2 workers should now have policed the same amount
2022 stats = policer.get_stats()
2023 stats0 = policer.get_stats(worker=0)
2024 stats1 = policer.get_stats(worker=1)
2025
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002026 self.assertGreater(stats0["conform_packets"], 0)
2027 self.assertEqual(stats0["exceed_packets"], 0)
2028 self.assertGreater(stats0["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002030 self.assertGreater(stats1["conform_packets"], 0)
2031 self.assertEqual(stats1["exceed_packets"], 0)
2032 self.assertGreater(stats1["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002033
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002034 self.assertEqual(
2035 stats0["conform_packets"] + stats1["conform_packets"],
2036 stats["conform_packets"],
2037 )
Brian Russellbb983142021-02-10 13:56:06 +00002038
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002039 self.assertEqual(
2040 stats0["violate_packets"] + stats1["violate_packets"],
2041 stats["violate_packets"],
2042 )
Brian Russellbb983142021-02-10 13:56:06 +00002043
2044 # Unbind the policer and repeat
2045 policer.bind_vpp_config(1, False)
2046 for worker in [0, 1]:
2047 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2048 self.logger.debug(self.vapi.cli("show trace max 100"))
2049
2050 # The policer should auto-bind to worker 0 when packets arrive
2051 stats = policer.get_stats()
2052 stats0new = policer.get_stats(worker=0)
2053 stats1new = policer.get_stats(worker=1)
2054
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002055 self.assertGreater(stats0new["conform_packets"], stats0["conform_packets"])
2056 self.assertEqual(stats0new["exceed_packets"], 0)
2057 self.assertGreater(stats0new["violate_packets"], stats0["violate_packets"])
Brian Russellbb983142021-02-10 13:56:06 +00002058
2059 self.assertEqual(stats1, stats1new)
2060
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002061 #
2062 # Clean up
2063 #
2064 ip_punt_policer.remove_vpp_config()
2065 policer.remove_vpp_config()
2066 ip_punt_redirect.remove_vpp_config()
2067
2068
Neale Ranns054c03a2017-10-13 05:15:07 -07002069class TestIPDeag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002070 """IPv4 Deaggregate Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002071
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002072 @classmethod
2073 def setUpClass(cls):
2074 super(TestIPDeag, cls).setUpClass()
2075
2076 @classmethod
2077 def tearDownClass(cls):
2078 super(TestIPDeag, cls).tearDownClass()
2079
Neale Ranns054c03a2017-10-13 05:15:07 -07002080 def setUp(self):
2081 super(TestIPDeag, self).setUp()
2082
2083 self.create_pg_interfaces(range(3))
2084
2085 for i in self.pg_interfaces:
2086 i.admin_up()
2087 i.config_ip4()
2088 i.resolve_arp()
2089
2090 def tearDown(self):
2091 super(TestIPDeag, self).tearDown()
2092 for i in self.pg_interfaces:
2093 i.unconfig_ip4()
2094 i.admin_down()
2095
Neale Ranns054c03a2017-10-13 05:15:07 -07002096 def test_ip_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002097 """IP Deag Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002098
2099 #
2100 # Create a table to be used for:
2101 # 1 - another destination address lookup
2102 # 2 - a source address lookup
2103 #
2104 table_dst = VppIpTable(self, 1)
2105 table_src = VppIpTable(self, 2)
2106 table_dst.add_vpp_config()
2107 table_src.add_vpp_config()
2108
2109 #
2110 # Add a route in the default table to point to a deag/
2111 # second lookup in each of these tables
2112 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002113 route_to_dst = VppIpRoute(
2114 self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
2115 )
Neale Ranns097fa662018-05-01 05:17:55 -07002116 route_to_src = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002117 self,
2118 "1.1.1.2",
2119 32,
2120 [
2121 VppRoutePath(
2122 "0.0.0.0",
2123 0xFFFFFFFF,
2124 nh_table_id=2,
2125 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP,
2126 )
2127 ],
2128 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002129 route_to_dst.add_vpp_config()
2130 route_to_src.add_vpp_config()
2131
2132 #
2133 # packets to these destination are dropped, since they'll
2134 # hit the respective default routes in the second table
2135 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002136 p_dst = (
2137 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2138 / IP(src="5.5.5.5", dst="1.1.1.1")
2139 / TCP(sport=1234, dport=1234)
2140 / Raw(b"\xa5" * 100)
2141 )
2142 p_src = (
2143 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2144 / IP(src="2.2.2.2", dst="1.1.1.2")
2145 / TCP(sport=1234, dport=1234)
2146 / Raw(b"\xa5" * 100)
2147 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002148 pkts_dst = p_dst * 257
2149 pkts_src = p_src * 257
2150
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002151 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in dst table")
2152 self.send_and_assert_no_replies(self.pg0, pkts_src, "IP in src table")
Neale Ranns054c03a2017-10-13 05:15:07 -07002153
2154 #
2155 # add a route in the dst table to forward via pg1
2156 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002157 route_in_dst = VppIpRoute(
2158 self,
2159 "1.1.1.1",
2160 32,
2161 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2162 table_id=1,
2163 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002164 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07002165
Neale Ranns054c03a2017-10-13 05:15:07 -07002166 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
2167
2168 #
2169 # add a route in the src table to forward via pg2
2170 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002171 route_in_src = VppIpRoute(
2172 self,
2173 "2.2.2.2",
2174 32,
2175 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2176 table_id=2,
2177 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002178 route_in_src.add_vpp_config()
2179 self.send_and_expect(self.pg0, pkts_src, self.pg2)
2180
Neale Rannsce9e0b42018-08-01 12:53:17 -07002181 #
2182 # loop in the lookup DP
2183 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002184 route_loop = VppIpRoute(
2185 self, "2.2.2.3", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
2186 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002187 route_loop.add_vpp_config()
2188
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002189 p_l = (
2190 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2191 / IP(src="2.2.2.4", dst="2.2.2.3")
2192 / TCP(sport=1234, dport=1234)
2193 / Raw(b"\xa5" * 100)
2194 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002195
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002196 self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop")
Neale Rannsce9e0b42018-08-01 12:53:17 -07002197
Neale Ranns054c03a2017-10-13 05:15:07 -07002198
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002199class TestIPInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002200 """IPv4 Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002201
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002202 @classmethod
2203 def setUpClass(cls):
2204 super(TestIPInput, cls).setUpClass()
2205
2206 @classmethod
2207 def tearDownClass(cls):
2208 super(TestIPInput, cls).tearDownClass()
2209
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002210 def setUp(self):
2211 super(TestIPInput, self).setUp()
2212
2213 self.create_pg_interfaces(range(2))
2214
2215 for i in self.pg_interfaces:
2216 i.admin_up()
2217 i.config_ip4()
2218 i.resolve_arp()
2219
2220 def tearDown(self):
2221 super(TestIPInput, self).tearDown()
2222 for i in self.pg_interfaces:
2223 i.unconfig_ip4()
2224 i.admin_down()
2225
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002226 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002227 """IP Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002228
2229 # i can't find a way in scapy to construct an IP packet
2230 # with a length less than the IP header length
2231
2232 #
2233 # Packet too short - this is forwarded
2234 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002235 p_short = (
2236 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2237 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=40)
2238 / UDP(sport=1234, dport=1234)
2239 / Raw(b"\xa5" * 100)
2240 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002241
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002242 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002243
2244 #
2245 # Packet too long - this is dropped
2246 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002247 p_long = (
2248 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2249 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=400)
2250 / UDP(sport=1234, dport=1234)
2251 / Raw(b"\xa5" * 100)
2252 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002253
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002254 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002255
2256 #
2257 # bad chksum - this is dropped
2258 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002259 p_chksum = (
2260 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2261 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, chksum=400)
2262 / UDP(sport=1234, dport=1234)
2263 / Raw(b"\xa5" * 100)
2264 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002265
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002266 rx = self.send_and_assert_no_replies(
2267 self.pg0, p_chksum * NUM_PKTS, "bad checksum"
2268 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002269
2270 #
2271 # bad version - this is dropped
2272 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002273 p_ver = (
2274 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2275 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, version=3)
2276 / UDP(sport=1234, dport=1234)
2277 / Raw(b"\xa5" * 100)
2278 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002279
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002280 rx = self.send_and_assert_no_replies(
2281 self.pg0, p_ver * NUM_PKTS, "funky version"
2282 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002283
2284 #
2285 # fragment offset 1 - this is dropped
2286 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002287 p_frag = (
2288 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2289 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, frag=1)
2290 / UDP(sport=1234, dport=1234)
2291 / Raw(b"\xa5" * 100)
2292 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002293
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002294 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002295
2296 #
2297 # TTL expired packet
2298 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002299 p_ttl = (
2300 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2301 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=1)
2302 / UDP(sport=1234, dport=1234)
2303 / Raw(b"\xa5" * 100)
2304 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002305
Neale Ranns5c6dd172022-02-17 09:08:47 +00002306 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002307
Neale Ranns5c6dd172022-02-17 09:08:47 +00002308 for rx in rxs:
2309 icmp = rx[ICMP]
2310 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002311 self.assertEqual(icmpcodes[icmp.type][icmp.code], "ttl-zero-during-transit")
Neale Ranns5c6dd172022-02-17 09:08:47 +00002312 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2313 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002314
Neale Rannsffd78d12018-02-09 06:05:16 -08002315 #
2316 # MTU exceeded
2317 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002318 p_mtu = (
2319 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2320 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=10, flags="DF")
2321 / UDP(sport=1234, dport=1234)
2322 / Raw(b"\xa5" * 2000)
2323 )
Neale Rannsffd78d12018-02-09 06:05:16 -08002324
Ole Troand7231612018-06-07 10:17:57 +02002325 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002326
Neale Ranns5c6dd172022-02-17 09:08:47 +00002327 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002328
Neale Ranns5c6dd172022-02-17 09:08:47 +00002329 for rx in rxs:
2330 icmp = rx[ICMP]
2331 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 self.assertEqual(icmpcodes[icmp.type][icmp.code], "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002333 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002334 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2335 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002336
Ole Troand7231612018-06-07 10:17:57 +02002337 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002338 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002339
Ole Troand7231612018-06-07 10:17:57 +02002340 # Reset MTU for subsequent tests
2341 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002342
Neale Rannsbe2286b2018-12-09 12:54:51 -08002343 #
2344 # source address 0.0.0.0 and 25.255.255.255 and for-us
2345 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002346 p_s0 = (
2347 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2348 / IP(src="0.0.0.0", dst=self.pg0.local_ip4)
2349 / ICMP(id=4, seq=4)
2350 / Raw(load=b"\x0a" * 18)
2351 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002352 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2353
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002354 p_s0 = (
2355 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2356 / IP(src="255.255.255.255", dst=self.pg0.local_ip4)
2357 / ICMP(id=4, seq=4)
2358 / Raw(load=b"\x0a" * 18)
2359 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002360 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2361
Neale Ranns1855b8e2018-07-11 10:31:26 -07002362
2363class TestIPDirectedBroadcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002364 """IPv4 Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002365
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002366 @classmethod
2367 def setUpClass(cls):
2368 super(TestIPDirectedBroadcast, cls).setUpClass()
2369
2370 @classmethod
2371 def tearDownClass(cls):
2372 super(TestIPDirectedBroadcast, cls).tearDownClass()
2373
Neale Ranns1855b8e2018-07-11 10:31:26 -07002374 def setUp(self):
2375 super(TestIPDirectedBroadcast, self).setUp()
2376
2377 self.create_pg_interfaces(range(2))
2378
2379 for i in self.pg_interfaces:
2380 i.admin_up()
2381
2382 def tearDown(self):
2383 super(TestIPDirectedBroadcast, self).tearDown()
2384 for i in self.pg_interfaces:
2385 i.admin_down()
2386
2387 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002388 """IP Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002389
2390 #
2391 # set the directed broadcast on pg0 first, then config IP4 addresses
2392 # for pg1 directed broadcast is always disabled
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002393 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002394
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002395 p0 = (
2396 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2397 / IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast)
2398 / UDP(sport=1234, dport=1234)
2399 / Raw(b"\xa5" * 2000)
2400 )
2401 p1 = (
2402 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2403 / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast)
2404 / UDP(sport=1234, dport=1234)
2405 / Raw(b"\xa5" * 2000)
2406 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002407
2408 self.pg0.config_ip4()
2409 self.pg0.resolve_arp()
2410 self.pg1.config_ip4()
2411 self.pg1.resolve_arp()
2412
2413 #
2414 # test packet is L2 broadcast
2415 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002416 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002417 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2418
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002419 self.send_and_assert_no_replies(
2420 self.pg0, p1 * NUM_PKTS, "directed broadcast disabled"
2421 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002422
2423 #
2424 # toggle directed broadcast on pg0
2425 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002426 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 0)
2427 self.send_and_assert_no_replies(
2428 self.pg1, p0 * NUM_PKTS, "directed broadcast disabled"
2429 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002430
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002431 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002432 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002433
2434 self.pg0.unconfig_ip4()
2435 self.pg1.unconfig_ip4()
2436
2437
mu.duojiao59a82952018-10-11 14:27:30 +08002438class TestIPLPM(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002439 """IPv4 longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002440
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002441 @classmethod
2442 def setUpClass(cls):
2443 super(TestIPLPM, cls).setUpClass()
2444
2445 @classmethod
2446 def tearDownClass(cls):
2447 super(TestIPLPM, cls).tearDownClass()
2448
mu.duojiao59a82952018-10-11 14:27:30 +08002449 def setUp(self):
2450 super(TestIPLPM, self).setUp()
2451
2452 self.create_pg_interfaces(range(4))
2453
2454 for i in self.pg_interfaces:
2455 i.admin_up()
2456 i.config_ip4()
2457 i.resolve_arp()
2458
2459 def tearDown(self):
2460 super(TestIPLPM, self).tearDown()
2461 for i in self.pg_interfaces:
2462 i.admin_down()
2463 i.unconfig_ip4()
2464
2465 def test_ip_lpm(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002466 """IP longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002467
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002468 s_24 = VppIpRoute(
2469 self,
2470 "10.1.2.0",
2471 24,
2472 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2473 )
mu.duojiao59a82952018-10-11 14:27:30 +08002474 s_24.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002475 s_8 = VppIpRoute(
2476 self,
2477 "10.0.0.0",
2478 8,
2479 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2480 )
mu.duojiao59a82952018-10-11 14:27:30 +08002481 s_8.add_vpp_config()
2482
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002483 p_8 = (
2484 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2485 / IP(src="1.1.1.1", dst="10.1.1.1")
2486 / UDP(sport=1234, dport=1234)
2487 / Raw(b"\xa5" * 2000)
2488 )
2489 p_24 = (
2490 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2491 / IP(src="1.1.1.1", dst="10.1.2.1")
2492 / UDP(sport=1234, dport=1234)
2493 / Raw(b"\xa5" * 2000)
2494 )
mu.duojiao59a82952018-10-11 14:27:30 +08002495
2496 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002497 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2498 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002499
2500
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002501@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002502class TestIPv4Frag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002503 """IPv4 fragmentation"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002504
2505 @classmethod
2506 def setUpClass(cls):
2507 super(TestIPv4Frag, cls).setUpClass()
2508
2509 cls.create_pg_interfaces([0, 1])
2510 cls.src_if = cls.pg0
2511 cls.dst_if = cls.pg1
2512
2513 # setup all interfaces
2514 for i in cls.pg_interfaces:
2515 i.admin_up()
2516 i.config_ip4()
2517 i.resolve_arp()
2518
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002519 @classmethod
2520 def tearDownClass(cls):
2521 super(TestIPv4Frag, cls).tearDownClass()
2522
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002523 def test_frag_large_packets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002524 """Fragmentation of large packets"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002525
Neale Ranns0b6a8572019-10-30 17:34:14 +00002526 self.vapi.cli("adjacency counters enable")
2527
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002528 p = (
2529 Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac)
2530 / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4)
2531 / UDP(sport=1234, dport=5678)
2532 / Raw()
2533 )
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002534 self.extend_packet(p, 6000, "abcde")
2535 saved_payload = p[Raw].load
2536
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002537 nbr = VppNeighbor(
2538 self,
2539 self.dst_if.sw_if_index,
2540 self.dst_if.remote_mac,
2541 self.dst_if.remote_ip4,
2542 ).add_vpp_config()
Neale Ranns0b6a8572019-10-30 17:34:14 +00002543
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002544 # Force fragmentation by setting MTU of output interface
2545 # lower than packet size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, [5000, 0, 0, 0])
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002547
2548 self.pg_enable_capture()
2549 self.src_if.add_stream(p)
2550 self.pg_start()
2551
2552 # Expecting 3 fragments because size of created fragments currently
2553 # cannot be larger then VPP buffer size (which is 2048)
2554 packets = self.dst_if.get_capture(3)
2555
Neale Ranns0b6a8572019-10-30 17:34:14 +00002556 # we should show 3 packets thru the neighbor
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002557 self.assertEqual(3, nbr.get_stats()["packets"])
Neale Ranns0b6a8572019-10-30 17:34:14 +00002558
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002559 # Assume VPP sends the fragments in order
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002560 payload = b""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002561 for p in packets:
2562 payload_offset = p.frag * 8
2563 if payload_offset > 0:
2564 payload_offset -= 8 # UDP header is not in payload
2565 self.assert_equal(payload_offset, len(payload))
2566 payload += p[Raw].load
2567 self.assert_equal(payload, saved_payload, "payload")
2568
2569
Neale Ranns9db6ada2019-11-08 12:42:31 +00002570class TestIPReplace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002571 """IPv4 Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002572
2573 @classmethod
2574 def setUpClass(cls):
2575 super(TestIPReplace, cls).setUpClass()
2576
2577 @classmethod
2578 def tearDownClass(cls):
2579 super(TestIPReplace, cls).tearDownClass()
2580
2581 def setUp(self):
2582 super(TestIPReplace, self).setUp()
2583
2584 self.create_pg_interfaces(range(4))
2585
2586 table_id = 1
2587 self.tables = []
2588
2589 for i in self.pg_interfaces:
2590 i.admin_up()
2591 i.config_ip4()
2592 i.resolve_arp()
2593 i.generate_remote_hosts(2)
2594 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2595 table_id += 1
2596
2597 def tearDown(self):
2598 super(TestIPReplace, self).tearDown()
2599 for i in self.pg_interfaces:
2600 i.admin_down()
2601 i.unconfig_ip4()
2602
2603 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002604 """IP Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002605
Neale Ranns990f6942020-10-20 07:20:17 +00002606 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2607 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002608 N_ROUTES = 20
2609 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2610 routes = [[], [], [], []]
2611
2612 # load up the tables with some routes
2613 for ii, t in enumerate(self.tables):
2614 for jj in range(N_ROUTES):
2615 uni = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002616 self,
2617 "10.0.0.%d" % jj,
2618 32,
2619 [
2620 VppRoutePath(
2621 links[ii].remote_hosts[0].ip4, links[ii].sw_if_index
2622 ),
2623 VppRoutePath(
2624 links[ii].remote_hosts[1].ip4, links[ii].sw_if_index
2625 ),
2626 ],
2627 table_id=t.table_id,
2628 ).add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002629 multi = VppIpMRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002630 self,
2631 "0.0.0.0",
2632 "239.0.0.%d" % jj,
2633 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002634 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002635 [
2636 VppMRoutePath(
2637 self.pg0.sw_if_index,
2638 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
2639 ),
2640 VppMRoutePath(
2641 self.pg1.sw_if_index,
2642 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2643 ),
2644 VppMRoutePath(
2645 self.pg2.sw_if_index,
2646 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2647 ),
2648 VppMRoutePath(
2649 self.pg3.sw_if_index,
2650 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2651 ),
2652 ],
2653 table_id=t.table_id,
2654 ).add_vpp_config()
2655 routes[ii].append({"uni": uni, "multi": multi})
Neale Ranns9db6ada2019-11-08 12:42:31 +00002656
2657 #
2658 # replace the tables a few times
2659 #
2660 for kk in range(3):
2661 # replace_begin each table
2662 for t in self.tables:
2663 t.replace_begin()
2664
2665 # all the routes are still there
2666 for ii, t in enumerate(self.tables):
2667 dump = t.dump()
2668 mdump = t.mdump()
2669 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002670 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2671 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002672
2673 # redownload the even numbered routes
2674 for ii, t in enumerate(self.tables):
2675 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002676 routes[ii][jj]["uni"].add_vpp_config()
2677 routes[ii][jj]["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002678
2679 # signal each table replace_end
2680 for t in self.tables:
2681 t.replace_end()
2682
2683 # we should find the even routes, but not the odd
2684 for ii, t in enumerate(self.tables):
2685 dump = t.dump()
2686 mdump = t.mdump()
2687 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002688 self.assertTrue(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2689 self.assertTrue(
2690 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2691 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002692 for jj in range(1, N_ROUTES - 1, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002693 self.assertFalse(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2694 self.assertFalse(
2695 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2696 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002697
2698 # reload all the routes
2699 for ii, t in enumerate(self.tables):
2700 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002701 r["uni"].add_vpp_config()
2702 r["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002703
2704 # all the routes are still there
2705 for ii, t in enumerate(self.tables):
2706 dump = t.dump()
2707 mdump = t.mdump()
2708 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002709 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2710 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002711
2712 #
2713 # finally flush the tables for good measure
2714 #
2715 for t in self.tables:
2716 t.flush()
2717 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002718 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002719
2720
Neale Ranns9efcee62019-11-26 19:30:08 +00002721class TestIPCover(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002722 """IPv4 Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002723
2724 @classmethod
2725 def setUpClass(cls):
2726 super(TestIPCover, cls).setUpClass()
2727
2728 @classmethod
2729 def tearDownClass(cls):
2730 super(TestIPCover, cls).tearDownClass()
2731
2732 def setUp(self):
2733 super(TestIPCover, self).setUp()
2734
2735 self.create_pg_interfaces(range(4))
2736
2737 table_id = 1
2738 self.tables = []
2739
2740 for i in self.pg_interfaces:
2741 i.admin_up()
2742 i.config_ip4()
2743 i.resolve_arp()
2744 i.generate_remote_hosts(2)
2745 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2746 table_id += 1
2747
2748 def tearDown(self):
2749 super(TestIPCover, self).tearDown()
2750 for i in self.pg_interfaces:
2751 i.admin_down()
2752 i.unconfig_ip4()
2753
2754 def test_cover(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002755 """IP Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002756
2757 # add a loop back with a /32 prefix
2758 lo = VppLoInterface(self)
2759 lo.admin_up()
2760 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2761
2762 # add a neighbour that matches the loopback's /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002763 nbr = VppNeighbor(
2764 self, lo.sw_if_index, lo.remote_mac, "127.0.0.1"
2765 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002766
2767 # add the default route which will be the cover for /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002768 r = VppIpRoute(
2769 self,
2770 "0.0.0.0",
2771 0,
2772 [VppRoutePath("127.0.0.1", lo.sw_if_index)],
2773 register=False,
2774 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002775
2776 # add/remove/add a longer mask cover
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002777 r8 = VppIpRoute(
2778 self, "127.0.0.0", 8, [VppRoutePath("127.0.0.1", lo.sw_if_index)]
2779 ).add_vpp_config()
Neale Ranns87866032020-11-25 09:14:22 +00002780 r8.remove_vpp_config()
2781 r8.add_vpp_config()
2782 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002783
2784 # remove the default route
2785 r.remove_vpp_config()
2786
Neale Ranns87866032020-11-25 09:14:22 +00002787 # remove the interface prefix
2788 a.remove_vpp_config()
2789
Neale Ranns59f71132020-04-08 12:19:38 +00002790
2791class TestIP4Replace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002792 """IPv4 Interface Address Replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002793
2794 @classmethod
2795 def setUpClass(cls):
2796 super(TestIP4Replace, cls).setUpClass()
2797
2798 @classmethod
2799 def tearDownClass(cls):
2800 super(TestIP4Replace, cls).tearDownClass()
2801
2802 def setUp(self):
2803 super(TestIP4Replace, self).setUp()
2804
2805 self.create_pg_interfaces(range(4))
2806
2807 for i in self.pg_interfaces:
2808 i.admin_up()
2809
2810 def tearDown(self):
2811 super(TestIP4Replace, self).tearDown()
2812 for i in self.pg_interfaces:
2813 i.admin_down()
2814
2815 def get_n_pfxs(self, intf):
2816 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2817
2818 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002819 """IP interface address replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002820
2821 intf_pfxs = [[], [], [], []]
2822
2823 # add prefixes to each of the interfaces
2824 for i in range(len(self.pg_interfaces)):
2825 intf = self.pg_interfaces[i]
2826
2827 # 172.16.x.1/24
2828 addr = "172.16.%d.1" % intf.sw_if_index
2829 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2830 intf_pfxs[i].append(a)
2831
2832 # 172.16.x.2/24 - a different address in the same subnet as above
2833 addr = "172.16.%d.2" % intf.sw_if_index
2834 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2835 intf_pfxs[i].append(a)
2836
2837 # 172.15.x.2/24 - a different address and subnet
2838 addr = "172.15.%d.2" % intf.sw_if_index
2839 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2840 intf_pfxs[i].append(a)
2841
2842 # a dump should n_address in it
2843 for intf in self.pg_interfaces:
2844 self.assertEqual(self.get_n_pfxs(intf), 3)
2845
2846 #
2847 # remove all the address thru a replace
2848 #
2849 self.vapi.sw_interface_address_replace_begin()
2850 self.vapi.sw_interface_address_replace_end()
2851 for intf in self.pg_interfaces:
2852 self.assertEqual(self.get_n_pfxs(intf), 0)
2853
2854 #
2855 # add all the interface addresses back
2856 #
2857 for p in intf_pfxs:
2858 for v in p:
2859 v.add_vpp_config()
2860 for intf in self.pg_interfaces:
2861 self.assertEqual(self.get_n_pfxs(intf), 3)
2862
2863 #
2864 # replace again, but this time update/re-add the address on the first
2865 # two interfaces
2866 #
2867 self.vapi.sw_interface_address_replace_begin()
2868
2869 for p in intf_pfxs[:2]:
2870 for v in p:
2871 v.add_vpp_config()
2872
2873 self.vapi.sw_interface_address_replace_end()
2874
2875 # on the first two the address still exist,
2876 # on the other two they do not
2877 for intf in self.pg_interfaces[:2]:
2878 self.assertEqual(self.get_n_pfxs(intf), 3)
2879 for p in intf_pfxs[:2]:
2880 for v in p:
2881 self.assertTrue(v.query_vpp_config())
2882 for intf in self.pg_interfaces[2:]:
2883 self.assertEqual(self.get_n_pfxs(intf), 0)
2884
2885 #
2886 # add all the interface addresses back on the last two
2887 #
2888 for p in intf_pfxs[2:]:
2889 for v in p:
2890 v.add_vpp_config()
2891 for intf in self.pg_interfaces:
2892 self.assertEqual(self.get_n_pfxs(intf), 3)
2893
2894 #
2895 # replace again, this time add different prefixes on all the interfaces
2896 #
2897 self.vapi.sw_interface_address_replace_begin()
2898
2899 pfxs = []
2900 for intf in self.pg_interfaces:
2901 # 172.18.x.1/24
2902 addr = "172.18.%d.1" % intf.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002903 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002904
2905 self.vapi.sw_interface_address_replace_end()
2906
2907 # only .18 should exist on each interface
2908 for intf in self.pg_interfaces:
2909 self.assertEqual(self.get_n_pfxs(intf), 1)
2910 for pfx in pfxs:
2911 self.assertTrue(pfx.query_vpp_config())
2912
2913 #
2914 # remove everything
2915 #
2916 self.vapi.sw_interface_address_replace_begin()
2917 self.vapi.sw_interface_address_replace_end()
2918 for intf in self.pg_interfaces:
2919 self.assertEqual(self.get_n_pfxs(intf), 0)
2920
2921 #
2922 # add prefixes to each interface. post-begin add the prefix from
2923 # interface X onto interface Y. this would normally be an error
2924 # since it would generate a 'duplicate address' warning. but in
2925 # this case, since what is newly downloaded is sane, it's ok
2926 #
2927 for intf in self.pg_interfaces:
2928 # 172.18.x.1/24
2929 addr = "172.18.%d.1" % intf.sw_if_index
2930 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2931
2932 self.vapi.sw_interface_address_replace_begin()
2933
2934 pfxs = []
2935 for intf in self.pg_interfaces:
2936 # 172.18.x.1/24
2937 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002938 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002939
2940 self.vapi.sw_interface_address_replace_end()
2941
2942 self.logger.info(self.vapi.cli("sh int addr"))
2943
2944 for intf in self.pg_interfaces:
2945 self.assertEqual(self.get_n_pfxs(intf), 1)
2946 for pfx in pfxs:
2947 self.assertTrue(pfx.query_vpp_config())
2948
2949
Neale Ranns8f5fef22020-12-21 08:29:34 +00002950class TestIPv4PathMTU(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002951 """IPv4 Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002952
2953 @classmethod
2954 def setUpClass(cls):
2955 super(TestIPv4PathMTU, cls).setUpClass()
2956
2957 cls.create_pg_interfaces(range(2))
2958
2959 # setup all interfaces
2960 for i in cls.pg_interfaces:
2961 i.admin_up()
2962 i.config_ip4()
2963 i.resolve_arp()
2964
2965 @classmethod
2966 def tearDownClass(cls):
2967 super(TestIPv4PathMTU, cls).tearDownClass()
2968
2969 def test_path_mtu(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002970 """Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002971
2972 #
2973 # The goal here is not to test that fragmentation works correctly,
2974 # that's done elsewhere, the intent is to ensure that the Path MTU
2975 # settings are honoured.
2976 #
2977 self.vapi.cli("adjacency counters enable")
2978
2979 # set the interface MTU to a reasonable value
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002980 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00002981
2982 self.pg1.generate_remote_hosts(4)
2983
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002984 p_2k = (
2985 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2986 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2987 / UDP(sport=1234, dport=5678)
2988 / Raw(b"0xa" * 640)
2989 )
2990 p_1k = (
2991 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2992 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2993 / UDP(sport=1234, dport=5678)
2994 / Raw(b"0xa" * 320)
2995 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00002996
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002997 nbr = VppNeighbor(
2998 self, self.pg1.sw_if_index, self.pg1.remote_mac, self.pg1.remote_ip4
2999 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003000
3001 # this is now the interface MTU frags
3002 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3003 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3004
3005 # drop the path MTU for this neighbour to below the interface MTU
3006 # expect more frags
3007 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
3008
3009 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3010 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3011
3012 # print/format the adj delegate
3013 self.logger.info(self.vapi.cli("sh adj 5"))
3014
3015 # increase the path MTU to more than the interface
3016 # expect to use the interface MTU
3017 pmtu.modify(8192)
3018
3019 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3020 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3021
3022 # go back to an MTU from the path
3023 # wrap the call around mark-n-sweep to enusre updates clear stale
3024 self.vapi.ip_path_mtu_replace_begin()
3025 pmtu.modify(900)
3026 self.vapi.ip_path_mtu_replace_end()
3027
3028 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3029 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3030
3031 # raise the interface's MTU
3032 # should still use that of the path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003033 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003034 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3035 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3036
3037 # set path high and interface low
3038 pmtu.modify(2000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003039 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [900, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003040 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3041 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3042
3043 # remove the path MTU using the mark-n-sweep semantics
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003044 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003045 self.vapi.ip_path_mtu_replace_begin()
3046 self.vapi.ip_path_mtu_replace_end()
3047
3048 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3049 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3050
3051 #
3052 # set path MTU for a neighbour that doesn't exist, yet
3053 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003054 pmtu2 = VppIpPathMtu(self, self.pg1.remote_hosts[2].ip4, 900).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003055
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003056 p_2k = (
3057 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3058 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3059 / UDP(sport=1234, dport=5678)
3060 / Raw(b"0xa" * 640)
3061 )
3062 p_1k = (
3063 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3064 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3065 / UDP(sport=1234, dport=5678)
3066 / Raw(b"0xa" * 320)
3067 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003068
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003069 nbr2 = VppNeighbor(
3070 self,
3071 self.pg1.sw_if_index,
3072 self.pg1.remote_hosts[2].mac,
3073 self.pg1.remote_hosts[2].ip4,
3074 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003075
3076 # should frag to the path MTU
3077 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3078 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3079
3080 # remove and re-add the neighbour
3081 nbr2.remove_vpp_config()
3082 nbr2.add_vpp_config()
3083
3084 # should frag to the path MTU
3085 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3086 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3087
3088 #
3089 # set PMTUs for many peers
3090 #
3091 N_HOSTS = 16
3092 self.pg1.generate_remote_hosts(16)
3093 self.pg1.configure_ipv4_neighbors()
3094
3095 for h in range(N_HOSTS):
3096 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
3097 pmtu.add_vpp_config()
3098 self.assertTrue(pmtu.query_vpp_config())
3099
3100 self.logger.info(self.vapi.cli("sh ip pmtu"))
3101 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
3102 self.assertEqual(N_HOSTS, len(dump))
3103
3104 for h in range(N_HOSTS):
3105 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
3106 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
3107
3108 # should frag to the path MTU
3109 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3110 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3111
3112
Neale Ranns50bd1d32021-10-08 07:16:12 +00003113class TestIPv4ItfRebind(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003114 """IPv4 Interface Bind w/ attached routes"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003115
3116 def setUp(self):
3117 super(TestIPv4ItfRebind, self).setUp()
3118
3119 self.create_pg_interfaces(range(3))
3120
3121 def tearDown(self):
3122 super(TestIPv4ItfRebind, self).tearDown()
3123
3124 def test_rebind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003125 """Import to no import"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003126
3127 TABLE_ID = 1
3128 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
3129 self.pg1.set_table_ip4(TABLE_ID)
3130
3131 for i in self.pg_interfaces:
3132 i.admin_up()
3133 i.config_ip4()
3134 i.resolve_arp()
3135
3136 # add an attached route via an pg0
3137 # in a different table. this prefix should import
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003138 rt = VppIpRoute(
3139 self,
3140 self.pg0.local_ip4,
3141 24,
3142 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
3143 table_id=TABLE_ID,
3144 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003145
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003146 p = (
3147 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3148 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3149 / UDP(sport=1234, dport=5678)
3150 / Raw(b"0xa" * 640)
3151 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003152
3153 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3154 self.assertFalse(rx[0].haslayer(ARP))
3155
3156 # then bind pg0 to a new table
3157 # so the prefix no longer imports
3158 self.pg0.unconfig_ip4()
3159 self.pg0.set_table_ip4(TABLE_ID)
3160 self.pg0.config_ip4()
3161 self.pg0.resolve_arp()
3162
3163 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3164 self.assertFalse(rx[0].haslayer(ARP))
3165
3166 # revert back to imported
3167 self.pg0.unconfig_ip4()
3168 self.pg0.set_table_ip4(0)
3169 self.pg0.config_ip4()
3170 self.pg0.resolve_arp()
3171
3172 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3173 self.assertFalse(rx[0].haslayer(ARP))
3174
3175 # cleanup
3176 for i in self.pg_interfaces:
3177 i.unconfig_ip4()
3178 i.set_table_ip4(0)
3179 i.admin_down()
3180
3181 rt.remove_vpp_config()
3182 tbl.remove_vpp_config()
3183
3184 def test_delete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003185 """Swap import tables"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003186
3187 TABLE_ID1 = 1
3188 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
3189 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
3190 TABLE_ID2 = 2
3191 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
3192 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
3193
3194 # table mappings
3195 self.pg1.set_table_ip4(TABLE_ID1)
3196 self.pg1.set_table_ip6(TABLE_ID1)
3197 self.pg2.set_table_ip4(TABLE_ID2)
3198 self.pg2.set_table_ip6(TABLE_ID2)
3199
3200 for i in self.pg_interfaces:
3201 i.admin_up()
3202 i.config_ip4()
3203 i.resolve_arp()
3204
3205 # add an attached route in the default table via pg0
3206 # this should import to table 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003207 rt4 = VppIpRoute(
3208 self,
3209 self.pg1.local_ip4,
3210 24,
3211 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3212 ).add_vpp_config()
3213 rt6 = VppIpRoute(
3214 self,
3215 self.pg1.local_ip6,
3216 64,
3217 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3218 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003219
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003220 p1 = (
3221 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3222 / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
3223 / UDP(sport=1234, dport=5678)
3224 / Raw(b"0xa" * 640)
3225 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003226
3227 # inject into table 0
3228 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3229 self.assertFalse(rx[0].haslayer(ARP))
3230
3231 # swap the attached interface to table 2
3232 self.pg1.unconfig_ip4()
3233 self.pg1.unconfig_ip6()
3234 self.pg1.set_table_ip4(TABLE_ID2)
3235 self.pg1.set_table_ip6(TABLE_ID2)
3236 self.pg1.config_ip4()
3237 self.pg1.config_ip6()
3238 self.pg1.resolve_arp()
3239
3240 # delete table 1
3241 tbl1_4.flush()
3242 tbl1_6.flush()
3243 tbl1_4.remove_vpp_config()
3244 tbl1_6.remove_vpp_config()
3245
3246 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3247 self.assertFalse(rx[0].haslayer(ARP))
3248
3249 for i in self.pg_interfaces:
3250 i.unconfig_ip4()
3251 i.unconfig_ip6()
3252 i.set_table_ip4(0)
3253 i.set_table_ip6(0)
3254 i.admin_down()
3255
3256
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003257if __name__ == "__main__":
Klement Sekeraf62ae122016-10-11 11:47:09 +02003258 unittest.main(testRunner=VppTestRunner)