blob: 2f130f59a4a26938018dc6336c679bfca9a9f62a [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
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09009from scapy.contrib.gtp import GTP_U_Header
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080010from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
Neale Rannsaa7cfd02022-03-24 12:28:42 +000011from scapy.layers.inet6 import IPv6
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080012from scapy.layers.l2 import Ether, Dot1Q, ARP
13from scapy.packet import Raw
14from six import moves
15
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000016from framework import tag_fixme_vpp_workers
Damjan Marionf56b77a2016-10-03 19:44:57 +020017from framework import VppTestCase, VppTestRunner
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080018from util import ppp
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020019from vpp_ip_route import (
20 VppIpRoute,
21 VppRoutePath,
22 VppIpMRoute,
23 VppMRoutePath,
24 VppMplsIpBind,
25 VppMplsTable,
26 VppIpTable,
27 FibPathType,
28 find_route,
29 VppIpInterfaceAddress,
30 find_route_in_dump,
31 find_mroute_in_dump,
32)
Neale Ranns8f5fef22020-12-21 08:29:34 +000033from vpp_ip import VppIpPuntPolicer, VppIpPuntRedirect, VppIpPathMtu
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080034from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Klement Sekerafd1f56a2021-11-22 21:25:57 +010035from vpp_papi import vpp_papi, VppEnum
Neale Ranns0b6a8572019-10-30 17:34:14 +000036from vpp_neighbor import VppNeighbor
Neale Ranns9efcee62019-11-26 19:30:08 +000037from vpp_lo_interface import VppLoInterface
Brian Russellc8f3cdf2021-01-19 16:57:42 +000038from vpp_policer import VppPolicer, PolicerAction
Damjan Marionf56b77a2016-10-03 19:44:57 +020039
Paul Vinciguerra4271c972019-05-14 13:25:49 -040040NUM_PKTS = 67
41
Damjan Marionf56b77a2016-10-03 19:44:57 +020042
Klement Sekeraf62ae122016-10-11 11:47:09 +020043class TestIPv4(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044 """IPv4 Test Case"""
Damjan Marionf56b77a2016-10-03 19:44:57 +020045
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070046 @classmethod
47 def setUpClass(cls):
48 super(TestIPv4, cls).setUpClass()
49
50 @classmethod
51 def tearDownClass(cls):
52 super(TestIPv4, cls).tearDownClass()
53
Klement Sekeraf62ae122016-10-11 11:47:09 +020054 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010055 """
56 Perform test setup before test case.
57
58 **Config:**
59 - create 3 pg interfaces
60 - untagged pg0 interface
61 - Dot1Q subinterface on pg1
62 - Dot1AD subinterface on pg2
63 - setup interfaces:
64 - put it into UP state
65 - set IPv4 addresses
66 - resolve neighbor address using ARP
67 - configure 200 fib entries
68
69 :ivar list interfaces: pg interfaces and subinterfaces.
70 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010071 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020073
Klement Sekeraf62ae122016-10-11 11:47:09 +020074 # create 3 pg interfaces
75 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020076
Klement Sekeraf62ae122016-10-11 11:47:09 +020077 # create 2 subinterfaces for pg1 and pg2
78 self.sub_interfaces = [
79 VppDot1QSubint(self, self.pg1, 100),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020080 VppDot1ADSubint(self, self.pg2, 200, 300, 400),
81 ]
Damjan Marionf56b77a2016-10-03 19:44:57 +020082
Klement Sekeraf62ae122016-10-11 11:47:09 +020083 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
84 self.flows = dict()
85 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
86 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
87 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020088
Klement Sekeraf62ae122016-10-11 11:47:09 +020089 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020090 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020091
Klement Sekeraf62ae122016-10-11 11:47:09 +020092 self.interfaces = list(self.pg_interfaces)
93 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020094
Klement Sekeraf62ae122016-10-11 11:47:09 +020095 # setup all interfaces
96 for i in self.interfaces:
97 i.admin_up()
98 i.config_ip4()
99 i.resolve_arp()
100
Matej Klotton86d87c42016-11-11 11:38:55 +0100101 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200102
103 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100104 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200105 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700106
107 def show_commands_at_teardown(self):
Neale Rannscbe25aa2019-09-30 10:53:31 +0000108 self.logger.info(self.vapi.cli("show ip4 neighbors"))
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700109 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200110
Jan Geletye6c78ee2018-06-26 12:24:03 +0200111 def modify_packet(self, src_if, packet_size, pkt):
112 """Add load, set destination IP and extend packet to required packet
113 size for defined interface.
114
115 :param VppInterface src_if: Interface to create packet for.
116 :param int packet_size: Required packet size.
117 :param Scapy pkt: Packet to be modified.
118 """
Ole Troan6ed154f2019-10-15 19:31:55 +0200119 dst_if_idx = int(packet_size / 10 % 2)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200120 dst_if = self.flows[src_if][dst_if_idx]
121 info = self.create_packet_info(src_if, dst_if)
122 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200123 p = pkt / Raw(payload)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200124 p[IP].dst = dst_if.remote_ip4
125 info.data = p.copy()
126 if isinstance(src_if, VppSubInterface):
127 p = src_if.add_dot1_layer(p)
128 self.extend_packet(p, packet_size)
129
130 return p
131
132 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100133 """Create input packet stream for defined interface.
134
135 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100136 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200137 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200138 pkt_tmpl = (
139 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
140 / IP(src=src_if.remote_ip4)
141 / UDP(sport=1234, dport=1234)
142 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200143
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200144 pkts = [
145 self.modify_packet(src_if, i, pkt_tmpl)
146 for i in moves.range(
147 self.pg_if_packet_sizes[0], self.pg_if_packet_sizes[1], 10
148 )
149 ]
150 pkts_b = [
151 self.modify_packet(src_if, i, pkt_tmpl)
152 for i in moves.range(
153 self.pg_if_packet_sizes[1] + hdr_ext,
154 self.pg_if_packet_sizes[2] + hdr_ext,
155 50,
156 )
157 ]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200158 pkts.extend(pkts_b)
159
Damjan Marionf56b77a2016-10-03 19:44:57 +0200160 return pkts
161
Klement Sekeraf62ae122016-10-11 11:47:09 +0200162 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100163 """Verify captured input packet stream for defined interface.
164
165 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200166 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100167 :param list capture: Captured packet stream.
168 """
169 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200170 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200171 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200172 last_info[i.sw_if_index] = None
173 is_sub_if = False
174 dst_sw_if_index = dst_if.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200175 if hasattr(dst_if, "parent"):
Klement Sekeraf62ae122016-10-11 11:47:09 +0200176 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200177 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200178 if is_sub_if:
179 # Check VLAN tags and Ethernet header
180 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200181 self.assertTrue(Dot1Q not in packet)
182 try:
183 ip = packet[IP]
184 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800185 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200186 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200187 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100188 self.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200189 "Got packet on port %s: src=%u (id=%u)"
190 % (dst_if.name, payload_info.src, packet_index)
191 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200192 next_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200193 payload_info.src, dst_sw_if_index, last_info[payload_info.src]
194 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200195 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200196 self.assertTrue(next_info is not None)
197 self.assertEqual(packet_index, next_info.index)
198 saved_packet = next_info.data
199 # Check standard fields
200 self.assertEqual(ip.src, saved_packet[IP].src)
201 self.assertEqual(ip.dst, saved_packet[IP].dst)
202 self.assertEqual(udp.sport, saved_packet[UDP].sport)
203 self.assertEqual(udp.dport, saved_packet[UDP].dport)
204 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100205 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200206 raise
207 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200208 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200209 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index]
210 )
211 self.assertTrue(
212 remaining_packet is None,
213 "Interface %s: Packet expected from interface %s "
214 "didn't arrive" % (dst_if.name, i.name),
215 )
Damjan Marionf56b77a2016-10-03 19:44:57 +0200216
217 def test_fib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218 """IPv4 FIB test
Matej Klotton86d87c42016-11-11 11:38:55 +0100219
220 Test scenario:
221
222 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200223 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100224 - Send and verify received packets on each interface.
225 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200226
Jan Geletye6c78ee2018-06-26 12:24:03 +0200227 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200228 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200229
Klement Sekeraf62ae122016-10-11 11:47:09 +0200230 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200231 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200232 i.parent.add_stream(pkts)
233
234 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200235 self.pg_start()
236
Klement Sekeraf62ae122016-10-11 11:47:09 +0200237 pkts = self.pg0.get_capture()
238 self.verify_capture(self.pg0, pkts)
239
240 for i in self.sub_interfaces:
241 pkts = i.parent.get_capture()
242 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200243
244
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400245class TestIPv4RouteLookup(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200246 """IPv4 Route Lookup Test Case"""
247
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400248 routes = []
249
250 def route_lookup(self, prefix, exact):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200251 return self.vapi.api(
252 self.vapi.papi.ip_route_lookup,
253 {
254 "table_id": 0,
255 "exact": exact,
256 "prefix": prefix,
257 },
258 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400259
260 @classmethod
261 def setUpClass(cls):
262 super(TestIPv4RouteLookup, cls).setUpClass()
263
264 @classmethod
265 def tearDownClass(cls):
266 super(TestIPv4RouteLookup, cls).tearDownClass()
267
268 def setUp(self):
269 super(TestIPv4RouteLookup, self).setUp()
270
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200271 drop_nh = VppRoutePath(
272 "127.0.0.1", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP
273 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400274
275 # Add 3 routes
276 r = VppIpRoute(self, "1.1.0.0", 16, [drop_nh])
277 r.add_vpp_config()
278 self.routes.append(r)
279
280 r = VppIpRoute(self, "1.1.1.0", 24, [drop_nh])
281 r.add_vpp_config()
282 self.routes.append(r)
283
284 r = VppIpRoute(self, "1.1.1.1", 32, [drop_nh])
285 r.add_vpp_config()
286 self.routes.append(r)
287
288 def tearDown(self):
289 # Remove the routes we added
290 for r in self.routes:
291 r.remove_vpp_config()
292
293 super(TestIPv4RouteLookup, self).tearDown()
294
295 def test_exact_match(self):
296 # Verify we find the host route
297 prefix = "1.1.1.1/32"
298 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200299 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400300
301 # Verify we find a middle prefix route
302 prefix = "1.1.1.0/24"
303 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400305
306 # Verify we do not find an available LPM.
307 with self.vapi.assert_negative_api_retval():
308 self.route_lookup("1.1.1.2/32", True)
309
310 def test_longest_prefix_match(self):
311 # verify we find lpm
312 lpm_prefix = "1.1.1.0/24"
313 result = self.route_lookup("1.1.1.2/32", False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200314 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400315
316 # Verify we find the exact when not requested
317 result = self.route_lookup(lpm_prefix, False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400319
320 # Can't seem to delete the default route so no negative LPM test.
321
322
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500323class TestIPv4IfAddrRoute(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200324 """IPv4 Interface Addr Route Test Case"""
Matthew G Smith88d29a92019-07-17 10:01:17 -0500325
326 @classmethod
327 def setUpClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500328 super(TestIPv4IfAddrRoute, cls).setUpClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500329
330 @classmethod
331 def tearDownClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500332 super(TestIPv4IfAddrRoute, cls).tearDownClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500333
334 def setUp(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500335 super(TestIPv4IfAddrRoute, self).setUp()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500336
337 # create 1 pg interface
338 self.create_pg_interfaces(range(1))
339
340 for i in self.pg_interfaces:
341 i.admin_up()
342 i.config_ip4()
343 i.resolve_arp()
344
345 def tearDown(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500346 super(TestIPv4IfAddrRoute, self).tearDown()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500347 for i in self.pg_interfaces:
348 i.unconfig_ip4()
349 i.admin_down()
350
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500351 def test_ipv4_ifaddrs_same_prefix(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200352 """IPv4 Interface Addresses Same Prefix test
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500353
354 Test scenario:
355
356 - Verify no route in FIB for prefix 10.10.10.0/24
357 - Configure IPv4 address 10.10.10.10/24 on an interface
358 - Verify route in FIB for prefix 10.10.10.0/24
359 - Configure IPv4 address 10.10.10.20/24 on an interface
360 - Delete 10.10.10.10/24 from interface
361 - Verify route in FIB for prefix 10.10.10.0/24
362 - Delete 10.10.10.20/24 from interface
363 - Verify no route in FIB for prefix 10.10.10.0/24
364 """
365
366 # create two addresses, verify route not present
Neale Rannsefd7bc22019-11-11 08:32:34 +0000367 if_addr1 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.10", 24)
368 if_addr2 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.20", 24)
369 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500370 self.assertFalse(find_route(self, "10.10.10.10", 32))
371 self.assertFalse(find_route(self, "10.10.10.20", 32))
372 self.assertFalse(find_route(self, "10.10.10.255", 32))
373 self.assertFalse(find_route(self, "10.10.10.0", 32))
374
375 # configure first address, verify route present
376 if_addr1.add_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000377 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500378 self.assertTrue(find_route(self, "10.10.10.10", 32))
379 self.assertFalse(find_route(self, "10.10.10.20", 32))
380 self.assertTrue(find_route(self, "10.10.10.255", 32))
381 self.assertTrue(find_route(self, "10.10.10.0", 32))
382
383 # configure second address, delete first, verify route not removed
384 if_addr2.add_vpp_config()
385 if_addr1.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000386 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
387 self.assertTrue(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500388 self.assertFalse(find_route(self, "10.10.10.10", 32))
389 self.assertTrue(find_route(self, "10.10.10.20", 32))
390 self.assertTrue(find_route(self, "10.10.10.255", 32))
391 self.assertTrue(find_route(self, "10.10.10.0", 32))
392
393 # delete second address, verify route removed
394 if_addr2.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000395 self.assertFalse(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500396 self.assertFalse(find_route(self, "10.10.10.10", 32))
397 self.assertFalse(find_route(self, "10.10.10.20", 32))
398 self.assertFalse(find_route(self, "10.10.10.255", 32))
399 self.assertFalse(find_route(self, "10.10.10.0", 32))
400
Matthew G Smith88d29a92019-07-17 10:01:17 -0500401 def test_ipv4_ifaddr_route(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200402 """IPv4 Interface Address Route test
Matthew G Smith88d29a92019-07-17 10:01:17 -0500403
404 Test scenario:
405
406 - Create loopback
407 - Configure IPv4 address on loopback
408 - Verify that address is not in the FIB
409 - Bring loopback up
410 - Verify that address is in the FIB now
411 - Bring loopback down
412 - Verify that address is not in the FIB anymore
413 - Bring loopback up
414 - Configure IPv4 address on loopback
415 - Verify that address is in the FIB now
416 """
417
418 # create a loopback and configure IPv4
419 loopbacks = self.create_loopback_interfaces(1)
420 lo_if = self.lo_interfaces[0]
421
422 lo_if.local_ip4_prefix_len = 32
423 lo_if.config_ip4()
424
425 # The intf was down when addr was added -> entry not in FIB
426 fib4_dump = self.vapi.ip_route_dump(0)
427 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
428
429 # When intf is brought up, entry is added
430 lo_if.admin_up()
431 fib4_dump = self.vapi.ip_route_dump(0)
432 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
433
434 # When intf is brought down, entry is removed
435 lo_if.admin_down()
436 fib4_dump = self.vapi.ip_route_dump(0)
437 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
438
439 # Remove addr, bring up interface, re-add -> entry in FIB
440 lo_if.unconfig_ip4()
441 lo_if.admin_up()
442 lo_if.config_ip4()
443 fib4_dump = self.vapi.ip_route_dump(0)
444 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
445
yedgdbd366b2020-05-14 10:51:53 +0800446 def test_ipv4_ifaddr_del(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200447 """Delete an interface address that does not exist"""
yedgdbd366b2020-05-14 10:51:53 +0800448
449 loopbacks = self.create_loopback_interfaces(1)
450 lo = self.lo_interfaces[0]
451
452 lo.config_ip4()
453 lo.admin_up()
454
455 #
456 # try and remove pg0's subnet from lo
457 #
458 with self.vapi.assert_negative_api_retval():
459 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200460 sw_if_index=lo.sw_if_index, prefix=self.pg0.local_ip4_prefix, is_add=0
461 )
yedgdbd366b2020-05-14 10:51:53 +0800462
Matthew G Smith88d29a92019-07-17 10:01:17 -0500463
Jan Geletye6c78ee2018-06-26 12:24:03 +0200464class TestICMPEcho(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200465 """ICMP Echo Test Case"""
Jan Geletye6c78ee2018-06-26 12:24:03 +0200466
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700467 @classmethod
468 def setUpClass(cls):
469 super(TestICMPEcho, cls).setUpClass()
470
471 @classmethod
472 def tearDownClass(cls):
473 super(TestICMPEcho, cls).tearDownClass()
474
Jan Geletye6c78ee2018-06-26 12:24:03 +0200475 def setUp(self):
476 super(TestICMPEcho, self).setUp()
477
478 # create 1 pg interface
479 self.create_pg_interfaces(range(1))
480
481 for i in self.pg_interfaces:
482 i.admin_up()
483 i.config_ip4()
484 i.resolve_arp()
485
486 def tearDown(self):
487 super(TestICMPEcho, self).tearDown()
488 for i in self.pg_interfaces:
489 i.unconfig_ip4()
490 i.admin_down()
491
492 def test_icmp_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 """VPP replies to ICMP Echo Request
Jan Geletye6c78ee2018-06-26 12:24:03 +0200494
495 Test scenario:
496
497 - Receive ICMP Echo Request message on pg0 interface.
498 - Check outgoing ICMP Echo Reply message on pg0 interface.
499 """
500
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200501 icmp_id = 0xB
Jan Geletye6c78ee2018-06-26 12:24:03 +0200502 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200503 icmp_load = b"\x0a" * 18
504 p_echo_request = (
505 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
506 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
507 / ICMP(id=icmp_id, seq=icmp_seq)
508 / Raw(load=icmp_load)
509 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200510
511 self.pg0.add_stream(p_echo_request)
512 self.pg_enable_capture(self.pg_interfaces)
513 self.pg_start()
514
515 rx = self.pg0.get_capture(1)
516 rx = rx[0]
517 ether = rx[Ether]
518 ipv4 = rx[IP]
519 icmp = rx[ICMP]
520
521 self.assertEqual(ether.src, self.pg0.local_mac)
522 self.assertEqual(ether.dst, self.pg0.remote_mac)
523
524 self.assertEqual(ipv4.src, self.pg0.local_ip4)
525 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
526
527 self.assertEqual(icmptypes[icmp.type], "echo-reply")
528 self.assertEqual(icmp.id, icmp_id)
529 self.assertEqual(icmp.seq, icmp_seq)
530 self.assertEqual(icmp[Raw].load, icmp_load)
531
532
Matej Klotton16a14cd2016-12-07 15:09:13 +0100533class TestIPv4FibCrud(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 """FIB - add/update/delete - ip4 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100535
536 Test scenario:
537 - add 1k,
538 - del 100,
539 - add new 1k,
540 - del 1.5k
541
Klement Sekerada505f62017-01-04 12:58:53 +0100542 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100543 """
544
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200545 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100546 """
547
548 :param start_dest_addr:
549 :param next_hop_addr:
550 :param count:
551 :return list: added ips with 32 prefix
552 """
Neale Ranns097fa662018-05-01 05:17:55 -0700553 routes = []
554 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 r = VppIpRoute(
556 self,
557 start_dest_addr % (i + start),
558 32,
559 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
560 )
Neale Ranns097fa662018-05-01 05:17:55 -0700561 r.add_vpp_config()
562 routes.append(r)
563 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100564
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200565 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
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
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001213 fhcv2 = VppEnum.vl_api_ip_flow_hash_config_v2_t
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001214 af = VppEnum.vl_api_address_family_t
1215
Neale Ranns227038a2017-04-21 01:07:59 -07001216 #
1217 # An array of packets that differ only in the destination port
1218 #
Neale Ranns71275e32017-05-25 12:38:58 -07001219 port_ip_pkts = []
1220 port_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001221 port_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001222
1223 #
1224 # An array of packets that differ only in the source address
1225 #
Neale Ranns71275e32017-05-25 12:38:58 -07001226 src_ip_pkts = []
1227 src_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001228 src_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001229
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001230 for ii in range(NUM_PKTS):
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001231 internal_src_ip_hdr = IP(dst="10.0.0.1", src="20.0.0.1")
1232
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001233 port_ip_hdr = (
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001234 internal_src_ip_hdr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001235 / UDP(sport=1234, dport=1234 + ii)
1236 / Raw(b"\xa5" * 100)
1237 )
1238 port_ip_pkts.append(
1239 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)
1240 )
1241 port_mpls_pkts.append(
1242 (
1243 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1244 / MPLS(label=66, ttl=2)
1245 / port_ip_hdr
1246 )
1247 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001248 port_gtp_pkts.append(
1249 (
1250 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1251 / internal_src_ip_hdr
1252 / UDP(sport=2152, dport=2152, chksum=0)
1253 / GTP_U_Header(gtp_type="g_pdu", teid=200)
1254 / Raw(b"\xa5" * 100)
1255 )
1256 )
Neale Ranns71275e32017-05-25 12:38:58 -07001257
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001258 src_ip_hdr = (
1259 IP(dst="10.0.0.1", src="20.0.0.%d" % ii)
1260 / UDP(sport=1234, dport=1234)
1261 / Raw(b"\xa5" * 100)
1262 )
1263 src_ip_pkts.append(
1264 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)
1265 )
1266 src_mpls_pkts.append(
1267 (
1268 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1269 / MPLS(label=66, ttl=2)
1270 / src_ip_hdr
1271 )
1272 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001273 src_gtp_pkts.append(
1274 (
1275 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1276 / IP(dst="10.0.0.1", src="20.0.0.1")
1277 / UDP(sport=2152, dport=2152, chksum=0)
1278 / GTP_U_Header(gtp_type="g_pdu", teid=ii)
1279 / Raw(b"\xa5" * 100)
1280 )
1281 )
Neale Ranns227038a2017-04-21 01:07:59 -07001282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001283 route_10_0_0_1 = VppIpRoute(
1284 self,
1285 "10.0.0.1",
1286 32,
1287 [
1288 VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index),
1289 VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index),
1290 ],
1291 )
Neale Ranns227038a2017-04-21 01:07:59 -07001292 route_10_0_0_1.add_vpp_config()
1293
Neale Ranns71275e32017-05-25 12:38:58 -07001294 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1295 binding.add_vpp_config()
1296
Neale Ranns227038a2017-04-21 01:07:59 -07001297 #
1298 # inject the packet on pg0 - expect load-balancing across the 2 paths
1299 # - since the default hash config is to use IP src,dst and port
1300 # src,dst
1301 # We are not going to ensure equal amounts of packets across each link,
1302 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001303 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001304 # balancing. So instead just ensure there is traffic on each link.
1305 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001306 rx = self.send_and_expect_load_balancing(
1307 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1308 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001309 n_ip_pg0 = len(rx[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001310 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1311 self.send_and_expect_load_balancing(
1312 self.pg0, port_mpls_pkts, [self.pg1, self.pg2]
1313 )
1314 rx = self.send_and_expect_load_balancing(
1315 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1316 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001317 n_mpls_pg0 = len(rx[0])
1318
1319 #
1320 # change the router ID and expect the distribution changes
1321 #
1322 self.vapi.set_ip_flow_hash_router_id(router_id=0x11111111)
1323
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001324 rx = self.send_and_expect_load_balancing(
1325 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1326 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001327 self.assertNotEqual(n_ip_pg0, len(rx[0]))
1328
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001329 rx = self.send_and_expect_load_balancing(
1330 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1331 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001332 self.assertNotEqual(n_mpls_pg0, len(rx[0]))
Neale Ranns227038a2017-04-21 01:07:59 -07001333
1334 #
1335 # change the flow hash config so it's only IP src,dst
1336 # - now only the stream with differing source address will
1337 # load-balance
1338 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001339 self.vapi.set_ip_flow_hash_v2(
1340 af=af.ADDRESS_IP4,
1341 table_id=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 flow_hash_config=(
1343 fhc.IP_API_FLOW_HASH_SRC_IP
1344 | fhc.IP_API_FLOW_HASH_DST_IP
1345 | fhc.IP_API_FLOW_HASH_PROTO
1346 ),
1347 )
Neale Ranns227038a2017-04-21 01:07:59 -07001348
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001349 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1350 self.send_and_expect_load_balancing(
1351 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1352 )
Neale Ranns227038a2017-04-21 01:07:59 -07001353
Neale Ranns699bea22022-02-17 09:22:16 +00001354 self.send_and_expect_only(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001355
1356 #
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001357 # this case gtp v1 teid key LB
1358 #
1359 self.vapi.set_ip_flow_hash_v3(
1360 af=af.ADDRESS_IP4,
1361 table_id=0,
1362 flow_hash_config=(
1363 fhcv2.IP_API_V2_FLOW_HASH_SRC_IP
1364 | fhcv2.IP_API_V2_FLOW_HASH_PROTO
1365 | fhcv2.IP_API_V2_FLOW_HASH_GTPV1_TEID
1366 ),
1367 )
1368 self.logger.info(self.vapi.cli("show ip fib"))
1369
1370 self.send_and_expect_load_balancing(
1371 self.pg0, src_gtp_pkts, [self.pg1, self.pg2]
1372 )
1373
1374 self.send_and_expect_only(self.pg0, port_gtp_pkts, self.pg2)
1375
1376 #
Neale Ranns227038a2017-04-21 01:07:59 -07001377 # change the flow hash config back to defaults
1378 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001379 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 -07001380
1381 #
1382 # Recursive prefixes
1383 # - testing that 2 stages of load-balancing occurs and there is no
1384 # polarisation (i.e. only 2 of 4 paths are used)
1385 #
1386 port_pkts = []
1387 src_pkts = []
1388
1389 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001390 port_pkts.append(
1391 (
1392 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1393 / IP(dst="1.1.1.1", src="20.0.0.1")
1394 / UDP(sport=1234, dport=1234 + ii)
1395 / Raw(b"\xa5" * 100)
1396 )
1397 )
1398 src_pkts.append(
1399 (
1400 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1401 / IP(dst="1.1.1.1", src="20.0.0.%d" % ii)
1402 / UDP(sport=1234, dport=1234)
1403 / Raw(b"\xa5" * 100)
1404 )
1405 )
Neale Ranns227038a2017-04-21 01:07:59 -07001406
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001407 route_10_0_0_2 = VppIpRoute(
1408 self,
1409 "10.0.0.2",
1410 32,
1411 [
1412 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1413 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1414 ],
1415 )
Neale Ranns227038a2017-04-21 01:07:59 -07001416 route_10_0_0_2.add_vpp_config()
1417
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001418 route_1_1_1_1 = VppIpRoute(
1419 self,
1420 "1.1.1.1",
1421 32,
1422 [
1423 VppRoutePath("10.0.0.2", 0xFFFFFFFF),
1424 VppRoutePath("10.0.0.1", 0xFFFFFFFF),
1425 ],
1426 )
Neale Ranns227038a2017-04-21 01:07:59 -07001427 route_1_1_1_1.add_vpp_config()
1428
1429 #
1430 # inject the packet on pg0 - expect load-balancing across all 4 paths
1431 #
1432 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 self.send_and_expect_load_balancing(
1434 self.pg0, port_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1435 )
1436 self.send_and_expect_load_balancing(
1437 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1438 )
Neale Ranns227038a2017-04-21 01:07:59 -07001439
Neale Ranns42e6b092017-07-31 02:56:03 -07001440 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001441 # bring down pg1 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001442 #
1443 self.pg1.link_down()
1444
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001445 rx = self.send_and_expect_load_balancing(
1446 self.pg0, src_pkts, [self.pg2, self.pg3, self.pg4]
1447 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001448 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001449
1450 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001451 # bring down pg2 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001452 #
1453 self.pg2.link_down()
1454
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001455 rx = self.send_and_expect_load_balancing(
1456 self.pg0, src_pkts, [self.pg3, self.pg4]
1457 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001458 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001459
1460 #
1461 # bring the links back up - expect LB over all again
1462 #
1463 self.pg1.link_up()
1464 self.pg2.link_up()
1465
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001466 rx = self.send_and_expect_load_balancing(
1467 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1468 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001469 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001470
1471 #
1472 # The same link-up/down but this time admin state
1473 #
1474 self.pg1.admin_down()
1475 self.pg2.admin_down()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001476 rx = self.send_and_expect_load_balancing(
1477 self.pg0, src_pkts, [self.pg3, self.pg4]
1478 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001479 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001480 self.pg1.admin_up()
1481 self.pg2.admin_up()
1482 self.pg1.resolve_arp()
1483 self.pg2.resolve_arp()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001484 rx = self.send_and_expect_load_balancing(
1485 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1486 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001487 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001488
1489 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001490 # Recursive prefixes
1491 # - testing that 2 stages of load-balancing, no choices
1492 #
1493 port_pkts = []
1494
1495 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001496 port_pkts.append(
1497 (
1498 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1499 / IP(dst="1.1.1.2", src="20.0.0.2")
1500 / UDP(sport=1234, dport=1234 + ii)
1501 / Raw(b"\xa5" * 100)
1502 )
1503 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001504
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001505 route_10_0_0_3 = VppIpRoute(
1506 self,
1507 "10.0.0.3",
1508 32,
1509 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
1510 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001511 route_10_0_0_3.add_vpp_config()
1512
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001513 route_1_1_1_2 = VppIpRoute(
1514 self, "1.1.1.2", 32, [VppRoutePath("10.0.0.3", 0xFFFFFFFF)]
1515 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001516 route_1_1_1_2.add_vpp_config()
1517
1518 #
Neale Ranns63480742019-03-13 06:41:52 -07001519 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001520 #
1521 self.vapi.cli("clear trace")
Neale Ranns699bea22022-02-17 09:22:16 +00001522 self.send_and_expect_only(self.pg0, port_pkts, self.pg3)
Neale Ranns42e6b092017-07-31 02:56:03 -07001523
Neale Ranns63480742019-03-13 06:41:52 -07001524 #
1525 # Add a LB route in the presence of a down link - expect no
1526 # packets over the down link
1527 #
1528 self.pg3.link_down()
1529
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001530 route_10_0_0_3 = VppIpRoute(
1531 self,
1532 "10.0.0.3",
1533 32,
1534 [
1535 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1536 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1537 ],
1538 )
Neale Ranns63480742019-03-13 06:41:52 -07001539 route_10_0_0_3.add_vpp_config()
1540
1541 port_pkts = []
1542 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001543 port_pkts.append(
1544 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1545 / IP(dst="10.0.0.3", src="20.0.0.2")
1546 / UDP(sport=1234, dport=1234 + ii)
1547 / Raw(b"\xa5" * 100)
1548 )
Neale Ranns63480742019-03-13 06:41:52 -07001549
Neale Ranns699bea22022-02-17 09:22:16 +00001550 self.send_and_expect_only(self.pg0, port_pkts, self.pg4)
Neale Ranns63480742019-03-13 06:41:52 -07001551
1552 # bring the link back up
1553 self.pg3.link_up()
1554
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 rx = self.send_and_expect_load_balancing(
1556 self.pg0, port_pkts, [self.pg3, self.pg4]
1557 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001558 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001559
Neale Ranns30d0fd42017-05-30 07:30:04 -07001560
1561class TestIPVlan0(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001562 """IPv4 VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001563
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001564 @classmethod
1565 def setUpClass(cls):
1566 super(TestIPVlan0, cls).setUpClass()
1567
1568 @classmethod
1569 def tearDownClass(cls):
1570 super(TestIPVlan0, cls).tearDownClass()
1571
Neale Ranns30d0fd42017-05-30 07:30:04 -07001572 def setUp(self):
1573 super(TestIPVlan0, self).setUp()
1574
1575 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001576 mpls_tbl = VppMplsTable(self, 0)
1577 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001578
1579 for i in self.pg_interfaces:
1580 i.admin_up()
1581 i.config_ip4()
1582 i.resolve_arp()
1583 i.enable_mpls()
1584
1585 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001586 for i in self.pg_interfaces:
1587 i.disable_mpls()
1588 i.unconfig_ip4()
1589 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001590 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001591
Neale Ranns30d0fd42017-05-30 07:30:04 -07001592 def test_ip_vlan_0(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001593 """IP VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001594
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001595 pkts = (
1596 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1597 / Dot1Q(vlan=0)
1598 / IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4)
1599 / UDP(sport=1234, dport=1234)
1600 / Raw(b"\xa5" * 100)
1601 ) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001602
1603 #
1604 # Expect that packets sent on VLAN-0 are forwarded on the
1605 # main interface.
1606 #
1607 self.send_and_expect(self.pg0, pkts, self.pg1)
1608
1609
Brian Russell318fdb82021-01-19 16:56:32 +00001610class IPPuntSetup(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001611 """Setup for IPv4 Punt Police/Redirect"""
Neale Rannsd91c1db2017-07-31 02:30:50 -07001612
Brian Russell318fdb82021-01-19 16:56:32 +00001613 def punt_setup(self):
Pavel Kotucek609e1212018-11-27 09:59:44 +01001614 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001615
1616 for i in self.pg_interfaces:
1617 i.admin_up()
1618 i.config_ip4()
1619 i.resolve_arp()
1620
Neale Ranns68577d22019-06-04 13:31:23 +00001621 # use UDP packet that have a port we need to explicitly
1622 # register to get punted.
1623 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1624 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1625 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1626 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001627 "type": pt_l4,
1628 "punt": {
1629 "l4": {
1630 "af": af_ip4,
1631 "protocol": udp_proto,
1632 "port": 1234,
Neale Ranns68577d22019-06-04 13:31:23 +00001633 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001634 },
Neale Ranns68577d22019-06-04 13:31:23 +00001635 }
1636
1637 self.vapi.set_punt(is_add=1, punt=punt_udp)
1638
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001639 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
1640 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001641 "type": pt_l4,
1642 "punt": {
1643 "l4": {
1644 "af": af_ip6,
1645 "protocol": udp_proto,
1646 "port": 1236,
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001647 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001648 },
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001649 }
1650
1651 self.vapi.set_punt(is_add=1, punt=punt_udp)
1652
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001653 self.pkt = (
1654 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1655 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1656 / UDP(sport=1234, dport=1234)
1657 / Raw(b"\xa5" * 100)
1658 )
Neale Rannsd91c1db2017-07-31 02:30:50 -07001659
Brian Russell318fdb82021-01-19 16:56:32 +00001660 def punt_teardown(self):
1661 for i in self.pg_interfaces:
1662 i.unconfig_ip4()
1663 i.admin_down()
1664
1665
1666class TestIPPunt(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001667 """IPv4 Punt Police/Redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001668
1669 def setUp(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001670 super().setUp()
1671 super().punt_setup()
Brian Russell318fdb82021-01-19 16:56:32 +00001672
1673 def tearDown(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001674 super().punt_teardown()
1675 super().tearDown()
1676
1677 def test_ip_punt_api_validation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001678 """IP punt API parameter validation"""
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001679
1680 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001681 punt = {
1682 "rx_sw_if_index": self.pg0.sw_if_index,
1683 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1684 "n_paths": 1000000,
1685 "paths": [],
1686 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001687
1688 with self.assertRaises(vpp_papi.VPPIOError):
1689 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
1690
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001691 punt = {
1692 "rx_sw_if_index": self.pg0.sw_if_index,
1693 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1694 "n_paths": 0,
1695 "paths": [],
1696 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001697
1698 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
Brian Russell318fdb82021-01-19 16:56:32 +00001699
1700 def test_ip_punt(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001701 """IP punt police and redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001702
1703 pkts = self.pkt * 1025
Neale Rannsd91c1db2017-07-31 02:30:50 -07001704
1705 #
1706 # Configure a punt redirect via pg1.
1707 #
Ole Troan0bcad322018-12-11 13:04:01 +01001708 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001709 ip_punt_redirect = VppIpPuntRedirect(
1710 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1711 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001712 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001713
1714 self.send_and_expect(self.pg0, pkts, self.pg1)
1715
1716 #
1717 # add a policer
1718 #
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001719 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1)
1720 policer.add_vpp_config()
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001721 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1722 ip_punt_policer.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001723
1724 self.vapi.cli("clear trace")
1725 self.pg0.add_stream(pkts)
1726 self.pg_enable_capture(self.pg_interfaces)
1727 self.pg_start()
1728
1729 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001730 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001731 # but not equal to the number sent, since some were policed
1732 #
1733 rx = self.pg1._get_capture(1)
Brian Russelle9887262021-01-27 14:45:22 +00001734
1735 stats = policer.get_stats()
1736
1737 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001738 self.assertGreater(stats["conform_packets"], 0)
1739 self.assertEqual(stats["exceed_packets"], 0)
1740 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00001741
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001742 self.assertGreater(len(rx), 0)
1743 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001744
1745 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001746 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001747 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001748 ip_punt_policer.remove_vpp_config()
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001749 policer.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001750 self.send_and_expect(self.pg0, pkts, self.pg1)
1751
1752 #
1753 # remove the redirect. expect full drop.
1754 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001755 ip_punt_redirect.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001756 self.send_and_assert_no_replies(self.pg0, pkts, "IP no punt config")
Neale Rannsd91c1db2017-07-31 02:30:50 -07001757
1758 #
1759 # Add a redirect that is not input port selective
1760 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001761 ip_punt_redirect = VppIpPuntRedirect(
1762 self, 0xFFFFFFFF, self.pg1.sw_if_index, nh_addr
1763 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001764 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001765 self.send_and_expect(self.pg0, pkts, self.pg1)
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001766 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001767
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001768 def test_ip_punt_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001769 """IP punt/local with VRFs"""
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001770
1771 # use a punt redirect to test if for-us packets are accepted
1772 pkts = self.pkt * 1025
1773
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001774 vlans_pg0 = [VppDot1QSubint(self, self.pg0, v) for v in range(100, 104)]
1775 vlans_pg1 = [VppDot1QSubint(self, self.pg1, v) for v in range(100, 104)]
1776 tbl4 = [VppIpTable(self, v).add_vpp_config() for v in range(100, 104)]
1777 tbl6 = [VppIpTable(self, v, True).add_vpp_config() for v in range(100, 104)]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001778
1779 for v in vlans_pg0 + vlans_pg1:
1780 v.admin_up()
1781 v.set_table_ip4(v.vlan)
1782 v.set_table_ip6(v.vlan)
1783 v.config_ip4()
1784 v.config_ip6()
1785 v.resolve_arp()
1786 v.resolve_ndp()
1787
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001788 [
1789 VppIpPuntRedirect(
1790 self,
1791 vlans_pg0[i].sw_if_index,
1792 vlans_pg1[i].sw_if_index,
1793 vlans_pg1[i].remote_ip4,
1794 ).add_vpp_config()
1795 for i in range(4)
1796 ]
1797 [
1798 VppIpPuntRedirect(
1799 self,
1800 vlans_pg0[i].sw_if_index,
1801 vlans_pg1[i].sw_if_index,
1802 vlans_pg1[i].remote_ip6,
1803 ).add_vpp_config()
1804 for i in range(4)
1805 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001806
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001807 pkts = [
1808 (
1809 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1810 / Dot1Q(vlan=i.vlan)
1811 / IP(src=i.remote_ip4, dst=i.local_ip4)
1812 / UDP(sport=1234, dport=1234)
1813 / Raw(b"\xa5" * 100)
1814 )
1815 for i in vlans_pg0
1816 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001817
1818 self.send_and_expect(self.pg0, pkts, self.pg1)
1819
1820 #
1821 # IPv4
1822 #
1823
1824 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001825 pkts = [
1826 (
1827 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1828 / Dot1Q(vlan=i.vlan)
1829 / IP(src="1.1.1.1", dst=i.local_ip4)
1830 / UDP(sport=1234, dport=1234)
1831 / Raw(b"\xa5" * 100)
1832 )
1833 for i in vlans_pg0
1834 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001835 # single and dual loop
1836 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1837 self.send_and_assert_no_replies(self.pg0, pkts)
1838
Neale Rannse22a7042022-08-09 03:03:29 +00001839 self.assert_error_counter_equal("/err/ip4-local/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001840
1841 # using the same source in different tables, should reject
1842 # for the table that the source is not present in
1843 # the first packet in the stream is drop
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 / IP(src=vlans_pg0[0].remote_ip4, dst=i.local_ip4)
1849 / UDP(sport=1234, dport=1234)
1850 / Raw(b"\xa5" * 100)
1851 )
1852 for i in vlans_pg0
1853 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001854 # single loop accept and drop
1855 # followed by both in the same frame/loop
1856 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1857 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1858 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1859
1860 # using the same source in different tables, should reject
1861 # for the table that the source is not present in
1862 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001863 pkts = [
1864 (
1865 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1866 / Dot1Q(vlan=i.vlan)
1867 / IP(src=vlans_pg0[3].remote_ip4, dst=i.local_ip4)
1868 / UDP(sport=1234, dport=1234)
1869 / Raw(b"\xa5" * 100)
1870 )
1871 for i in vlans_pg0
1872 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001873
1874 # single loop accept and drop
1875 # followed by both in the same frame/loop
1876 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1877 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1878 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1879
1880 #
1881 # IPv6
1882 #
1883
1884 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001885 pkts = [
1886 (
1887 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1888 / Dot1Q(vlan=i.vlan)
1889 / IPv6(src="1::1", dst=i.local_ip6)
1890 / UDP(sport=1236, dport=1236)
1891 / Raw(b"\xa5" * 100)
1892 )
1893 for i in vlans_pg0
1894 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001895 # single and dual loop
1896 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1897 self.send_and_assert_no_replies(self.pg0, pkts)
1898
Neale Rannse22a7042022-08-09 03:03:29 +00001899 self.assert_error_counter_equal("/err/ip6-input/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001900
1901 # using the same source in different tables, should reject
1902 # for the table that the source is not present in
1903 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001904 pkts = [
1905 (
1906 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1907 / Dot1Q(vlan=i.vlan)
1908 / IPv6(src=vlans_pg0[0].remote_ip6, dst=i.local_ip6)
1909 / UDP(sport=1236, dport=1236)
1910 / Raw(b"\xa5" * 100)
1911 )
1912 for i in vlans_pg0
1913 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001914 # single loop accept and drop
1915 # followed by both in the same frame/loop
1916 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1917 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1918 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1919
1920 # using the same source in different tables, should reject
1921 # for the table that the source is not present in
1922 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001923 pkts = [
1924 (
1925 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1926 / Dot1Q(vlan=i.vlan)
1927 / IPv6(src=vlans_pg0[3].remote_ip6, dst=i.local_ip6)
1928 / UDP(sport=1236, dport=1236)
1929 / Raw(b"\xa5" * 100)
1930 )
1931 for i in vlans_pg0
1932 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001933
1934 # single loop accept and drop
1935 # followed by both in the same frame/loop
1936 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1937 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1938 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1939
1940 for v in vlans_pg0 + vlans_pg1:
1941 v.unconfig_ip4()
1942 v.unconfig_ip6()
1943 v.set_table_ip4(0)
1944 v.set_table_ip6(0)
1945
Pavel Kotucek609e1212018-11-27 09:59:44 +01001946 def test_ip_punt_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001947 """IP4 punt redirect dump"""
Pavel Kotucek609e1212018-11-27 09:59:44 +01001948
1949 #
1950 # Configure a punt redirects
1951 #
Ole Troan0bcad322018-12-11 13:04:01 +01001952 nh_address = self.pg3.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001953 ipr_03 = VppIpPuntRedirect(
1954 self, self.pg0.sw_if_index, self.pg3.sw_if_index, nh_address
1955 )
1956 ipr_13 = VppIpPuntRedirect(
1957 self, self.pg1.sw_if_index, self.pg3.sw_if_index, nh_address
1958 )
1959 ipr_23 = VppIpPuntRedirect(
1960 self, self.pg2.sw_if_index, self.pg3.sw_if_index, "0.0.0.0"
1961 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001962 ipr_03.add_vpp_config()
1963 ipr_13.add_vpp_config()
1964 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01001965
1966 #
1967 # Dump pg0 punt redirects
1968 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001969 self.assertTrue(ipr_03.query_vpp_config())
1970 self.assertTrue(ipr_13.query_vpp_config())
1971 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01001972
1973 #
1974 # Dump punt redirects for all interfaces
1975 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001976 punts = self.vapi.ip_punt_redirect_dump(0xFFFFFFFF)
Pavel Kotucek609e1212018-11-27 09:59:44 +01001977 self.assertEqual(len(punts), 3)
1978 for p in punts:
1979 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001980 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001981 self.assertEqual(str(punts[2].punt.nh), "0.0.0.0")
Pavel Kotucek609e1212018-11-27 09:59:44 +01001982
Neale Rannsd91c1db2017-07-31 02:30:50 -07001983
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001984class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001985 """IPv4 Punt Policer thread handoff"""
1986
Klement Sekera8d815022021-03-15 16:58:10 +01001987 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001988
1989 def setUp(self):
1990 super(TestIPPuntHandoff, self).setUp()
1991 super(TestIPPuntHandoff, self).punt_setup()
1992
1993 def tearDown(self):
1994 super(TestIPPuntHandoff, self).punt_teardown()
1995 super(TestIPPuntHandoff, self).tearDown()
1996
1997 def test_ip_punt_policer_handoff(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001998 """IP4 punt policer thread handoff"""
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001999 pkts = self.pkt * NUM_PKTS
2000
2001 #
2002 # Configure a punt redirect via pg1.
2003 #
2004 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002005 ip_punt_redirect = VppIpPuntRedirect(
2006 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
2007 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002008 ip_punt_redirect.add_vpp_config()
2009
2010 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002011 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
2012 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002013 #
2014 # This policer drops no packets, we are just
2015 # testing that they get to the right thread.
2016 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002017 policer = VppPolicer(
2018 self,
2019 "ip4-punt",
2020 400,
2021 0,
2022 10,
2023 0,
2024 1,
2025 0,
2026 0,
2027 False,
2028 action_tx,
2029 action_tx,
2030 action_tx,
2031 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002032 policer.add_vpp_config()
2033 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
2034 ip_punt_policer.add_vpp_config()
2035
2036 for worker in [0, 1]:
2037 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00002038 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002039
Brian Russelle9887262021-01-27 14:45:22 +00002040 # Combined stats, all threads
2041 stats = policer.get_stats()
2042
2043 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002044 self.assertGreater(stats["conform_packets"], 0)
2045 self.assertEqual(stats["exceed_packets"], 0)
2046 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002047
2048 # Worker 0, should have done all the policing
2049 stats0 = policer.get_stats(worker=0)
2050 self.assertEqual(stats, stats0)
2051
2052 # Worker 1, should have handed everything off
2053 stats1 = policer.get_stats(worker=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002054 self.assertEqual(stats1["conform_packets"], 0)
2055 self.assertEqual(stats1["exceed_packets"], 0)
2056 self.assertEqual(stats1["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002057
Brian Russellbb983142021-02-10 13:56:06 +00002058 # Bind the policer to worker 1 and repeat
2059 policer.bind_vpp_config(1, True)
2060 for worker in [0, 1]:
2061 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2062 self.logger.debug(self.vapi.cli("show trace max 100"))
2063
2064 # The 2 workers should now have policed the same amount
2065 stats = policer.get_stats()
2066 stats0 = policer.get_stats(worker=0)
2067 stats1 = policer.get_stats(worker=1)
2068
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002069 self.assertGreater(stats0["conform_packets"], 0)
2070 self.assertEqual(stats0["exceed_packets"], 0)
2071 self.assertGreater(stats0["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002072
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002073 self.assertGreater(stats1["conform_packets"], 0)
2074 self.assertEqual(stats1["exceed_packets"], 0)
2075 self.assertGreater(stats1["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002076
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002077 self.assertEqual(
2078 stats0["conform_packets"] + stats1["conform_packets"],
2079 stats["conform_packets"],
2080 )
Brian Russellbb983142021-02-10 13:56:06 +00002081
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002082 self.assertEqual(
2083 stats0["violate_packets"] + stats1["violate_packets"],
2084 stats["violate_packets"],
2085 )
Brian Russellbb983142021-02-10 13:56:06 +00002086
2087 # Unbind the policer and repeat
2088 policer.bind_vpp_config(1, False)
2089 for worker in [0, 1]:
2090 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2091 self.logger.debug(self.vapi.cli("show trace max 100"))
2092
2093 # The policer should auto-bind to worker 0 when packets arrive
2094 stats = policer.get_stats()
2095 stats0new = policer.get_stats(worker=0)
2096 stats1new = policer.get_stats(worker=1)
2097
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002098 self.assertGreater(stats0new["conform_packets"], stats0["conform_packets"])
2099 self.assertEqual(stats0new["exceed_packets"], 0)
2100 self.assertGreater(stats0new["violate_packets"], stats0["violate_packets"])
Brian Russellbb983142021-02-10 13:56:06 +00002101
2102 self.assertEqual(stats1, stats1new)
2103
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002104 #
2105 # Clean up
2106 #
2107 ip_punt_policer.remove_vpp_config()
2108 policer.remove_vpp_config()
2109 ip_punt_redirect.remove_vpp_config()
2110
2111
Neale Ranns054c03a2017-10-13 05:15:07 -07002112class TestIPDeag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002113 """IPv4 Deaggregate Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002114
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002115 @classmethod
2116 def setUpClass(cls):
2117 super(TestIPDeag, cls).setUpClass()
2118
2119 @classmethod
2120 def tearDownClass(cls):
2121 super(TestIPDeag, cls).tearDownClass()
2122
Neale Ranns054c03a2017-10-13 05:15:07 -07002123 def setUp(self):
2124 super(TestIPDeag, self).setUp()
2125
2126 self.create_pg_interfaces(range(3))
2127
2128 for i in self.pg_interfaces:
2129 i.admin_up()
2130 i.config_ip4()
2131 i.resolve_arp()
2132
2133 def tearDown(self):
2134 super(TestIPDeag, self).tearDown()
2135 for i in self.pg_interfaces:
2136 i.unconfig_ip4()
2137 i.admin_down()
2138
Neale Ranns054c03a2017-10-13 05:15:07 -07002139 def test_ip_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002140 """IP Deag Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002141
2142 #
2143 # Create a table to be used for:
2144 # 1 - another destination address lookup
2145 # 2 - a source address lookup
2146 #
2147 table_dst = VppIpTable(self, 1)
2148 table_src = VppIpTable(self, 2)
2149 table_dst.add_vpp_config()
2150 table_src.add_vpp_config()
2151
2152 #
2153 # Add a route in the default table to point to a deag/
2154 # second lookup in each of these tables
2155 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002156 route_to_dst = VppIpRoute(
2157 self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
2158 )
Neale Ranns097fa662018-05-01 05:17:55 -07002159 route_to_src = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002160 self,
2161 "1.1.1.2",
2162 32,
2163 [
2164 VppRoutePath(
2165 "0.0.0.0",
2166 0xFFFFFFFF,
2167 nh_table_id=2,
2168 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP,
2169 )
2170 ],
2171 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002172 route_to_dst.add_vpp_config()
2173 route_to_src.add_vpp_config()
2174
2175 #
2176 # packets to these destination are dropped, since they'll
2177 # hit the respective default routes in the second table
2178 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002179 p_dst = (
2180 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2181 / IP(src="5.5.5.5", dst="1.1.1.1")
2182 / TCP(sport=1234, dport=1234)
2183 / Raw(b"\xa5" * 100)
2184 )
2185 p_src = (
2186 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2187 / IP(src="2.2.2.2", dst="1.1.1.2")
2188 / TCP(sport=1234, dport=1234)
2189 / Raw(b"\xa5" * 100)
2190 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002191 pkts_dst = p_dst * 257
2192 pkts_src = p_src * 257
2193
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002194 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in dst table")
2195 self.send_and_assert_no_replies(self.pg0, pkts_src, "IP in src table")
Neale Ranns054c03a2017-10-13 05:15:07 -07002196
2197 #
2198 # add a route in the dst table to forward via pg1
2199 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002200 route_in_dst = VppIpRoute(
2201 self,
2202 "1.1.1.1",
2203 32,
2204 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2205 table_id=1,
2206 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002207 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07002208
Neale Ranns054c03a2017-10-13 05:15:07 -07002209 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
2210
2211 #
2212 # add a route in the src table to forward via pg2
2213 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002214 route_in_src = VppIpRoute(
2215 self,
2216 "2.2.2.2",
2217 32,
2218 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2219 table_id=2,
2220 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002221 route_in_src.add_vpp_config()
2222 self.send_and_expect(self.pg0, pkts_src, self.pg2)
2223
Neale Rannsce9e0b42018-08-01 12:53:17 -07002224 #
2225 # loop in the lookup DP
2226 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002227 route_loop = VppIpRoute(
2228 self, "2.2.2.3", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
2229 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002230 route_loop.add_vpp_config()
2231
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002232 p_l = (
2233 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2234 / IP(src="2.2.2.4", dst="2.2.2.3")
2235 / TCP(sport=1234, dport=1234)
2236 / Raw(b"\xa5" * 100)
2237 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002238
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002239 self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop")
Neale Rannsce9e0b42018-08-01 12:53:17 -07002240
Neale Ranns054c03a2017-10-13 05:15:07 -07002241
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002242class TestIPInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002243 """IPv4 Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002244
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002245 @classmethod
2246 def setUpClass(cls):
2247 super(TestIPInput, cls).setUpClass()
2248
2249 @classmethod
2250 def tearDownClass(cls):
2251 super(TestIPInput, cls).tearDownClass()
2252
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002253 def setUp(self):
2254 super(TestIPInput, self).setUp()
2255
2256 self.create_pg_interfaces(range(2))
2257
2258 for i in self.pg_interfaces:
2259 i.admin_up()
2260 i.config_ip4()
2261 i.resolve_arp()
2262
2263 def tearDown(self):
2264 super(TestIPInput, self).tearDown()
2265 for i in self.pg_interfaces:
2266 i.unconfig_ip4()
2267 i.admin_down()
2268
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002269 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002270 """IP Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002271
2272 # i can't find a way in scapy to construct an IP packet
2273 # with a length less than the IP header length
2274
2275 #
2276 # Packet too short - this is forwarded
2277 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002278 p_short = (
2279 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2280 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=40)
2281 / UDP(sport=1234, dport=1234)
2282 / Raw(b"\xa5" * 100)
2283 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002284
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002285 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002286
2287 #
2288 # Packet too long - this is dropped
2289 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002290 p_long = (
2291 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2292 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=400)
2293 / UDP(sport=1234, dport=1234)
2294 / Raw(b"\xa5" * 100)
2295 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002296
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002297 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002298
2299 #
2300 # bad chksum - this is dropped
2301 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002302 p_chksum = (
2303 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2304 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, chksum=400)
2305 / UDP(sport=1234, dport=1234)
2306 / Raw(b"\xa5" * 100)
2307 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002308
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002309 rx = self.send_and_assert_no_replies(
2310 self.pg0, p_chksum * NUM_PKTS, "bad checksum"
2311 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002312
2313 #
2314 # bad version - this is dropped
2315 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002316 p_ver = (
2317 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2318 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, version=3)
2319 / UDP(sport=1234, dport=1234)
2320 / Raw(b"\xa5" * 100)
2321 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002322
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002323 rx = self.send_and_assert_no_replies(
2324 self.pg0, p_ver * NUM_PKTS, "funky version"
2325 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002326
2327 #
2328 # fragment offset 1 - this is dropped
2329 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002330 p_frag = (
2331 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2332 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, frag=1)
2333 / UDP(sport=1234, dport=1234)
2334 / Raw(b"\xa5" * 100)
2335 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002336
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002337 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002338
2339 #
2340 # TTL expired packet
2341 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002342 p_ttl = (
2343 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2344 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=1)
2345 / UDP(sport=1234, dport=1234)
2346 / Raw(b"\xa5" * 100)
2347 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002348
Neale Ranns5c6dd172022-02-17 09:08:47 +00002349 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002350
Neale Ranns5c6dd172022-02-17 09:08:47 +00002351 for rx in rxs:
2352 icmp = rx[ICMP]
2353 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002354 self.assertEqual(icmpcodes[icmp.type][icmp.code], "ttl-zero-during-transit")
Neale Ranns5c6dd172022-02-17 09:08:47 +00002355 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2356 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002357
Neale Rannsffd78d12018-02-09 06:05:16 -08002358 #
2359 # MTU exceeded
2360 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002361 p_mtu = (
2362 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2363 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=10, flags="DF")
2364 / UDP(sport=1234, dport=1234)
2365 / Raw(b"\xa5" * 2000)
2366 )
Neale Rannsffd78d12018-02-09 06:05:16 -08002367
Ole Troand7231612018-06-07 10:17:57 +02002368 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002369
Neale Ranns5c6dd172022-02-17 09:08:47 +00002370 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002371
Neale Ranns5c6dd172022-02-17 09:08:47 +00002372 for rx in rxs:
2373 icmp = rx[ICMP]
2374 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002375 self.assertEqual(icmpcodes[icmp.type][icmp.code], "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002376 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002377 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2378 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002379
Ole Troand7231612018-06-07 10:17:57 +02002380 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002381 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002382
Ole Troand7231612018-06-07 10:17:57 +02002383 # Reset MTU for subsequent tests
2384 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002385
Neale Rannsbe2286b2018-12-09 12:54:51 -08002386 #
2387 # source address 0.0.0.0 and 25.255.255.255 and for-us
2388 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002389 p_s0 = (
2390 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2391 / IP(src="0.0.0.0", dst=self.pg0.local_ip4)
2392 / ICMP(id=4, seq=4)
2393 / Raw(load=b"\x0a" * 18)
2394 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002395 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2396
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002397 p_s0 = (
2398 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2399 / IP(src="255.255.255.255", dst=self.pg0.local_ip4)
2400 / ICMP(id=4, seq=4)
2401 / Raw(load=b"\x0a" * 18)
2402 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002403 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2404
Neale Ranns1855b8e2018-07-11 10:31:26 -07002405
2406class TestIPDirectedBroadcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002407 """IPv4 Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002408
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002409 @classmethod
2410 def setUpClass(cls):
2411 super(TestIPDirectedBroadcast, cls).setUpClass()
2412
2413 @classmethod
2414 def tearDownClass(cls):
2415 super(TestIPDirectedBroadcast, cls).tearDownClass()
2416
Neale Ranns1855b8e2018-07-11 10:31:26 -07002417 def setUp(self):
2418 super(TestIPDirectedBroadcast, self).setUp()
2419
2420 self.create_pg_interfaces(range(2))
2421
2422 for i in self.pg_interfaces:
2423 i.admin_up()
2424
2425 def tearDown(self):
2426 super(TestIPDirectedBroadcast, self).tearDown()
2427 for i in self.pg_interfaces:
2428 i.admin_down()
2429
2430 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002431 """IP Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002432
2433 #
2434 # set the directed broadcast on pg0 first, then config IP4 addresses
2435 # for pg1 directed broadcast is always disabled
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002436 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002437
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002438 p0 = (
2439 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2440 / IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast)
2441 / UDP(sport=1234, dport=1234)
2442 / Raw(b"\xa5" * 2000)
2443 )
2444 p1 = (
2445 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2446 / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast)
2447 / UDP(sport=1234, dport=1234)
2448 / Raw(b"\xa5" * 2000)
2449 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002450
2451 self.pg0.config_ip4()
2452 self.pg0.resolve_arp()
2453 self.pg1.config_ip4()
2454 self.pg1.resolve_arp()
2455
2456 #
2457 # test packet is L2 broadcast
2458 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002459 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002460 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2461
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002462 self.send_and_assert_no_replies(
2463 self.pg0, p1 * NUM_PKTS, "directed broadcast disabled"
2464 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002465
2466 #
2467 # toggle directed broadcast on pg0
2468 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002469 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 0)
2470 self.send_and_assert_no_replies(
2471 self.pg1, p0 * NUM_PKTS, "directed broadcast disabled"
2472 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002473
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002474 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002475 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002476
2477 self.pg0.unconfig_ip4()
2478 self.pg1.unconfig_ip4()
2479
2480
mu.duojiao59a82952018-10-11 14:27:30 +08002481class TestIPLPM(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002482 """IPv4 longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002483
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002484 @classmethod
2485 def setUpClass(cls):
2486 super(TestIPLPM, cls).setUpClass()
2487
2488 @classmethod
2489 def tearDownClass(cls):
2490 super(TestIPLPM, cls).tearDownClass()
2491
mu.duojiao59a82952018-10-11 14:27:30 +08002492 def setUp(self):
2493 super(TestIPLPM, self).setUp()
2494
2495 self.create_pg_interfaces(range(4))
2496
2497 for i in self.pg_interfaces:
2498 i.admin_up()
2499 i.config_ip4()
2500 i.resolve_arp()
2501
2502 def tearDown(self):
2503 super(TestIPLPM, self).tearDown()
2504 for i in self.pg_interfaces:
2505 i.admin_down()
2506 i.unconfig_ip4()
2507
2508 def test_ip_lpm(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002509 """IP longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002510
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002511 s_24 = VppIpRoute(
2512 self,
2513 "10.1.2.0",
2514 24,
2515 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2516 )
mu.duojiao59a82952018-10-11 14:27:30 +08002517 s_24.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002518 s_8 = VppIpRoute(
2519 self,
2520 "10.0.0.0",
2521 8,
2522 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2523 )
mu.duojiao59a82952018-10-11 14:27:30 +08002524 s_8.add_vpp_config()
2525
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002526 p_8 = (
2527 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2528 / IP(src="1.1.1.1", dst="10.1.1.1")
2529 / UDP(sport=1234, dport=1234)
2530 / Raw(b"\xa5" * 2000)
2531 )
2532 p_24 = (
2533 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2534 / IP(src="1.1.1.1", dst="10.1.2.1")
2535 / UDP(sport=1234, dport=1234)
2536 / Raw(b"\xa5" * 2000)
2537 )
mu.duojiao59a82952018-10-11 14:27:30 +08002538
2539 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002540 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2541 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002542
2543
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002544@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002545class TestIPv4Frag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 """IPv4 fragmentation"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002547
2548 @classmethod
2549 def setUpClass(cls):
2550 super(TestIPv4Frag, cls).setUpClass()
2551
2552 cls.create_pg_interfaces([0, 1])
2553 cls.src_if = cls.pg0
2554 cls.dst_if = cls.pg1
2555
2556 # setup all interfaces
2557 for i in cls.pg_interfaces:
2558 i.admin_up()
2559 i.config_ip4()
2560 i.resolve_arp()
2561
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002562 @classmethod
2563 def tearDownClass(cls):
2564 super(TestIPv4Frag, cls).tearDownClass()
2565
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002566 def test_frag_large_packets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002567 """Fragmentation of large packets"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002568
Neale Ranns0b6a8572019-10-30 17:34:14 +00002569 self.vapi.cli("adjacency counters enable")
2570
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002571 p = (
2572 Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac)
2573 / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4)
2574 / UDP(sport=1234, dport=5678)
2575 / Raw()
2576 )
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002577 self.extend_packet(p, 6000, "abcde")
2578 saved_payload = p[Raw].load
2579
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002580 nbr = VppNeighbor(
2581 self,
2582 self.dst_if.sw_if_index,
2583 self.dst_if.remote_mac,
2584 self.dst_if.remote_ip4,
2585 ).add_vpp_config()
Neale Ranns0b6a8572019-10-30 17:34:14 +00002586
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002587 # Force fragmentation by setting MTU of output interface
2588 # lower than packet size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002589 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, [5000, 0, 0, 0])
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002590
2591 self.pg_enable_capture()
2592 self.src_if.add_stream(p)
2593 self.pg_start()
2594
2595 # Expecting 3 fragments because size of created fragments currently
2596 # cannot be larger then VPP buffer size (which is 2048)
2597 packets = self.dst_if.get_capture(3)
2598
Neale Ranns0b6a8572019-10-30 17:34:14 +00002599 # we should show 3 packets thru the neighbor
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002600 self.assertEqual(3, nbr.get_stats()["packets"])
Neale Ranns0b6a8572019-10-30 17:34:14 +00002601
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002602 # Assume VPP sends the fragments in order
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002603 payload = b""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002604 for p in packets:
2605 payload_offset = p.frag * 8
2606 if payload_offset > 0:
2607 payload_offset -= 8 # UDP header is not in payload
2608 self.assert_equal(payload_offset, len(payload))
2609 payload += p[Raw].load
2610 self.assert_equal(payload, saved_payload, "payload")
2611
2612
Neale Ranns9db6ada2019-11-08 12:42:31 +00002613class TestIPReplace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002614 """IPv4 Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002615
2616 @classmethod
2617 def setUpClass(cls):
2618 super(TestIPReplace, cls).setUpClass()
2619
2620 @classmethod
2621 def tearDownClass(cls):
2622 super(TestIPReplace, cls).tearDownClass()
2623
2624 def setUp(self):
2625 super(TestIPReplace, self).setUp()
2626
2627 self.create_pg_interfaces(range(4))
2628
2629 table_id = 1
2630 self.tables = []
2631
2632 for i in self.pg_interfaces:
2633 i.admin_up()
2634 i.config_ip4()
2635 i.resolve_arp()
2636 i.generate_remote_hosts(2)
2637 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2638 table_id += 1
2639
2640 def tearDown(self):
2641 super(TestIPReplace, self).tearDown()
2642 for i in self.pg_interfaces:
2643 i.admin_down()
2644 i.unconfig_ip4()
2645
2646 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002647 """IP Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002648
Neale Ranns990f6942020-10-20 07:20:17 +00002649 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2650 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002651 N_ROUTES = 20
2652 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2653 routes = [[], [], [], []]
2654
2655 # load up the tables with some routes
2656 for ii, t in enumerate(self.tables):
2657 for jj in range(N_ROUTES):
2658 uni = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002659 self,
2660 "10.0.0.%d" % jj,
2661 32,
2662 [
2663 VppRoutePath(
2664 links[ii].remote_hosts[0].ip4, links[ii].sw_if_index
2665 ),
2666 VppRoutePath(
2667 links[ii].remote_hosts[1].ip4, links[ii].sw_if_index
2668 ),
2669 ],
2670 table_id=t.table_id,
2671 ).add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002672 multi = VppIpMRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002673 self,
2674 "0.0.0.0",
2675 "239.0.0.%d" % jj,
2676 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002677 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002678 [
2679 VppMRoutePath(
2680 self.pg0.sw_if_index,
2681 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
2682 ),
2683 VppMRoutePath(
2684 self.pg1.sw_if_index,
2685 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2686 ),
2687 VppMRoutePath(
2688 self.pg2.sw_if_index,
2689 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2690 ),
2691 VppMRoutePath(
2692 self.pg3.sw_if_index,
2693 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2694 ),
2695 ],
2696 table_id=t.table_id,
2697 ).add_vpp_config()
2698 routes[ii].append({"uni": uni, "multi": multi})
Neale Ranns9db6ada2019-11-08 12:42:31 +00002699
2700 #
2701 # replace the tables a few times
2702 #
2703 for kk in range(3):
2704 # replace_begin each table
2705 for t in self.tables:
2706 t.replace_begin()
2707
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 # redownload the even numbered routes
2717 for ii, t in enumerate(self.tables):
2718 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002719 routes[ii][jj]["uni"].add_vpp_config()
2720 routes[ii][jj]["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002721
2722 # signal each table replace_end
2723 for t in self.tables:
2724 t.replace_end()
2725
2726 # we should find the even routes, but not the odd
2727 for ii, t in enumerate(self.tables):
2728 dump = t.dump()
2729 mdump = t.mdump()
2730 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002731 self.assertTrue(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2732 self.assertTrue(
2733 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2734 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002735 for jj in range(1, N_ROUTES - 1, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002736 self.assertFalse(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2737 self.assertFalse(
2738 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2739 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002740
2741 # reload all the routes
2742 for ii, t in enumerate(self.tables):
2743 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002744 r["uni"].add_vpp_config()
2745 r["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002746
2747 # all the routes are still there
2748 for ii, t in enumerate(self.tables):
2749 dump = t.dump()
2750 mdump = t.mdump()
2751 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002752 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2753 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002754
2755 #
2756 # finally flush the tables for good measure
2757 #
2758 for t in self.tables:
2759 t.flush()
2760 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002761 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002762
2763
Neale Ranns9efcee62019-11-26 19:30:08 +00002764class TestIPCover(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002765 """IPv4 Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002766
2767 @classmethod
2768 def setUpClass(cls):
2769 super(TestIPCover, cls).setUpClass()
2770
2771 @classmethod
2772 def tearDownClass(cls):
2773 super(TestIPCover, cls).tearDownClass()
2774
2775 def setUp(self):
2776 super(TestIPCover, self).setUp()
2777
2778 self.create_pg_interfaces(range(4))
2779
2780 table_id = 1
2781 self.tables = []
2782
2783 for i in self.pg_interfaces:
2784 i.admin_up()
2785 i.config_ip4()
2786 i.resolve_arp()
2787 i.generate_remote_hosts(2)
2788 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2789 table_id += 1
2790
2791 def tearDown(self):
2792 super(TestIPCover, self).tearDown()
2793 for i in self.pg_interfaces:
2794 i.admin_down()
2795 i.unconfig_ip4()
2796
2797 def test_cover(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002798 """IP Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002799
2800 # add a loop back with a /32 prefix
2801 lo = VppLoInterface(self)
2802 lo.admin_up()
2803 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2804
2805 # add a neighbour that matches the loopback's /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002806 nbr = VppNeighbor(
2807 self, lo.sw_if_index, lo.remote_mac, "127.0.0.1"
2808 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002809
2810 # add the default route which will be the cover for /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002811 r = VppIpRoute(
2812 self,
2813 "0.0.0.0",
2814 0,
2815 [VppRoutePath("127.0.0.1", lo.sw_if_index)],
2816 register=False,
2817 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002818
2819 # add/remove/add a longer mask cover
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002820 r8 = VppIpRoute(
2821 self, "127.0.0.0", 8, [VppRoutePath("127.0.0.1", lo.sw_if_index)]
2822 ).add_vpp_config()
Neale Ranns87866032020-11-25 09:14:22 +00002823 r8.remove_vpp_config()
2824 r8.add_vpp_config()
2825 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002826
2827 # remove the default route
2828 r.remove_vpp_config()
2829
Neale Ranns87866032020-11-25 09:14:22 +00002830 # remove the interface prefix
2831 a.remove_vpp_config()
2832
Neale Ranns59f71132020-04-08 12:19:38 +00002833
2834class TestIP4Replace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002835 """IPv4 Interface Address Replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002836
2837 @classmethod
2838 def setUpClass(cls):
2839 super(TestIP4Replace, cls).setUpClass()
2840
2841 @classmethod
2842 def tearDownClass(cls):
2843 super(TestIP4Replace, cls).tearDownClass()
2844
2845 def setUp(self):
2846 super(TestIP4Replace, self).setUp()
2847
2848 self.create_pg_interfaces(range(4))
2849
2850 for i in self.pg_interfaces:
2851 i.admin_up()
2852
2853 def tearDown(self):
2854 super(TestIP4Replace, self).tearDown()
2855 for i in self.pg_interfaces:
2856 i.admin_down()
2857
2858 def get_n_pfxs(self, intf):
2859 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2860
2861 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002862 """IP interface address replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002863
2864 intf_pfxs = [[], [], [], []]
2865
2866 # add prefixes to each of the interfaces
2867 for i in range(len(self.pg_interfaces)):
2868 intf = self.pg_interfaces[i]
2869
2870 # 172.16.x.1/24
2871 addr = "172.16.%d.1" % intf.sw_if_index
2872 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2873 intf_pfxs[i].append(a)
2874
2875 # 172.16.x.2/24 - a different address in the same subnet as above
2876 addr = "172.16.%d.2" % intf.sw_if_index
2877 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2878 intf_pfxs[i].append(a)
2879
2880 # 172.15.x.2/24 - a different address and subnet
2881 addr = "172.15.%d.2" % intf.sw_if_index
2882 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2883 intf_pfxs[i].append(a)
2884
2885 # a dump should n_address in it
2886 for intf in self.pg_interfaces:
2887 self.assertEqual(self.get_n_pfxs(intf), 3)
2888
2889 #
2890 # remove all the address thru a replace
2891 #
2892 self.vapi.sw_interface_address_replace_begin()
2893 self.vapi.sw_interface_address_replace_end()
2894 for intf in self.pg_interfaces:
2895 self.assertEqual(self.get_n_pfxs(intf), 0)
2896
2897 #
2898 # add all the interface addresses back
2899 #
2900 for p in intf_pfxs:
2901 for v in p:
2902 v.add_vpp_config()
2903 for intf in self.pg_interfaces:
2904 self.assertEqual(self.get_n_pfxs(intf), 3)
2905
2906 #
2907 # replace again, but this time update/re-add the address on the first
2908 # two interfaces
2909 #
2910 self.vapi.sw_interface_address_replace_begin()
2911
2912 for p in intf_pfxs[:2]:
2913 for v in p:
2914 v.add_vpp_config()
2915
2916 self.vapi.sw_interface_address_replace_end()
2917
2918 # on the first two the address still exist,
2919 # on the other two they do not
2920 for intf in self.pg_interfaces[:2]:
2921 self.assertEqual(self.get_n_pfxs(intf), 3)
2922 for p in intf_pfxs[:2]:
2923 for v in p:
2924 self.assertTrue(v.query_vpp_config())
2925 for intf in self.pg_interfaces[2:]:
2926 self.assertEqual(self.get_n_pfxs(intf), 0)
2927
2928 #
2929 # add all the interface addresses back on the last two
2930 #
2931 for p in intf_pfxs[2:]:
2932 for v in p:
2933 v.add_vpp_config()
2934 for intf in self.pg_interfaces:
2935 self.assertEqual(self.get_n_pfxs(intf), 3)
2936
2937 #
2938 # replace again, this time add different prefixes on all the interfaces
2939 #
2940 self.vapi.sw_interface_address_replace_begin()
2941
2942 pfxs = []
2943 for intf in self.pg_interfaces:
2944 # 172.18.x.1/24
2945 addr = "172.18.%d.1" % intf.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002946 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002947
2948 self.vapi.sw_interface_address_replace_end()
2949
2950 # only .18 should exist on each interface
2951 for intf in self.pg_interfaces:
2952 self.assertEqual(self.get_n_pfxs(intf), 1)
2953 for pfx in pfxs:
2954 self.assertTrue(pfx.query_vpp_config())
2955
2956 #
2957 # remove everything
2958 #
2959 self.vapi.sw_interface_address_replace_begin()
2960 self.vapi.sw_interface_address_replace_end()
2961 for intf in self.pg_interfaces:
2962 self.assertEqual(self.get_n_pfxs(intf), 0)
2963
2964 #
2965 # add prefixes to each interface. post-begin add the prefix from
2966 # interface X onto interface Y. this would normally be an error
2967 # since it would generate a 'duplicate address' warning. but in
2968 # this case, since what is newly downloaded is sane, it's ok
2969 #
2970 for intf in self.pg_interfaces:
2971 # 172.18.x.1/24
2972 addr = "172.18.%d.1" % intf.sw_if_index
2973 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2974
2975 self.vapi.sw_interface_address_replace_begin()
2976
2977 pfxs = []
2978 for intf in self.pg_interfaces:
2979 # 172.18.x.1/24
2980 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002981 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002982
2983 self.vapi.sw_interface_address_replace_end()
2984
2985 self.logger.info(self.vapi.cli("sh int addr"))
2986
2987 for intf in self.pg_interfaces:
2988 self.assertEqual(self.get_n_pfxs(intf), 1)
2989 for pfx in pfxs:
2990 self.assertTrue(pfx.query_vpp_config())
2991
2992
Neale Ranns8f5fef22020-12-21 08:29:34 +00002993class TestIPv4PathMTU(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002994 """IPv4 Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002995
2996 @classmethod
2997 def setUpClass(cls):
2998 super(TestIPv4PathMTU, cls).setUpClass()
2999
3000 cls.create_pg_interfaces(range(2))
3001
3002 # setup all interfaces
3003 for i in cls.pg_interfaces:
3004 i.admin_up()
3005 i.config_ip4()
3006 i.resolve_arp()
3007
3008 @classmethod
3009 def tearDownClass(cls):
3010 super(TestIPv4PathMTU, cls).tearDownClass()
3011
3012 def test_path_mtu(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003013 """Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00003014
3015 #
3016 # The goal here is not to test that fragmentation works correctly,
3017 # that's done elsewhere, the intent is to ensure that the Path MTU
3018 # settings are honoured.
3019 #
3020 self.vapi.cli("adjacency counters enable")
3021
3022 # set the interface MTU to a reasonable value
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003023 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003024
3025 self.pg1.generate_remote_hosts(4)
3026
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003027 p_2k = (
3028 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3029 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3030 / UDP(sport=1234, dport=5678)
3031 / Raw(b"0xa" * 640)
3032 )
3033 p_1k = (
3034 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3035 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3036 / UDP(sport=1234, dport=5678)
3037 / Raw(b"0xa" * 320)
3038 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003039
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003040 nbr = VppNeighbor(
3041 self, self.pg1.sw_if_index, self.pg1.remote_mac, self.pg1.remote_ip4
3042 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003043
3044 # this is now the interface MTU frags
3045 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3046 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3047
3048 # drop the path MTU for this neighbour to below the interface MTU
3049 # expect more frags
3050 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
3051
3052 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3053 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3054
3055 # print/format the adj delegate
3056 self.logger.info(self.vapi.cli("sh adj 5"))
3057
3058 # increase the path MTU to more than the interface
3059 # expect to use the interface MTU
3060 pmtu.modify(8192)
3061
3062 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3063 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3064
3065 # go back to an MTU from the path
3066 # wrap the call around mark-n-sweep to enusre updates clear stale
3067 self.vapi.ip_path_mtu_replace_begin()
3068 pmtu.modify(900)
3069 self.vapi.ip_path_mtu_replace_end()
3070
3071 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3072 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3073
3074 # raise the interface's MTU
3075 # should still use that of the path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003076 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003077 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3078 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3079
3080 # set path high and interface low
3081 pmtu.modify(2000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003082 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [900, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003083 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3084 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3085
3086 # remove the path MTU using the mark-n-sweep semantics
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003087 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003088 self.vapi.ip_path_mtu_replace_begin()
3089 self.vapi.ip_path_mtu_replace_end()
3090
3091 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3092 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3093
3094 #
3095 # set path MTU for a neighbour that doesn't exist, yet
3096 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003097 pmtu2 = VppIpPathMtu(self, self.pg1.remote_hosts[2].ip4, 900).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003098
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003099 p_2k = (
3100 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3101 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3102 / UDP(sport=1234, dport=5678)
3103 / Raw(b"0xa" * 640)
3104 )
3105 p_1k = (
3106 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3107 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3108 / UDP(sport=1234, dport=5678)
3109 / Raw(b"0xa" * 320)
3110 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003111
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003112 nbr2 = VppNeighbor(
3113 self,
3114 self.pg1.sw_if_index,
3115 self.pg1.remote_hosts[2].mac,
3116 self.pg1.remote_hosts[2].ip4,
3117 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003118
3119 # should frag to the path MTU
3120 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3121 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3122
3123 # remove and re-add the neighbour
3124 nbr2.remove_vpp_config()
3125 nbr2.add_vpp_config()
3126
3127 # should frag to the path MTU
3128 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3129 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3130
3131 #
3132 # set PMTUs for many peers
3133 #
3134 N_HOSTS = 16
3135 self.pg1.generate_remote_hosts(16)
3136 self.pg1.configure_ipv4_neighbors()
3137
3138 for h in range(N_HOSTS):
3139 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
3140 pmtu.add_vpp_config()
3141 self.assertTrue(pmtu.query_vpp_config())
3142
3143 self.logger.info(self.vapi.cli("sh ip pmtu"))
3144 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
3145 self.assertEqual(N_HOSTS, len(dump))
3146
3147 for h in range(N_HOSTS):
3148 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
3149 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
3150
3151 # should frag to the path MTU
3152 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3153 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3154
3155
Neale Ranns50bd1d32021-10-08 07:16:12 +00003156class TestIPv4ItfRebind(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003157 """IPv4 Interface Bind w/ attached routes"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003158
3159 def setUp(self):
3160 super(TestIPv4ItfRebind, self).setUp()
3161
3162 self.create_pg_interfaces(range(3))
3163
3164 def tearDown(self):
3165 super(TestIPv4ItfRebind, self).tearDown()
3166
3167 def test_rebind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003168 """Import to no import"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003169
3170 TABLE_ID = 1
3171 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
3172 self.pg1.set_table_ip4(TABLE_ID)
3173
3174 for i in self.pg_interfaces:
3175 i.admin_up()
3176 i.config_ip4()
3177 i.resolve_arp()
3178
3179 # add an attached route via an pg0
3180 # in a different table. this prefix should import
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003181 rt = VppIpRoute(
3182 self,
3183 self.pg0.local_ip4,
3184 24,
3185 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
3186 table_id=TABLE_ID,
3187 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003188
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003189 p = (
3190 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3191 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3192 / UDP(sport=1234, dport=5678)
3193 / Raw(b"0xa" * 640)
3194 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003195
3196 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3197 self.assertFalse(rx[0].haslayer(ARP))
3198
3199 # then bind pg0 to a new table
3200 # so the prefix no longer imports
3201 self.pg0.unconfig_ip4()
3202 self.pg0.set_table_ip4(TABLE_ID)
3203 self.pg0.config_ip4()
3204 self.pg0.resolve_arp()
3205
3206 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3207 self.assertFalse(rx[0].haslayer(ARP))
3208
3209 # revert back to imported
3210 self.pg0.unconfig_ip4()
3211 self.pg0.set_table_ip4(0)
3212 self.pg0.config_ip4()
3213 self.pg0.resolve_arp()
3214
3215 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3216 self.assertFalse(rx[0].haslayer(ARP))
3217
3218 # cleanup
3219 for i in self.pg_interfaces:
3220 i.unconfig_ip4()
3221 i.set_table_ip4(0)
3222 i.admin_down()
3223
3224 rt.remove_vpp_config()
3225 tbl.remove_vpp_config()
3226
3227 def test_delete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003228 """Swap import tables"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003229
3230 TABLE_ID1 = 1
3231 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
3232 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
3233 TABLE_ID2 = 2
3234 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
3235 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
3236
3237 # table mappings
3238 self.pg1.set_table_ip4(TABLE_ID1)
3239 self.pg1.set_table_ip6(TABLE_ID1)
3240 self.pg2.set_table_ip4(TABLE_ID2)
3241 self.pg2.set_table_ip6(TABLE_ID2)
3242
3243 for i in self.pg_interfaces:
3244 i.admin_up()
3245 i.config_ip4()
3246 i.resolve_arp()
3247
3248 # add an attached route in the default table via pg0
3249 # this should import to table 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003250 rt4 = VppIpRoute(
3251 self,
3252 self.pg1.local_ip4,
3253 24,
3254 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3255 ).add_vpp_config()
3256 rt6 = VppIpRoute(
3257 self,
3258 self.pg1.local_ip6,
3259 64,
3260 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3261 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003262
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003263 p1 = (
3264 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3265 / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
3266 / UDP(sport=1234, dport=5678)
3267 / Raw(b"0xa" * 640)
3268 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003269
3270 # inject into table 0
3271 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3272 self.assertFalse(rx[0].haslayer(ARP))
3273
3274 # swap the attached interface to table 2
3275 self.pg1.unconfig_ip4()
3276 self.pg1.unconfig_ip6()
3277 self.pg1.set_table_ip4(TABLE_ID2)
3278 self.pg1.set_table_ip6(TABLE_ID2)
3279 self.pg1.config_ip4()
3280 self.pg1.config_ip6()
3281 self.pg1.resolve_arp()
3282
3283 # delete table 1
3284 tbl1_4.flush()
3285 tbl1_6.flush()
3286 tbl1_4.remove_vpp_config()
3287 tbl1_6.remove_vpp_config()
3288
3289 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3290 self.assertFalse(rx[0].haslayer(ARP))
3291
3292 for i in self.pg_interfaces:
3293 i.unconfig_ip4()
3294 i.unconfig_ip6()
3295 i.set_table_ip4(0)
3296 i.set_table_ip6(0)
3297 i.admin_down()
3298
3299
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003300if __name__ == "__main__":
Klement Sekeraf62ae122016-10-11 11:47:09 +02003301 unittest.main(testRunner=VppTestRunner)