blob: 9079e54366ab8c9c924ee60751921c56d79c60ab [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
1796 self.assert_error_counter_equal(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001797 "/err/ip4-local/ip4 source lookup miss", len(pkts) + 1
1798 )
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001799
1800 # using the same source in different tables, should reject
1801 # for the table that the source is not present in
1802 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001803 pkts = [
1804 (
1805 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1806 / Dot1Q(vlan=i.vlan)
1807 / IP(src=vlans_pg0[0].remote_ip4, dst=i.local_ip4)
1808 / UDP(sport=1234, dport=1234)
1809 / Raw(b"\xa5" * 100)
1810 )
1811 for i in vlans_pg0
1812 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001813 # single loop accept and drop
1814 # followed by both in the same frame/loop
1815 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1816 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1817 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1818
1819 # using the same source in different tables, should reject
1820 # for the table that the source is not present in
1821 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 pkts = [
1823 (
1824 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1825 / Dot1Q(vlan=i.vlan)
1826 / IP(src=vlans_pg0[3].remote_ip4, dst=i.local_ip4)
1827 / UDP(sport=1234, dport=1234)
1828 / Raw(b"\xa5" * 100)
1829 )
1830 for i in vlans_pg0
1831 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001832
1833 # single loop accept and drop
1834 # followed by both in the same frame/loop
1835 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1836 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1837 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1838
1839 #
1840 # IPv6
1841 #
1842
1843 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001844 pkts = [
1845 (
1846 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1847 / Dot1Q(vlan=i.vlan)
1848 / IPv6(src="1::1", dst=i.local_ip6)
1849 / UDP(sport=1236, dport=1236)
1850 / Raw(b"\xa5" * 100)
1851 )
1852 for i in vlans_pg0
1853 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001854 # single and dual loop
1855 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1856 self.send_and_assert_no_replies(self.pg0, pkts)
1857
1858 self.assert_error_counter_equal(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001859 "/err/ip6-input/ip6 source lookup miss", len(pkts) + 1
1860 )
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001861
1862 # using the same source in different tables, should reject
1863 # for the table that the source is not present in
1864 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001865 pkts = [
1866 (
1867 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1868 / Dot1Q(vlan=i.vlan)
1869 / IPv6(src=vlans_pg0[0].remote_ip6, dst=i.local_ip6)
1870 / UDP(sport=1236, dport=1236)
1871 / Raw(b"\xa5" * 100)
1872 )
1873 for i in vlans_pg0
1874 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001875 # single loop accept and drop
1876 # followed by both in the same frame/loop
1877 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1878 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1879 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1880
1881 # using the same source in different tables, should reject
1882 # for the table that the source is not present in
1883 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001884 pkts = [
1885 (
1886 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1887 / Dot1Q(vlan=i.vlan)
1888 / IPv6(src=vlans_pg0[3].remote_ip6, dst=i.local_ip6)
1889 / UDP(sport=1236, dport=1236)
1890 / Raw(b"\xa5" * 100)
1891 )
1892 for i in vlans_pg0
1893 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001894
1895 # single loop accept and drop
1896 # followed by both in the same frame/loop
1897 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1898 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1899 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1900
1901 for v in vlans_pg0 + vlans_pg1:
1902 v.unconfig_ip4()
1903 v.unconfig_ip6()
1904 v.set_table_ip4(0)
1905 v.set_table_ip6(0)
1906
Pavel Kotucek609e1212018-11-27 09:59:44 +01001907 def test_ip_punt_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001908 """IP4 punt redirect dump"""
Pavel Kotucek609e1212018-11-27 09:59:44 +01001909
1910 #
1911 # Configure a punt redirects
1912 #
Ole Troan0bcad322018-12-11 13:04:01 +01001913 nh_address = self.pg3.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001914 ipr_03 = VppIpPuntRedirect(
1915 self, self.pg0.sw_if_index, self.pg3.sw_if_index, nh_address
1916 )
1917 ipr_13 = VppIpPuntRedirect(
1918 self, self.pg1.sw_if_index, self.pg3.sw_if_index, nh_address
1919 )
1920 ipr_23 = VppIpPuntRedirect(
1921 self, self.pg2.sw_if_index, self.pg3.sw_if_index, "0.0.0.0"
1922 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001923 ipr_03.add_vpp_config()
1924 ipr_13.add_vpp_config()
1925 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01001926
1927 #
1928 # Dump pg0 punt redirects
1929 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001930 self.assertTrue(ipr_03.query_vpp_config())
1931 self.assertTrue(ipr_13.query_vpp_config())
1932 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01001933
1934 #
1935 # Dump punt redirects for all interfaces
1936 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001937 punts = self.vapi.ip_punt_redirect_dump(0xFFFFFFFF)
Pavel Kotucek609e1212018-11-27 09:59:44 +01001938 self.assertEqual(len(punts), 3)
1939 for p in punts:
1940 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001941 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001942 self.assertEqual(str(punts[2].punt.nh), "0.0.0.0")
Pavel Kotucek609e1212018-11-27 09:59:44 +01001943
Neale Rannsd91c1db2017-07-31 02:30:50 -07001944
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001945class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001946 """IPv4 Punt Policer thread handoff"""
1947
Klement Sekera8d815022021-03-15 16:58:10 +01001948 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001949
1950 def setUp(self):
1951 super(TestIPPuntHandoff, self).setUp()
1952 super(TestIPPuntHandoff, self).punt_setup()
1953
1954 def tearDown(self):
1955 super(TestIPPuntHandoff, self).punt_teardown()
1956 super(TestIPPuntHandoff, self).tearDown()
1957
1958 def test_ip_punt_policer_handoff(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001959 """IP4 punt policer thread handoff"""
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001960 pkts = self.pkt * NUM_PKTS
1961
1962 #
1963 # Configure a punt redirect via pg1.
1964 #
1965 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001966 ip_punt_redirect = VppIpPuntRedirect(
1967 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1968 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001969 ip_punt_redirect.add_vpp_config()
1970
1971 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001972 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
1973 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001974 #
1975 # This policer drops no packets, we are just
1976 # testing that they get to the right thread.
1977 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001978 policer = VppPolicer(
1979 self,
1980 "ip4-punt",
1981 400,
1982 0,
1983 10,
1984 0,
1985 1,
1986 0,
1987 0,
1988 False,
1989 action_tx,
1990 action_tx,
1991 action_tx,
1992 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001993 policer.add_vpp_config()
1994 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1995 ip_punt_policer.add_vpp_config()
1996
1997 for worker in [0, 1]:
1998 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00001999 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002000
Brian Russelle9887262021-01-27 14:45:22 +00002001 # Combined stats, all threads
2002 stats = policer.get_stats()
2003
2004 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002005 self.assertGreater(stats["conform_packets"], 0)
2006 self.assertEqual(stats["exceed_packets"], 0)
2007 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002008
2009 # Worker 0, should have done all the policing
2010 stats0 = policer.get_stats(worker=0)
2011 self.assertEqual(stats, stats0)
2012
2013 # Worker 1, should have handed everything off
2014 stats1 = policer.get_stats(worker=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002015 self.assertEqual(stats1["conform_packets"], 0)
2016 self.assertEqual(stats1["exceed_packets"], 0)
2017 self.assertEqual(stats1["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002018
Brian Russellbb983142021-02-10 13:56:06 +00002019 # Bind the policer to worker 1 and repeat
2020 policer.bind_vpp_config(1, True)
2021 for worker in [0, 1]:
2022 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2023 self.logger.debug(self.vapi.cli("show trace max 100"))
2024
2025 # The 2 workers should now have policed the same amount
2026 stats = policer.get_stats()
2027 stats0 = policer.get_stats(worker=0)
2028 stats1 = policer.get_stats(worker=1)
2029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002030 self.assertGreater(stats0["conform_packets"], 0)
2031 self.assertEqual(stats0["exceed_packets"], 0)
2032 self.assertGreater(stats0["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002033
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002034 self.assertGreater(stats1["conform_packets"], 0)
2035 self.assertEqual(stats1["exceed_packets"], 0)
2036 self.assertGreater(stats1["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002037
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002038 self.assertEqual(
2039 stats0["conform_packets"] + stats1["conform_packets"],
2040 stats["conform_packets"],
2041 )
Brian Russellbb983142021-02-10 13:56:06 +00002042
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002043 self.assertEqual(
2044 stats0["violate_packets"] + stats1["violate_packets"],
2045 stats["violate_packets"],
2046 )
Brian Russellbb983142021-02-10 13:56:06 +00002047
2048 # Unbind the policer and repeat
2049 policer.bind_vpp_config(1, False)
2050 for worker in [0, 1]:
2051 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2052 self.logger.debug(self.vapi.cli("show trace max 100"))
2053
2054 # The policer should auto-bind to worker 0 when packets arrive
2055 stats = policer.get_stats()
2056 stats0new = policer.get_stats(worker=0)
2057 stats1new = policer.get_stats(worker=1)
2058
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002059 self.assertGreater(stats0new["conform_packets"], stats0["conform_packets"])
2060 self.assertEqual(stats0new["exceed_packets"], 0)
2061 self.assertGreater(stats0new["violate_packets"], stats0["violate_packets"])
Brian Russellbb983142021-02-10 13:56:06 +00002062
2063 self.assertEqual(stats1, stats1new)
2064
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002065 #
2066 # Clean up
2067 #
2068 ip_punt_policer.remove_vpp_config()
2069 policer.remove_vpp_config()
2070 ip_punt_redirect.remove_vpp_config()
2071
2072
Neale Ranns054c03a2017-10-13 05:15:07 -07002073class TestIPDeag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002074 """IPv4 Deaggregate Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002075
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002076 @classmethod
2077 def setUpClass(cls):
2078 super(TestIPDeag, cls).setUpClass()
2079
2080 @classmethod
2081 def tearDownClass(cls):
2082 super(TestIPDeag, cls).tearDownClass()
2083
Neale Ranns054c03a2017-10-13 05:15:07 -07002084 def setUp(self):
2085 super(TestIPDeag, self).setUp()
2086
2087 self.create_pg_interfaces(range(3))
2088
2089 for i in self.pg_interfaces:
2090 i.admin_up()
2091 i.config_ip4()
2092 i.resolve_arp()
2093
2094 def tearDown(self):
2095 super(TestIPDeag, self).tearDown()
2096 for i in self.pg_interfaces:
2097 i.unconfig_ip4()
2098 i.admin_down()
2099
Neale Ranns054c03a2017-10-13 05:15:07 -07002100 def test_ip_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002101 """IP Deag Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002102
2103 #
2104 # Create a table to be used for:
2105 # 1 - another destination address lookup
2106 # 2 - a source address lookup
2107 #
2108 table_dst = VppIpTable(self, 1)
2109 table_src = VppIpTable(self, 2)
2110 table_dst.add_vpp_config()
2111 table_src.add_vpp_config()
2112
2113 #
2114 # Add a route in the default table to point to a deag/
2115 # second lookup in each of these tables
2116 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002117 route_to_dst = VppIpRoute(
2118 self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
2119 )
Neale Ranns097fa662018-05-01 05:17:55 -07002120 route_to_src = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002121 self,
2122 "1.1.1.2",
2123 32,
2124 [
2125 VppRoutePath(
2126 "0.0.0.0",
2127 0xFFFFFFFF,
2128 nh_table_id=2,
2129 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP,
2130 )
2131 ],
2132 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002133 route_to_dst.add_vpp_config()
2134 route_to_src.add_vpp_config()
2135
2136 #
2137 # packets to these destination are dropped, since they'll
2138 # hit the respective default routes in the second table
2139 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002140 p_dst = (
2141 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2142 / IP(src="5.5.5.5", dst="1.1.1.1")
2143 / TCP(sport=1234, dport=1234)
2144 / Raw(b"\xa5" * 100)
2145 )
2146 p_src = (
2147 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2148 / IP(src="2.2.2.2", dst="1.1.1.2")
2149 / TCP(sport=1234, dport=1234)
2150 / Raw(b"\xa5" * 100)
2151 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002152 pkts_dst = p_dst * 257
2153 pkts_src = p_src * 257
2154
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002155 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in dst table")
2156 self.send_and_assert_no_replies(self.pg0, pkts_src, "IP in src table")
Neale Ranns054c03a2017-10-13 05:15:07 -07002157
2158 #
2159 # add a route in the dst table to forward via pg1
2160 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002161 route_in_dst = VppIpRoute(
2162 self,
2163 "1.1.1.1",
2164 32,
2165 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2166 table_id=1,
2167 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002168 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07002169
Neale Ranns054c03a2017-10-13 05:15:07 -07002170 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
2171
2172 #
2173 # add a route in the src table to forward via pg2
2174 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002175 route_in_src = VppIpRoute(
2176 self,
2177 "2.2.2.2",
2178 32,
2179 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2180 table_id=2,
2181 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002182 route_in_src.add_vpp_config()
2183 self.send_and_expect(self.pg0, pkts_src, self.pg2)
2184
Neale Rannsce9e0b42018-08-01 12:53:17 -07002185 #
2186 # loop in the lookup DP
2187 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002188 route_loop = VppIpRoute(
2189 self, "2.2.2.3", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
2190 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002191 route_loop.add_vpp_config()
2192
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002193 p_l = (
2194 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2195 / IP(src="2.2.2.4", dst="2.2.2.3")
2196 / TCP(sport=1234, dport=1234)
2197 / Raw(b"\xa5" * 100)
2198 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002199
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002200 self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop")
Neale Rannsce9e0b42018-08-01 12:53:17 -07002201
Neale Ranns054c03a2017-10-13 05:15:07 -07002202
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002203class TestIPInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002204 """IPv4 Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002205
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002206 @classmethod
2207 def setUpClass(cls):
2208 super(TestIPInput, cls).setUpClass()
2209
2210 @classmethod
2211 def tearDownClass(cls):
2212 super(TestIPInput, cls).tearDownClass()
2213
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002214 def setUp(self):
2215 super(TestIPInput, self).setUp()
2216
2217 self.create_pg_interfaces(range(2))
2218
2219 for i in self.pg_interfaces:
2220 i.admin_up()
2221 i.config_ip4()
2222 i.resolve_arp()
2223
2224 def tearDown(self):
2225 super(TestIPInput, self).tearDown()
2226 for i in self.pg_interfaces:
2227 i.unconfig_ip4()
2228 i.admin_down()
2229
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002230 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002231 """IP Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002232
2233 # i can't find a way in scapy to construct an IP packet
2234 # with a length less than the IP header length
2235
2236 #
2237 # Packet too short - this is forwarded
2238 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002239 p_short = (
2240 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2241 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=40)
2242 / UDP(sport=1234, dport=1234)
2243 / Raw(b"\xa5" * 100)
2244 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002245
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002246 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002247
2248 #
2249 # Packet too long - this is dropped
2250 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002251 p_long = (
2252 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2253 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=400)
2254 / UDP(sport=1234, dport=1234)
2255 / Raw(b"\xa5" * 100)
2256 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002257
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002258 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002259
2260 #
2261 # bad chksum - this is dropped
2262 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002263 p_chksum = (
2264 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2265 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, chksum=400)
2266 / UDP(sport=1234, dport=1234)
2267 / Raw(b"\xa5" * 100)
2268 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002269
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002270 rx = self.send_and_assert_no_replies(
2271 self.pg0, p_chksum * NUM_PKTS, "bad checksum"
2272 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002273
2274 #
2275 # bad version - this is dropped
2276 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002277 p_ver = (
2278 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2279 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, version=3)
2280 / UDP(sport=1234, dport=1234)
2281 / Raw(b"\xa5" * 100)
2282 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002283
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002284 rx = self.send_and_assert_no_replies(
2285 self.pg0, p_ver * NUM_PKTS, "funky version"
2286 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002287
2288 #
2289 # fragment offset 1 - this is dropped
2290 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002291 p_frag = (
2292 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2293 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, frag=1)
2294 / UDP(sport=1234, dport=1234)
2295 / Raw(b"\xa5" * 100)
2296 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002297
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002298 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002299
2300 #
2301 # TTL expired packet
2302 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002303 p_ttl = (
2304 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2305 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=1)
2306 / UDP(sport=1234, dport=1234)
2307 / Raw(b"\xa5" * 100)
2308 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002309
Neale Ranns5c6dd172022-02-17 09:08:47 +00002310 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002311
Neale Ranns5c6dd172022-02-17 09:08:47 +00002312 for rx in rxs:
2313 icmp = rx[ICMP]
2314 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002315 self.assertEqual(icmpcodes[icmp.type][icmp.code], "ttl-zero-during-transit")
Neale Ranns5c6dd172022-02-17 09:08:47 +00002316 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2317 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002318
Neale Rannsffd78d12018-02-09 06:05:16 -08002319 #
2320 # MTU exceeded
2321 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002322 p_mtu = (
2323 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2324 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=10, flags="DF")
2325 / UDP(sport=1234, dport=1234)
2326 / Raw(b"\xa5" * 2000)
2327 )
Neale Rannsffd78d12018-02-09 06:05:16 -08002328
Ole Troand7231612018-06-07 10:17:57 +02002329 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002330
Neale Ranns5c6dd172022-02-17 09:08:47 +00002331 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002332
Neale Ranns5c6dd172022-02-17 09:08:47 +00002333 for rx in rxs:
2334 icmp = rx[ICMP]
2335 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002336 self.assertEqual(icmpcodes[icmp.type][icmp.code], "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002337 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002338 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2339 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002340
Ole Troand7231612018-06-07 10:17:57 +02002341 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002342 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002343
Ole Troand7231612018-06-07 10:17:57 +02002344 # Reset MTU for subsequent tests
2345 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002346
Neale Rannsbe2286b2018-12-09 12:54:51 -08002347 #
2348 # source address 0.0.0.0 and 25.255.255.255 and for-us
2349 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002350 p_s0 = (
2351 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2352 / IP(src="0.0.0.0", dst=self.pg0.local_ip4)
2353 / ICMP(id=4, seq=4)
2354 / Raw(load=b"\x0a" * 18)
2355 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002356 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2357
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002358 p_s0 = (
2359 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2360 / IP(src="255.255.255.255", dst=self.pg0.local_ip4)
2361 / ICMP(id=4, seq=4)
2362 / Raw(load=b"\x0a" * 18)
2363 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002364 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2365
Neale Ranns1855b8e2018-07-11 10:31:26 -07002366
2367class TestIPDirectedBroadcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002368 """IPv4 Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002369
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002370 @classmethod
2371 def setUpClass(cls):
2372 super(TestIPDirectedBroadcast, cls).setUpClass()
2373
2374 @classmethod
2375 def tearDownClass(cls):
2376 super(TestIPDirectedBroadcast, cls).tearDownClass()
2377
Neale Ranns1855b8e2018-07-11 10:31:26 -07002378 def setUp(self):
2379 super(TestIPDirectedBroadcast, self).setUp()
2380
2381 self.create_pg_interfaces(range(2))
2382
2383 for i in self.pg_interfaces:
2384 i.admin_up()
2385
2386 def tearDown(self):
2387 super(TestIPDirectedBroadcast, self).tearDown()
2388 for i in self.pg_interfaces:
2389 i.admin_down()
2390
2391 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002392 """IP Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002393
2394 #
2395 # set the directed broadcast on pg0 first, then config IP4 addresses
2396 # for pg1 directed broadcast is always disabled
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002397 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002398
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002399 p0 = (
2400 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2401 / IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast)
2402 / UDP(sport=1234, dport=1234)
2403 / Raw(b"\xa5" * 2000)
2404 )
2405 p1 = (
2406 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2407 / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast)
2408 / UDP(sport=1234, dport=1234)
2409 / Raw(b"\xa5" * 2000)
2410 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002411
2412 self.pg0.config_ip4()
2413 self.pg0.resolve_arp()
2414 self.pg1.config_ip4()
2415 self.pg1.resolve_arp()
2416
2417 #
2418 # test packet is L2 broadcast
2419 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002420 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002421 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2422
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002423 self.send_and_assert_no_replies(
2424 self.pg0, p1 * NUM_PKTS, "directed broadcast disabled"
2425 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002426
2427 #
2428 # toggle directed broadcast on pg0
2429 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002430 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 0)
2431 self.send_and_assert_no_replies(
2432 self.pg1, p0 * NUM_PKTS, "directed broadcast disabled"
2433 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002434
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002435 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002436 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002437
2438 self.pg0.unconfig_ip4()
2439 self.pg1.unconfig_ip4()
2440
2441
mu.duojiao59a82952018-10-11 14:27:30 +08002442class TestIPLPM(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002443 """IPv4 longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002444
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002445 @classmethod
2446 def setUpClass(cls):
2447 super(TestIPLPM, cls).setUpClass()
2448
2449 @classmethod
2450 def tearDownClass(cls):
2451 super(TestIPLPM, cls).tearDownClass()
2452
mu.duojiao59a82952018-10-11 14:27:30 +08002453 def setUp(self):
2454 super(TestIPLPM, self).setUp()
2455
2456 self.create_pg_interfaces(range(4))
2457
2458 for i in self.pg_interfaces:
2459 i.admin_up()
2460 i.config_ip4()
2461 i.resolve_arp()
2462
2463 def tearDown(self):
2464 super(TestIPLPM, self).tearDown()
2465 for i in self.pg_interfaces:
2466 i.admin_down()
2467 i.unconfig_ip4()
2468
2469 def test_ip_lpm(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002470 """IP longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002471
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002472 s_24 = VppIpRoute(
2473 self,
2474 "10.1.2.0",
2475 24,
2476 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2477 )
mu.duojiao59a82952018-10-11 14:27:30 +08002478 s_24.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002479 s_8 = VppIpRoute(
2480 self,
2481 "10.0.0.0",
2482 8,
2483 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2484 )
mu.duojiao59a82952018-10-11 14:27:30 +08002485 s_8.add_vpp_config()
2486
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002487 p_8 = (
2488 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2489 / IP(src="1.1.1.1", dst="10.1.1.1")
2490 / UDP(sport=1234, dport=1234)
2491 / Raw(b"\xa5" * 2000)
2492 )
2493 p_24 = (
2494 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2495 / IP(src="1.1.1.1", dst="10.1.2.1")
2496 / UDP(sport=1234, dport=1234)
2497 / Raw(b"\xa5" * 2000)
2498 )
mu.duojiao59a82952018-10-11 14:27:30 +08002499
2500 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002501 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2502 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002503
2504
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002505@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002506class TestIPv4Frag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002507 """IPv4 fragmentation"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002508
2509 @classmethod
2510 def setUpClass(cls):
2511 super(TestIPv4Frag, cls).setUpClass()
2512
2513 cls.create_pg_interfaces([0, 1])
2514 cls.src_if = cls.pg0
2515 cls.dst_if = cls.pg1
2516
2517 # setup all interfaces
2518 for i in cls.pg_interfaces:
2519 i.admin_up()
2520 i.config_ip4()
2521 i.resolve_arp()
2522
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002523 @classmethod
2524 def tearDownClass(cls):
2525 super(TestIPv4Frag, cls).tearDownClass()
2526
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002527 def test_frag_large_packets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002528 """Fragmentation of large packets"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002529
Neale Ranns0b6a8572019-10-30 17:34:14 +00002530 self.vapi.cli("adjacency counters enable")
2531
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002532 p = (
2533 Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac)
2534 / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4)
2535 / UDP(sport=1234, dport=5678)
2536 / Raw()
2537 )
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002538 self.extend_packet(p, 6000, "abcde")
2539 saved_payload = p[Raw].load
2540
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002541 nbr = VppNeighbor(
2542 self,
2543 self.dst_if.sw_if_index,
2544 self.dst_if.remote_mac,
2545 self.dst_if.remote_ip4,
2546 ).add_vpp_config()
Neale Ranns0b6a8572019-10-30 17:34:14 +00002547
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002548 # Force fragmentation by setting MTU of output interface
2549 # lower than packet size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002550 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, [5000, 0, 0, 0])
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002551
2552 self.pg_enable_capture()
2553 self.src_if.add_stream(p)
2554 self.pg_start()
2555
2556 # Expecting 3 fragments because size of created fragments currently
2557 # cannot be larger then VPP buffer size (which is 2048)
2558 packets = self.dst_if.get_capture(3)
2559
Neale Ranns0b6a8572019-10-30 17:34:14 +00002560 # we should show 3 packets thru the neighbor
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002561 self.assertEqual(3, nbr.get_stats()["packets"])
Neale Ranns0b6a8572019-10-30 17:34:14 +00002562
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002563 # Assume VPP sends the fragments in order
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002564 payload = b""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002565 for p in packets:
2566 payload_offset = p.frag * 8
2567 if payload_offset > 0:
2568 payload_offset -= 8 # UDP header is not in payload
2569 self.assert_equal(payload_offset, len(payload))
2570 payload += p[Raw].load
2571 self.assert_equal(payload, saved_payload, "payload")
2572
2573
Neale Ranns9db6ada2019-11-08 12:42:31 +00002574class TestIPReplace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002575 """IPv4 Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002576
2577 @classmethod
2578 def setUpClass(cls):
2579 super(TestIPReplace, cls).setUpClass()
2580
2581 @classmethod
2582 def tearDownClass(cls):
2583 super(TestIPReplace, cls).tearDownClass()
2584
2585 def setUp(self):
2586 super(TestIPReplace, self).setUp()
2587
2588 self.create_pg_interfaces(range(4))
2589
2590 table_id = 1
2591 self.tables = []
2592
2593 for i in self.pg_interfaces:
2594 i.admin_up()
2595 i.config_ip4()
2596 i.resolve_arp()
2597 i.generate_remote_hosts(2)
2598 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2599 table_id += 1
2600
2601 def tearDown(self):
2602 super(TestIPReplace, self).tearDown()
2603 for i in self.pg_interfaces:
2604 i.admin_down()
2605 i.unconfig_ip4()
2606
2607 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002608 """IP Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002609
Neale Ranns990f6942020-10-20 07:20:17 +00002610 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2611 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002612 N_ROUTES = 20
2613 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2614 routes = [[], [], [], []]
2615
2616 # load up the tables with some routes
2617 for ii, t in enumerate(self.tables):
2618 for jj in range(N_ROUTES):
2619 uni = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002620 self,
2621 "10.0.0.%d" % jj,
2622 32,
2623 [
2624 VppRoutePath(
2625 links[ii].remote_hosts[0].ip4, links[ii].sw_if_index
2626 ),
2627 VppRoutePath(
2628 links[ii].remote_hosts[1].ip4, links[ii].sw_if_index
2629 ),
2630 ],
2631 table_id=t.table_id,
2632 ).add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002633 multi = VppIpMRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002634 self,
2635 "0.0.0.0",
2636 "239.0.0.%d" % jj,
2637 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002638 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002639 [
2640 VppMRoutePath(
2641 self.pg0.sw_if_index,
2642 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
2643 ),
2644 VppMRoutePath(
2645 self.pg1.sw_if_index,
2646 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2647 ),
2648 VppMRoutePath(
2649 self.pg2.sw_if_index,
2650 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2651 ),
2652 VppMRoutePath(
2653 self.pg3.sw_if_index,
2654 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2655 ),
2656 ],
2657 table_id=t.table_id,
2658 ).add_vpp_config()
2659 routes[ii].append({"uni": uni, "multi": multi})
Neale Ranns9db6ada2019-11-08 12:42:31 +00002660
2661 #
2662 # replace the tables a few times
2663 #
2664 for kk in range(3):
2665 # replace_begin each table
2666 for t in self.tables:
2667 t.replace_begin()
2668
2669 # all the routes are still there
2670 for ii, t in enumerate(self.tables):
2671 dump = t.dump()
2672 mdump = t.mdump()
2673 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002674 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2675 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002676
2677 # redownload the even numbered routes
2678 for ii, t in enumerate(self.tables):
2679 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002680 routes[ii][jj]["uni"].add_vpp_config()
2681 routes[ii][jj]["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002682
2683 # signal each table replace_end
2684 for t in self.tables:
2685 t.replace_end()
2686
2687 # we should find the even routes, but not the odd
2688 for ii, t in enumerate(self.tables):
2689 dump = t.dump()
2690 mdump = t.mdump()
2691 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002692 self.assertTrue(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2693 self.assertTrue(
2694 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2695 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002696 for jj in range(1, N_ROUTES - 1, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002697 self.assertFalse(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2698 self.assertFalse(
2699 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2700 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002701
2702 # reload all the routes
2703 for ii, t in enumerate(self.tables):
2704 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002705 r["uni"].add_vpp_config()
2706 r["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002707
2708 # all the routes are still there
2709 for ii, t in enumerate(self.tables):
2710 dump = t.dump()
2711 mdump = t.mdump()
2712 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002713 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2714 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002715
2716 #
2717 # finally flush the tables for good measure
2718 #
2719 for t in self.tables:
2720 t.flush()
2721 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002722 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002723
2724
Neale Ranns9efcee62019-11-26 19:30:08 +00002725class TestIPCover(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002726 """IPv4 Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002727
2728 @classmethod
2729 def setUpClass(cls):
2730 super(TestIPCover, cls).setUpClass()
2731
2732 @classmethod
2733 def tearDownClass(cls):
2734 super(TestIPCover, cls).tearDownClass()
2735
2736 def setUp(self):
2737 super(TestIPCover, self).setUp()
2738
2739 self.create_pg_interfaces(range(4))
2740
2741 table_id = 1
2742 self.tables = []
2743
2744 for i in self.pg_interfaces:
2745 i.admin_up()
2746 i.config_ip4()
2747 i.resolve_arp()
2748 i.generate_remote_hosts(2)
2749 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2750 table_id += 1
2751
2752 def tearDown(self):
2753 super(TestIPCover, self).tearDown()
2754 for i in self.pg_interfaces:
2755 i.admin_down()
2756 i.unconfig_ip4()
2757
2758 def test_cover(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002759 """IP Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002760
2761 # add a loop back with a /32 prefix
2762 lo = VppLoInterface(self)
2763 lo.admin_up()
2764 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2765
2766 # add a neighbour that matches the loopback's /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002767 nbr = VppNeighbor(
2768 self, lo.sw_if_index, lo.remote_mac, "127.0.0.1"
2769 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002770
2771 # add the default route which will be the cover for /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002772 r = VppIpRoute(
2773 self,
2774 "0.0.0.0",
2775 0,
2776 [VppRoutePath("127.0.0.1", lo.sw_if_index)],
2777 register=False,
2778 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002779
2780 # add/remove/add a longer mask cover
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002781 r8 = VppIpRoute(
2782 self, "127.0.0.0", 8, [VppRoutePath("127.0.0.1", lo.sw_if_index)]
2783 ).add_vpp_config()
Neale Ranns87866032020-11-25 09:14:22 +00002784 r8.remove_vpp_config()
2785 r8.add_vpp_config()
2786 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002787
2788 # remove the default route
2789 r.remove_vpp_config()
2790
Neale Ranns87866032020-11-25 09:14:22 +00002791 # remove the interface prefix
2792 a.remove_vpp_config()
2793
Neale Ranns59f71132020-04-08 12:19:38 +00002794
2795class TestIP4Replace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002796 """IPv4 Interface Address Replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002797
2798 @classmethod
2799 def setUpClass(cls):
2800 super(TestIP4Replace, cls).setUpClass()
2801
2802 @classmethod
2803 def tearDownClass(cls):
2804 super(TestIP4Replace, cls).tearDownClass()
2805
2806 def setUp(self):
2807 super(TestIP4Replace, self).setUp()
2808
2809 self.create_pg_interfaces(range(4))
2810
2811 for i in self.pg_interfaces:
2812 i.admin_up()
2813
2814 def tearDown(self):
2815 super(TestIP4Replace, self).tearDown()
2816 for i in self.pg_interfaces:
2817 i.admin_down()
2818
2819 def get_n_pfxs(self, intf):
2820 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2821
2822 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002823 """IP interface address replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002824
2825 intf_pfxs = [[], [], [], []]
2826
2827 # add prefixes to each of the interfaces
2828 for i in range(len(self.pg_interfaces)):
2829 intf = self.pg_interfaces[i]
2830
2831 # 172.16.x.1/24
2832 addr = "172.16.%d.1" % intf.sw_if_index
2833 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2834 intf_pfxs[i].append(a)
2835
2836 # 172.16.x.2/24 - a different address in the same subnet as above
2837 addr = "172.16.%d.2" % intf.sw_if_index
2838 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2839 intf_pfxs[i].append(a)
2840
2841 # 172.15.x.2/24 - a different address and subnet
2842 addr = "172.15.%d.2" % intf.sw_if_index
2843 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2844 intf_pfxs[i].append(a)
2845
2846 # a dump should n_address in it
2847 for intf in self.pg_interfaces:
2848 self.assertEqual(self.get_n_pfxs(intf), 3)
2849
2850 #
2851 # remove all the address thru a replace
2852 #
2853 self.vapi.sw_interface_address_replace_begin()
2854 self.vapi.sw_interface_address_replace_end()
2855 for intf in self.pg_interfaces:
2856 self.assertEqual(self.get_n_pfxs(intf), 0)
2857
2858 #
2859 # add all the interface addresses back
2860 #
2861 for p in intf_pfxs:
2862 for v in p:
2863 v.add_vpp_config()
2864 for intf in self.pg_interfaces:
2865 self.assertEqual(self.get_n_pfxs(intf), 3)
2866
2867 #
2868 # replace again, but this time update/re-add the address on the first
2869 # two interfaces
2870 #
2871 self.vapi.sw_interface_address_replace_begin()
2872
2873 for p in intf_pfxs[:2]:
2874 for v in p:
2875 v.add_vpp_config()
2876
2877 self.vapi.sw_interface_address_replace_end()
2878
2879 # on the first two the address still exist,
2880 # on the other two they do not
2881 for intf in self.pg_interfaces[:2]:
2882 self.assertEqual(self.get_n_pfxs(intf), 3)
2883 for p in intf_pfxs[:2]:
2884 for v in p:
2885 self.assertTrue(v.query_vpp_config())
2886 for intf in self.pg_interfaces[2:]:
2887 self.assertEqual(self.get_n_pfxs(intf), 0)
2888
2889 #
2890 # add all the interface addresses back on the last two
2891 #
2892 for p in intf_pfxs[2:]:
2893 for v in p:
2894 v.add_vpp_config()
2895 for intf in self.pg_interfaces:
2896 self.assertEqual(self.get_n_pfxs(intf), 3)
2897
2898 #
2899 # replace again, this time add different prefixes on all the interfaces
2900 #
2901 self.vapi.sw_interface_address_replace_begin()
2902
2903 pfxs = []
2904 for intf in self.pg_interfaces:
2905 # 172.18.x.1/24
2906 addr = "172.18.%d.1" % intf.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002907 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002908
2909 self.vapi.sw_interface_address_replace_end()
2910
2911 # only .18 should exist on each interface
2912 for intf in self.pg_interfaces:
2913 self.assertEqual(self.get_n_pfxs(intf), 1)
2914 for pfx in pfxs:
2915 self.assertTrue(pfx.query_vpp_config())
2916
2917 #
2918 # remove everything
2919 #
2920 self.vapi.sw_interface_address_replace_begin()
2921 self.vapi.sw_interface_address_replace_end()
2922 for intf in self.pg_interfaces:
2923 self.assertEqual(self.get_n_pfxs(intf), 0)
2924
2925 #
2926 # add prefixes to each interface. post-begin add the prefix from
2927 # interface X onto interface Y. this would normally be an error
2928 # since it would generate a 'duplicate address' warning. but in
2929 # this case, since what is newly downloaded is sane, it's ok
2930 #
2931 for intf in self.pg_interfaces:
2932 # 172.18.x.1/24
2933 addr = "172.18.%d.1" % intf.sw_if_index
2934 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2935
2936 self.vapi.sw_interface_address_replace_begin()
2937
2938 pfxs = []
2939 for intf in self.pg_interfaces:
2940 # 172.18.x.1/24
2941 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002942 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002943
2944 self.vapi.sw_interface_address_replace_end()
2945
2946 self.logger.info(self.vapi.cli("sh int addr"))
2947
2948 for intf in self.pg_interfaces:
2949 self.assertEqual(self.get_n_pfxs(intf), 1)
2950 for pfx in pfxs:
2951 self.assertTrue(pfx.query_vpp_config())
2952
2953
Neale Ranns8f5fef22020-12-21 08:29:34 +00002954class TestIPv4PathMTU(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002955 """IPv4 Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002956
2957 @classmethod
2958 def setUpClass(cls):
2959 super(TestIPv4PathMTU, cls).setUpClass()
2960
2961 cls.create_pg_interfaces(range(2))
2962
2963 # setup all interfaces
2964 for i in cls.pg_interfaces:
2965 i.admin_up()
2966 i.config_ip4()
2967 i.resolve_arp()
2968
2969 @classmethod
2970 def tearDownClass(cls):
2971 super(TestIPv4PathMTU, cls).tearDownClass()
2972
2973 def test_path_mtu(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002974 """Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002975
2976 #
2977 # The goal here is not to test that fragmentation works correctly,
2978 # that's done elsewhere, the intent is to ensure that the Path MTU
2979 # settings are honoured.
2980 #
2981 self.vapi.cli("adjacency counters enable")
2982
2983 # set the interface MTU to a reasonable value
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002984 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00002985
2986 self.pg1.generate_remote_hosts(4)
2987
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002988 p_2k = (
2989 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2990 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2991 / UDP(sport=1234, dport=5678)
2992 / Raw(b"0xa" * 640)
2993 )
2994 p_1k = (
2995 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2996 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2997 / UDP(sport=1234, dport=5678)
2998 / Raw(b"0xa" * 320)
2999 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003000
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003001 nbr = VppNeighbor(
3002 self, self.pg1.sw_if_index, self.pg1.remote_mac, self.pg1.remote_ip4
3003 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003004
3005 # this is now the interface MTU frags
3006 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3007 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3008
3009 # drop the path MTU for this neighbour to below the interface MTU
3010 # expect more frags
3011 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
3012
3013 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3014 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3015
3016 # print/format the adj delegate
3017 self.logger.info(self.vapi.cli("sh adj 5"))
3018
3019 # increase the path MTU to more than the interface
3020 # expect to use the interface MTU
3021 pmtu.modify(8192)
3022
3023 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3024 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3025
3026 # go back to an MTU from the path
3027 # wrap the call around mark-n-sweep to enusre updates clear stale
3028 self.vapi.ip_path_mtu_replace_begin()
3029 pmtu.modify(900)
3030 self.vapi.ip_path_mtu_replace_end()
3031
3032 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3033 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3034
3035 # raise the interface's MTU
3036 # should still use that of the path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003037 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003038 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3039 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3040
3041 # set path high and interface low
3042 pmtu.modify(2000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003043 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [900, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003044 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3045 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3046
3047 # remove the path MTU using the mark-n-sweep semantics
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003048 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003049 self.vapi.ip_path_mtu_replace_begin()
3050 self.vapi.ip_path_mtu_replace_end()
3051
3052 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3053 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3054
3055 #
3056 # set path MTU for a neighbour that doesn't exist, yet
3057 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003058 pmtu2 = VppIpPathMtu(self, self.pg1.remote_hosts[2].ip4, 900).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003059
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003060 p_2k = (
3061 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3062 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3063 / UDP(sport=1234, dport=5678)
3064 / Raw(b"0xa" * 640)
3065 )
3066 p_1k = (
3067 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3068 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3069 / UDP(sport=1234, dport=5678)
3070 / Raw(b"0xa" * 320)
3071 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003072
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003073 nbr2 = VppNeighbor(
3074 self,
3075 self.pg1.sw_if_index,
3076 self.pg1.remote_hosts[2].mac,
3077 self.pg1.remote_hosts[2].ip4,
3078 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003079
3080 # should frag to the path MTU
3081 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3082 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3083
3084 # remove and re-add the neighbour
3085 nbr2.remove_vpp_config()
3086 nbr2.add_vpp_config()
3087
3088 # should frag to the path MTU
3089 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3090 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3091
3092 #
3093 # set PMTUs for many peers
3094 #
3095 N_HOSTS = 16
3096 self.pg1.generate_remote_hosts(16)
3097 self.pg1.configure_ipv4_neighbors()
3098
3099 for h in range(N_HOSTS):
3100 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
3101 pmtu.add_vpp_config()
3102 self.assertTrue(pmtu.query_vpp_config())
3103
3104 self.logger.info(self.vapi.cli("sh ip pmtu"))
3105 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
3106 self.assertEqual(N_HOSTS, len(dump))
3107
3108 for h in range(N_HOSTS):
3109 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
3110 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
3111
3112 # should frag to the path MTU
3113 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3114 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3115
3116
Neale Ranns50bd1d32021-10-08 07:16:12 +00003117class TestIPv4ItfRebind(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003118 """IPv4 Interface Bind w/ attached routes"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003119
3120 def setUp(self):
3121 super(TestIPv4ItfRebind, self).setUp()
3122
3123 self.create_pg_interfaces(range(3))
3124
3125 def tearDown(self):
3126 super(TestIPv4ItfRebind, self).tearDown()
3127
3128 def test_rebind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003129 """Import to no import"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003130
3131 TABLE_ID = 1
3132 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
3133 self.pg1.set_table_ip4(TABLE_ID)
3134
3135 for i in self.pg_interfaces:
3136 i.admin_up()
3137 i.config_ip4()
3138 i.resolve_arp()
3139
3140 # add an attached route via an pg0
3141 # in a different table. this prefix should import
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003142 rt = VppIpRoute(
3143 self,
3144 self.pg0.local_ip4,
3145 24,
3146 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
3147 table_id=TABLE_ID,
3148 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003149
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003150 p = (
3151 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3152 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3153 / UDP(sport=1234, dport=5678)
3154 / Raw(b"0xa" * 640)
3155 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003156
3157 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3158 self.assertFalse(rx[0].haslayer(ARP))
3159
3160 # then bind pg0 to a new table
3161 # so the prefix no longer imports
3162 self.pg0.unconfig_ip4()
3163 self.pg0.set_table_ip4(TABLE_ID)
3164 self.pg0.config_ip4()
3165 self.pg0.resolve_arp()
3166
3167 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3168 self.assertFalse(rx[0].haslayer(ARP))
3169
3170 # revert back to imported
3171 self.pg0.unconfig_ip4()
3172 self.pg0.set_table_ip4(0)
3173 self.pg0.config_ip4()
3174 self.pg0.resolve_arp()
3175
3176 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3177 self.assertFalse(rx[0].haslayer(ARP))
3178
3179 # cleanup
3180 for i in self.pg_interfaces:
3181 i.unconfig_ip4()
3182 i.set_table_ip4(0)
3183 i.admin_down()
3184
3185 rt.remove_vpp_config()
3186 tbl.remove_vpp_config()
3187
3188 def test_delete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003189 """Swap import tables"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003190
3191 TABLE_ID1 = 1
3192 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
3193 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
3194 TABLE_ID2 = 2
3195 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
3196 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
3197
3198 # table mappings
3199 self.pg1.set_table_ip4(TABLE_ID1)
3200 self.pg1.set_table_ip6(TABLE_ID1)
3201 self.pg2.set_table_ip4(TABLE_ID2)
3202 self.pg2.set_table_ip6(TABLE_ID2)
3203
3204 for i in self.pg_interfaces:
3205 i.admin_up()
3206 i.config_ip4()
3207 i.resolve_arp()
3208
3209 # add an attached route in the default table via pg0
3210 # this should import to table 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003211 rt4 = VppIpRoute(
3212 self,
3213 self.pg1.local_ip4,
3214 24,
3215 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3216 ).add_vpp_config()
3217 rt6 = VppIpRoute(
3218 self,
3219 self.pg1.local_ip6,
3220 64,
3221 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3222 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003223
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003224 p1 = (
3225 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3226 / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
3227 / UDP(sport=1234, dport=5678)
3228 / Raw(b"0xa" * 640)
3229 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003230
3231 # inject into table 0
3232 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3233 self.assertFalse(rx[0].haslayer(ARP))
3234
3235 # swap the attached interface to table 2
3236 self.pg1.unconfig_ip4()
3237 self.pg1.unconfig_ip6()
3238 self.pg1.set_table_ip4(TABLE_ID2)
3239 self.pg1.set_table_ip6(TABLE_ID2)
3240 self.pg1.config_ip4()
3241 self.pg1.config_ip6()
3242 self.pg1.resolve_arp()
3243
3244 # delete table 1
3245 tbl1_4.flush()
3246 tbl1_6.flush()
3247 tbl1_4.remove_vpp_config()
3248 tbl1_6.remove_vpp_config()
3249
3250 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3251 self.assertFalse(rx[0].haslayer(ARP))
3252
3253 for i in self.pg_interfaces:
3254 i.unconfig_ip4()
3255 i.unconfig_ip6()
3256 i.set_table_ip4(0)
3257 i.set_table_ip6(0)
3258 i.admin_down()
3259
3260
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003261if __name__ == "__main__":
Klement Sekeraf62ae122016-10-11 11:47:09 +02003262 unittest.main(testRunner=VppTestRunner)