blob: e6597d24210877a942e054592a8d252b57f68893 [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):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100566
Neale Ranns097fa662018-05-01 05:17:55 -0700567 routes = []
568 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200569 r = VppIpRoute(
570 self,
571 start_dest_addr % (i + start),
572 32,
573 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
574 )
Neale Ranns097fa662018-05-01 05:17:55 -0700575 r.remove_vpp_config()
576 routes.append(r)
577 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100578
Neale Ranns097fa662018-05-01 05:17:55 -0700579 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100580 pkts = []
581
582 for _ in range(count):
Neale Rannsefd7bc22019-11-11 08:32:34 +0000583 dst_addr = random.choice(routes).prefix.network_address
Klement Sekeradab231a2016-12-21 08:50:14 +0100584 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100585 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 p = (
587 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
588 / IP(src=src_if.remote_ip4, dst=str(dst_addr))
589 / UDP(sport=1234, dport=1234)
590 / Raw(payload)
591 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100592 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100593 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
594 pkts.append(p)
595
596 return pkts
597
598 def _find_ip_match(self, find_in, pkt):
599 for p in find_in:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200600 if self.payload_to_info(p[Raw]) == self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100601 if p[IP].src != pkt[IP].src:
602 break
603 if p[IP].dst != pkt[IP].dst:
604 break
605 if p[UDP].sport != pkt[UDP].sport:
606 break
607 if p[UDP].dport != pkt[UDP].dport:
608 break
609 return p
610 return None
611
Matej Klotton16a14cd2016-12-07 15:09:13 +0100612 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
613 self.assertEqual(len(received_pkts), len(expected_pkts))
614 to_verify = list(expected_pkts)
615 for p in received_pkts:
616 self.assertEqual(p.src, dst_interface.local_mac)
617 self.assertEqual(p.dst, dst_interface.remote_mac)
618 x = self._find_ip_match(to_verify, p)
619 to_verify.remove(x)
620 self.assertListEqual(to_verify, [])
621
Neale Ranns097fa662018-05-01 05:17:55 -0700622 def verify_route_dump(self, routes):
623 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200624 self.assertTrue(
625 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
626 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100627
Neale Ranns097fa662018-05-01 05:17:55 -0700628 def verify_not_in_route_dump(self, routes):
629 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200630 self.assertFalse(
631 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
632 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100633
634 @classmethod
635 def setUpClass(cls):
636 """
637 #. Create and initialize 3 pg interfaces.
638 #. initialize class attributes configured_routes and deleted_routes
639 to store information between tests.
640 """
641 super(TestIPv4FibCrud, cls).setUpClass()
642
643 try:
644 # create 3 pg interfaces
645 cls.create_pg_interfaces(range(3))
646
647 cls.interfaces = list(cls.pg_interfaces)
648
649 # setup all interfaces
650 for i in cls.interfaces:
651 i.admin_up()
652 i.config_ip4()
653 i.resolve_arp()
654
655 cls.configured_routes = []
656 cls.deleted_routes = []
657 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
658
659 except Exception:
660 super(TestIPv4FibCrud, cls).tearDownClass()
661 raise
662
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700663 @classmethod
664 def tearDownClass(cls):
665 super(TestIPv4FibCrud, cls).tearDownClass()
666
Matej Klotton16a14cd2016-12-07 15:09:13 +0100667 def setUp(self):
668 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100669 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100670
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800671 self.configured_routes = []
672 self.deleted_routes = []
673
Matej Klotton16a14cd2016-12-07 15:09:13 +0100674 def test_1_add_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200675 """Add 1k routes"""
Matej Klotton16a14cd2016-12-07 15:09:13 +0100676
Neale Ranns097fa662018-05-01 05:17:55 -0700677 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200678 self.configured_routes.extend(
679 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
680 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100681
Neale Ranns097fa662018-05-01 05:17:55 -0700682 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100683
684 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200685 self.pg1, self.pg0, self.configured_routes, 100
686 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100687 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200688 self.pg2, self.pg0, self.configured_routes, 100
689 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100690 self.pg1.add_stream(self.stream_1)
691 self.pg2.add_stream(self.stream_2)
692
693 self.pg_enable_capture(self.pg_interfaces)
694 self.pg_start()
695
Klement Sekeradab231a2016-12-21 08:50:14 +0100696 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100697 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
698
Matej Klotton16a14cd2016-12-07 15:09:13 +0100699 def test_2_del_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200700 """Delete 100 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100701
702 - delete 10 routes check with traffic script.
703 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800704 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 self.configured_routes.extend(
706 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
707 )
708 self.deleted_routes.extend(
709 self.unconfig_fib_many_to_one(
710 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
711 )
712 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100713 for x in self.deleted_routes:
714 self.configured_routes.remove(x)
715
Neale Ranns097fa662018-05-01 05:17:55 -0700716 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100717
718 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 self.pg1, self.pg0, self.configured_routes, 100
720 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100721 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200722 self.pg2, self.pg0, self.configured_routes, 100
723 )
724 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
725 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100726 self.pg1.add_stream(self.stream_1 + self.stream_3)
727 self.pg2.add_stream(self.stream_2 + self.stream_4)
728 self.pg_enable_capture(self.pg_interfaces)
729 self.pg_start()
730
Klement Sekeradab231a2016-12-21 08:50:14 +0100731 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100732 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
733
734 def test_3_add_new_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200735 """Add 1k routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100736
737 - re-add 5 routes check with traffic script.
738 - add 100 routes check with traffic script.
739 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800740 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200741 self.configured_routes.extend(
742 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
743 )
744 self.deleted_routes.extend(
745 self.unconfig_fib_many_to_one(
746 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
747 )
748 )
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800749 for x in self.deleted_routes:
750 self.configured_routes.remove(x)
751
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200752 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 +0100753 self.configured_routes.extend(tmp)
754 for x in tmp:
755 self.deleted_routes.remove(x)
756
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200757 self.configured_routes.extend(
758 self.config_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
759 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100760
Neale Ranns097fa662018-05-01 05:17:55 -0700761 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100762
763 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200764 self.pg1, self.pg0, self.configured_routes, 300
765 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100766 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200767 self.pg2, self.pg0, self.configured_routes, 300
768 )
769 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
770 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100771
772 self.pg1.add_stream(self.stream_1 + self.stream_3)
773 self.pg2.add_stream(self.stream_2 + self.stream_4)
774 self.pg_enable_capture(self.pg_interfaces)
775 self.pg_start()
776
Klement Sekeradab231a2016-12-21 08:50:14 +0100777 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100778 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
779
Neale Ranns097fa662018-05-01 05:17:55 -0700780 # delete 5 routes check with traffic script.
781 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 self.deleted_routes.extend(
783 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 15)
784 )
785 self.deleted_routes.extend(
786 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 85)
787 )
788 self.deleted_routes.extend(
789 self.unconfig_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
790 )
Neale Ranns097fa662018-05-01 05:17:55 -0700791 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100792
793
Neale Ranns37be7362017-02-21 17:30:26 -0800794class TestIPNull(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200795 """IPv4 routes via NULL"""
Neale Ranns37be7362017-02-21 17:30:26 -0800796
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700797 @classmethod
798 def setUpClass(cls):
799 super(TestIPNull, cls).setUpClass()
800
801 @classmethod
802 def tearDownClass(cls):
803 super(TestIPNull, cls).tearDownClass()
804
Neale Ranns37be7362017-02-21 17:30:26 -0800805 def setUp(self):
806 super(TestIPNull, self).setUp()
807
808 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700809 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800810
811 for i in self.pg_interfaces:
812 i.admin_up()
813 i.config_ip4()
814 i.resolve_arp()
815
816 def tearDown(self):
817 super(TestIPNull, self).tearDown()
818 for i in self.pg_interfaces:
819 i.unconfig_ip4()
820 i.admin_down()
821
822 def test_ip_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200823 """IP NULL route"""
Neale Ranns37be7362017-02-21 17:30:26 -0800824
825 #
826 # A route via IP NULL that will reply with ICMP unreachables
827 #
Neale Ranns097fa662018-05-01 05:17:55 -0700828 ip_unreach = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200829 self,
830 "10.0.0.1",
831 32,
832 [
833 VppRoutePath(
834 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH
835 )
836 ],
837 )
Neale Ranns37be7362017-02-21 17:30:26 -0800838 ip_unreach.add_vpp_config()
839
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200840 p_unreach = (
841 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
842 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
843 / UDP(sport=1234, dport=1234)
844 / Raw(b"\xa5" * 100)
845 )
Neale Ranns37be7362017-02-21 17:30:26 -0800846 self.pg0.add_stream(p_unreach)
847 self.pg_enable_capture(self.pg_interfaces)
848 self.pg_start()
849
850 rx = self.pg0.get_capture(1)
851 rx = rx[0]
852 icmp = rx[ICMP]
853
854 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
855 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
856 self.assertEqual(icmp.src, self.pg0.remote_ip4)
857 self.assertEqual(icmp.dst, "10.0.0.1")
858
859 #
860 # ICMP replies are rate limited. so sit and spin.
861 #
862 self.sleep(1)
863
864 #
865 # A route via IP NULL that will reply with ICMP prohibited
866 #
Neale Ranns097fa662018-05-01 05:17:55 -0700867 ip_prohibit = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200868 self,
869 "10.0.0.2",
870 32,
871 [
872 VppRoutePath(
873 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT
874 )
875 ],
876 )
Neale Ranns37be7362017-02-21 17:30:26 -0800877 ip_prohibit.add_vpp_config()
878
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200879 p_prohibit = (
880 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
881 / IP(src=self.pg0.remote_ip4, dst="10.0.0.2")
882 / UDP(sport=1234, dport=1234)
883 / Raw(b"\xa5" * 100)
884 )
Neale Ranns37be7362017-02-21 17:30:26 -0800885
886 self.pg0.add_stream(p_prohibit)
887 self.pg_enable_capture(self.pg_interfaces)
888 self.pg_start()
889
890 rx = self.pg0.get_capture(1)
891
892 rx = rx[0]
893 icmp = rx[ICMP]
894
895 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
896 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
897 self.assertEqual(icmp.src, self.pg0.remote_ip4)
898 self.assertEqual(icmp.dst, "10.0.0.2")
899
Neale Ranns3b93be52018-09-07 01:48:54 -0700900 def test_ip_drop(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200901 """IP Drop Routes"""
Neale Ranns3b93be52018-09-07 01:48:54 -0700902
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200903 p = (
904 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
905 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
906 / UDP(sport=1234, dport=1234)
907 / Raw(b"\xa5" * 100)
908 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700909
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200910 r1 = VppIpRoute(
911 self,
912 "1.1.1.0",
913 24,
914 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
915 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700916 r1.add_vpp_config()
917
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400918 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700919
920 #
921 # insert a more specific as a drop
922 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200923 r2 = VppIpRoute(
924 self,
925 "1.1.1.1",
926 32,
927 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP)],
928 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700929 r2.add_vpp_config()
930
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400931 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700932 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400933 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700934
Neale Ranns37be7362017-02-21 17:30:26 -0800935
Neale Ranns180279b2017-03-16 15:49:09 -0400936class TestIPDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200937 """IPv4 disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -0400938
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700939 @classmethod
940 def setUpClass(cls):
941 super(TestIPDisabled, cls).setUpClass()
942
943 @classmethod
944 def tearDownClass(cls):
945 super(TestIPDisabled, cls).tearDownClass()
946
Neale Ranns180279b2017-03-16 15:49:09 -0400947 def setUp(self):
948 super(TestIPDisabled, self).setUp()
949
950 # create 2 pg interfaces
951 self.create_pg_interfaces(range(2))
952
953 # PG0 is IP enalbed
954 self.pg0.admin_up()
955 self.pg0.config_ip4()
956 self.pg0.resolve_arp()
957
958 # PG 1 is not IP enabled
959 self.pg1.admin_up()
960
961 def tearDown(self):
962 super(TestIPDisabled, self).tearDown()
963 for i in self.pg_interfaces:
964 i.unconfig_ip4()
965 i.admin_down()
966
Neale Ranns180279b2017-03-16 15:49:09 -0400967 def test_ip_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 """IP Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -0400969
Neale Ranns990f6942020-10-20 07:20:17 +0000970 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
971 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
972
Neale Ranns180279b2017-03-16 15:49:09 -0400973 #
974 # An (S,G).
975 # one accepting interface, pg0, 2 forwarding interfaces
976 #
977 route_232_1_1_1 = VppIpMRoute(
978 self,
979 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200980 "232.1.1.1",
981 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000982 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200983 [
984 VppMRoutePath(
985 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
986 ),
987 VppMRoutePath(
988 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
989 ),
990 ],
991 )
Neale Ranns180279b2017-03-16 15:49:09 -0400992 route_232_1_1_1.add_vpp_config()
993
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200994 pu = (
995 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
996 / IP(src="10.10.10.10", dst=self.pg0.remote_ip4)
997 / UDP(sport=1234, dport=1234)
998 / Raw(b"\xa5" * 100)
999 )
1000 pm = (
1001 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1002 / IP(src="10.10.10.10", dst="232.1.1.1")
1003 / UDP(sport=1234, dport=1234)
1004 / Raw(b"\xa5" * 100)
1005 )
Neale Ranns180279b2017-03-16 15:49:09 -04001006
1007 #
1008 # PG1 does not forward IP traffic
1009 #
1010 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1011 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1012
1013 #
1014 # IP enable PG1
1015 #
1016 self.pg1.config_ip4()
1017
1018 #
1019 # Now we get packets through
1020 #
1021 self.pg1.add_stream(pu)
1022 self.pg_enable_capture(self.pg_interfaces)
1023 self.pg_start()
1024 rx = self.pg0.get_capture(1)
1025
1026 self.pg1.add_stream(pm)
1027 self.pg_enable_capture(self.pg_interfaces)
1028 self.pg_start()
1029 rx = self.pg0.get_capture(1)
1030
1031 #
1032 # Disable PG1
1033 #
1034 self.pg1.unconfig_ip4()
1035
1036 #
1037 # PG1 does not forward IP traffic
1038 #
1039 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1040 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1041
1042
Neale Ranns9a69a602017-03-26 10:56:33 -07001043class TestIPSubNets(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001044 """IPv4 Subnets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001045
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001046 @classmethod
1047 def setUpClass(cls):
1048 super(TestIPSubNets, cls).setUpClass()
1049
1050 @classmethod
1051 def tearDownClass(cls):
1052 super(TestIPSubNets, cls).tearDownClass()
1053
Neale Ranns9a69a602017-03-26 10:56:33 -07001054 def setUp(self):
1055 super(TestIPSubNets, self).setUp()
1056
1057 # create a 2 pg interfaces
1058 self.create_pg_interfaces(range(2))
1059
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001060 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -07001061 self.pg0.admin_up()
1062
1063 # pg1 is setup normally
1064 self.pg1.admin_up()
1065 self.pg1.config_ip4()
1066 self.pg1.resolve_arp()
1067
1068 def tearDown(self):
1069 super(TestIPSubNets, self).tearDown()
1070 for i in self.pg_interfaces:
1071 i.admin_down()
1072
Neale Ranns9a69a602017-03-26 10:56:33 -07001073 def test_ip_sub_nets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001074 """IP Sub Nets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001075
1076 #
1077 # Configure a covering route to forward so we know
1078 # when we are dropping
1079 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001080 cover_route = VppIpRoute(
1081 self,
1082 "10.0.0.0",
1083 8,
1084 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1085 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001086 cover_route.add_vpp_config()
1087
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001088 p = (
1089 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1090 / IP(dst="10.10.10.10", src=self.pg0.local_ip4)
1091 / UDP(sport=1234, dport=1234)
1092 / Raw(b"\xa5" * 100)
1093 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001094
1095 self.pg1.add_stream(p)
1096 self.pg_enable_capture(self.pg_interfaces)
1097 self.pg_start()
1098 rx = self.pg1.get_capture(1)
1099
1100 #
1101 # Configure some non-/24 subnets on an IP interface
1102 #
1103 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1104
Ole Troan9a475372019-03-05 16:58:24 +01001105 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001106 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16"
1107 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001108
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 pn = (
1110 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1111 / IP(dst="10.10.0.0", src=self.pg0.local_ip4)
1112 / UDP(sport=1234, dport=1234)
1113 / Raw(b"\xa5" * 100)
1114 )
1115 pb = (
1116 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1117 / IP(dst="10.10.255.255", src=self.pg0.local_ip4)
1118 / UDP(sport=1234, dport=1234)
1119 / Raw(b"\xa5" * 100)
1120 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001121
1122 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
1123 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
1124
1125 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001126 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16", is_add=0
1128 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001129
Neale Ranns9a69a602017-03-26 10:56:33 -07001130 self.pg1.add_stream(pn)
1131 self.pg_enable_capture(self.pg_interfaces)
1132 self.pg_start()
1133 rx = self.pg1.get_capture(1)
1134 self.pg1.add_stream(pb)
1135 self.pg_enable_capture(self.pg_interfaces)
1136 self.pg_start()
1137 rx = self.pg1.get_capture(1)
1138
1139 #
1140 # A /31 is a special case where the 'other-side' is an attached host
1141 # packets to that peer generate ARP requests
1142 #
1143 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1144
Ole Troan9a475372019-03-05 16:58:24 +01001145 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001146 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31"
1147 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001148
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001149 pn = (
1150 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1151 / IP(dst="10.10.10.11", src=self.pg0.local_ip4)
1152 / UDP(sport=1234, dport=1234)
1153 / Raw(b"\xa5" * 100)
1154 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001155
1156 self.pg1.add_stream(pn)
1157 self.pg_enable_capture(self.pg_interfaces)
1158 self.pg_start()
1159 rx = self.pg0.get_capture(1)
1160 rx[ARP]
1161
1162 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001163 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001164 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31", is_add=0
1165 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001166
Neale Ranns9a69a602017-03-26 10:56:33 -07001167 self.pg1.add_stream(pn)
1168 self.pg_enable_capture(self.pg_interfaces)
1169 self.pg_start()
1170 rx = self.pg1.get_capture(1)
1171
1172
Neale Ranns227038a2017-04-21 01:07:59 -07001173class TestIPLoadBalance(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001174 """IPv4 Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001175
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001176 @classmethod
1177 def setUpClass(cls):
1178 super(TestIPLoadBalance, cls).setUpClass()
1179
1180 @classmethod
1181 def tearDownClass(cls):
1182 super(TestIPLoadBalance, cls).tearDownClass()
1183
Neale Ranns227038a2017-04-21 01:07:59 -07001184 def setUp(self):
1185 super(TestIPLoadBalance, self).setUp()
1186
1187 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -07001188 mpls_tbl = VppMplsTable(self, 0)
1189 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -07001190
1191 for i in self.pg_interfaces:
1192 i.admin_up()
1193 i.config_ip4()
1194 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -07001195 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001196
1197 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -07001198 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -07001199 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001200 i.unconfig_ip4()
1201 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001202 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -07001203
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001204 def total_len(self, rxs):
1205 n = 0
1206 for rx in rxs:
1207 n += len(rx)
1208 return n
1209
Neale Ranns227038a2017-04-21 01:07:59 -07001210 def test_ip_load_balance(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001211 """IP Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001212
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001213 fhc = VppEnum.vl_api_ip_flow_hash_config_t
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001214 fhcv2 = VppEnum.vl_api_ip_flow_hash_config_v2_t
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001215 af = VppEnum.vl_api_address_family_t
1216
Neale Ranns227038a2017-04-21 01:07:59 -07001217 #
1218 # An array of packets that differ only in the destination port
1219 #
Neale Ranns71275e32017-05-25 12:38:58 -07001220 port_ip_pkts = []
1221 port_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001222 port_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001223
1224 #
1225 # An array of packets that differ only in the source address
1226 #
Neale Ranns71275e32017-05-25 12:38:58 -07001227 src_ip_pkts = []
1228 src_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001229 src_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001230
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001231 for ii in range(NUM_PKTS):
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001232 internal_src_ip_hdr = IP(dst="10.0.0.1", src="20.0.0.1")
1233
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001234 port_ip_hdr = (
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001235 internal_src_ip_hdr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001236 / UDP(sport=1234, dport=1234 + ii)
1237 / Raw(b"\xa5" * 100)
1238 )
1239 port_ip_pkts.append(
1240 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)
1241 )
1242 port_mpls_pkts.append(
1243 (
1244 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1245 / MPLS(label=66, ttl=2)
1246 / port_ip_hdr
1247 )
1248 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001249 port_gtp_pkts.append(
1250 (
1251 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1252 / internal_src_ip_hdr
1253 / UDP(sport=2152, dport=2152, chksum=0)
1254 / GTP_U_Header(gtp_type="g_pdu", teid=200)
1255 / Raw(b"\xa5" * 100)
1256 )
1257 )
Neale Ranns71275e32017-05-25 12:38:58 -07001258
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001259 src_ip_hdr = (
1260 IP(dst="10.0.0.1", src="20.0.0.%d" % ii)
1261 / UDP(sport=1234, dport=1234)
1262 / Raw(b"\xa5" * 100)
1263 )
1264 src_ip_pkts.append(
1265 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)
1266 )
1267 src_mpls_pkts.append(
1268 (
1269 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1270 / MPLS(label=66, ttl=2)
1271 / src_ip_hdr
1272 )
1273 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001274 src_gtp_pkts.append(
1275 (
1276 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1277 / IP(dst="10.0.0.1", src="20.0.0.1")
1278 / UDP(sport=2152, dport=2152, chksum=0)
1279 / GTP_U_Header(gtp_type="g_pdu", teid=ii)
1280 / Raw(b"\xa5" * 100)
1281 )
1282 )
Neale Ranns227038a2017-04-21 01:07:59 -07001283
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001284 route_10_0_0_1 = VppIpRoute(
1285 self,
1286 "10.0.0.1",
1287 32,
1288 [
1289 VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index),
1290 VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index),
1291 ],
1292 )
Neale Ranns227038a2017-04-21 01:07:59 -07001293 route_10_0_0_1.add_vpp_config()
1294
Neale Ranns71275e32017-05-25 12:38:58 -07001295 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1296 binding.add_vpp_config()
1297
Neale Ranns227038a2017-04-21 01:07:59 -07001298 #
1299 # inject the packet on pg0 - expect load-balancing across the 2 paths
1300 # - since the default hash config is to use IP src,dst and port
1301 # src,dst
1302 # We are not going to ensure equal amounts of packets across each link,
1303 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001304 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001305 # balancing. So instead just ensure there is traffic on each link.
1306 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001307 rx = self.send_and_expect_load_balancing(
1308 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1309 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001310 n_ip_pg0 = len(rx[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001311 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1312 self.send_and_expect_load_balancing(
1313 self.pg0, port_mpls_pkts, [self.pg1, self.pg2]
1314 )
1315 rx = self.send_and_expect_load_balancing(
1316 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1317 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001318 n_mpls_pg0 = len(rx[0])
1319
1320 #
1321 # change the router ID and expect the distribution changes
1322 #
1323 self.vapi.set_ip_flow_hash_router_id(router_id=0x11111111)
1324
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001325 rx = self.send_and_expect_load_balancing(
1326 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1327 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001328 self.assertNotEqual(n_ip_pg0, len(rx[0]))
1329
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001330 rx = self.send_and_expect_load_balancing(
1331 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1332 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001333 self.assertNotEqual(n_mpls_pg0, len(rx[0]))
Neale Ranns227038a2017-04-21 01:07:59 -07001334
1335 #
1336 # change the flow hash config so it's only IP src,dst
1337 # - now only the stream with differing source address will
1338 # load-balance
1339 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001340 self.vapi.set_ip_flow_hash_v2(
1341 af=af.ADDRESS_IP4,
1342 table_id=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001343 flow_hash_config=(
1344 fhc.IP_API_FLOW_HASH_SRC_IP
1345 | fhc.IP_API_FLOW_HASH_DST_IP
1346 | fhc.IP_API_FLOW_HASH_PROTO
1347 ),
1348 )
Neale Ranns227038a2017-04-21 01:07:59 -07001349
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001350 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1351 self.send_and_expect_load_balancing(
1352 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1353 )
Neale Ranns227038a2017-04-21 01:07:59 -07001354
Neale Ranns699bea22022-02-17 09:22:16 +00001355 self.send_and_expect_only(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001356
1357 #
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001358 # this case gtp v1 teid key LB
1359 #
1360 self.vapi.set_ip_flow_hash_v3(
1361 af=af.ADDRESS_IP4,
1362 table_id=0,
1363 flow_hash_config=(
1364 fhcv2.IP_API_V2_FLOW_HASH_SRC_IP
1365 | fhcv2.IP_API_V2_FLOW_HASH_PROTO
1366 | fhcv2.IP_API_V2_FLOW_HASH_GTPV1_TEID
1367 ),
1368 )
1369 self.logger.info(self.vapi.cli("show ip fib"))
1370
1371 self.send_and_expect_load_balancing(
1372 self.pg0, src_gtp_pkts, [self.pg1, self.pg2]
1373 )
1374
1375 self.send_and_expect_only(self.pg0, port_gtp_pkts, self.pg2)
1376
1377 #
Neale Ranns227038a2017-04-21 01:07:59 -07001378 # change the flow hash config back to defaults
1379 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001380 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 -07001381
1382 #
1383 # Recursive prefixes
1384 # - testing that 2 stages of load-balancing occurs and there is no
1385 # polarisation (i.e. only 2 of 4 paths are used)
1386 #
1387 port_pkts = []
1388 src_pkts = []
1389
1390 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001391 port_pkts.append(
1392 (
1393 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1394 / IP(dst="1.1.1.1", src="20.0.0.1")
1395 / UDP(sport=1234, dport=1234 + ii)
1396 / Raw(b"\xa5" * 100)
1397 )
1398 )
1399 src_pkts.append(
1400 (
1401 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1402 / IP(dst="1.1.1.1", src="20.0.0.%d" % ii)
1403 / UDP(sport=1234, dport=1234)
1404 / Raw(b"\xa5" * 100)
1405 )
1406 )
Neale Ranns227038a2017-04-21 01:07:59 -07001407
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001408 route_10_0_0_2 = VppIpRoute(
1409 self,
1410 "10.0.0.2",
1411 32,
1412 [
1413 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1414 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1415 ],
1416 )
Neale Ranns227038a2017-04-21 01:07:59 -07001417 route_10_0_0_2.add_vpp_config()
1418
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001419 route_1_1_1_1 = VppIpRoute(
1420 self,
1421 "1.1.1.1",
1422 32,
1423 [
1424 VppRoutePath("10.0.0.2", 0xFFFFFFFF),
1425 VppRoutePath("10.0.0.1", 0xFFFFFFFF),
1426 ],
1427 )
Neale Ranns227038a2017-04-21 01:07:59 -07001428 route_1_1_1_1.add_vpp_config()
1429
1430 #
1431 # inject the packet on pg0 - expect load-balancing across all 4 paths
1432 #
1433 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001434 self.send_and_expect_load_balancing(
1435 self.pg0, port_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1436 )
1437 self.send_and_expect_load_balancing(
1438 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1439 )
Neale Ranns227038a2017-04-21 01:07:59 -07001440
Neale Ranns42e6b092017-07-31 02:56:03 -07001441 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001442 # bring down pg1 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001443 #
1444 self.pg1.link_down()
1445
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 rx = self.send_and_expect_load_balancing(
1447 self.pg0, src_pkts, [self.pg2, self.pg3, self.pg4]
1448 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001449 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001450
1451 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001452 # bring down pg2 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001453 #
1454 self.pg2.link_down()
1455
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001456 rx = self.send_and_expect_load_balancing(
1457 self.pg0, src_pkts, [self.pg3, self.pg4]
1458 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001459 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001460
1461 #
1462 # bring the links back up - expect LB over all again
1463 #
1464 self.pg1.link_up()
1465 self.pg2.link_up()
1466
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001467 rx = self.send_and_expect_load_balancing(
1468 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1469 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001470 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001471
1472 #
1473 # The same link-up/down but this time admin state
1474 #
1475 self.pg1.admin_down()
1476 self.pg2.admin_down()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001477 rx = self.send_and_expect_load_balancing(
1478 self.pg0, src_pkts, [self.pg3, self.pg4]
1479 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001480 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001481 self.pg1.admin_up()
1482 self.pg2.admin_up()
1483 self.pg1.resolve_arp()
1484 self.pg2.resolve_arp()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001485 rx = self.send_and_expect_load_balancing(
1486 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1487 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001488 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001489
1490 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001491 # Recursive prefixes
1492 # - testing that 2 stages of load-balancing, no choices
1493 #
1494 port_pkts = []
1495
1496 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001497 port_pkts.append(
1498 (
1499 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1500 / IP(dst="1.1.1.2", src="20.0.0.2")
1501 / UDP(sport=1234, dport=1234 + ii)
1502 / Raw(b"\xa5" * 100)
1503 )
1504 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001505
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001506 route_10_0_0_3 = VppIpRoute(
1507 self,
1508 "10.0.0.3",
1509 32,
1510 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
1511 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001512 route_10_0_0_3.add_vpp_config()
1513
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001514 route_1_1_1_2 = VppIpRoute(
1515 self, "1.1.1.2", 32, [VppRoutePath("10.0.0.3", 0xFFFFFFFF)]
1516 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001517 route_1_1_1_2.add_vpp_config()
1518
1519 #
Neale Ranns63480742019-03-13 06:41:52 -07001520 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001521 #
1522 self.vapi.cli("clear trace")
Neale Ranns699bea22022-02-17 09:22:16 +00001523 self.send_and_expect_only(self.pg0, port_pkts, self.pg3)
Neale Ranns42e6b092017-07-31 02:56:03 -07001524
Neale Ranns63480742019-03-13 06:41:52 -07001525 #
1526 # Add a LB route in the presence of a down link - expect no
1527 # packets over the down link
1528 #
1529 self.pg3.link_down()
1530
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001531 route_10_0_0_3 = VppIpRoute(
1532 self,
1533 "10.0.0.3",
1534 32,
1535 [
1536 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1537 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1538 ],
1539 )
Neale Ranns63480742019-03-13 06:41:52 -07001540 route_10_0_0_3.add_vpp_config()
1541
1542 port_pkts = []
1543 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001544 port_pkts.append(
1545 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1546 / IP(dst="10.0.0.3", src="20.0.0.2")
1547 / UDP(sport=1234, dport=1234 + ii)
1548 / Raw(b"\xa5" * 100)
1549 )
Neale Ranns63480742019-03-13 06:41:52 -07001550
Neale Ranns699bea22022-02-17 09:22:16 +00001551 self.send_and_expect_only(self.pg0, port_pkts, self.pg4)
Neale Ranns63480742019-03-13 06:41:52 -07001552
1553 # bring the link back up
1554 self.pg3.link_up()
1555
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001556 rx = self.send_and_expect_load_balancing(
1557 self.pg0, port_pkts, [self.pg3, self.pg4]
1558 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001559 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001560
Neale Ranns30d0fd42017-05-30 07:30:04 -07001561
1562class TestIPVlan0(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001563 """IPv4 VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001564
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001565 @classmethod
1566 def setUpClass(cls):
1567 super(TestIPVlan0, cls).setUpClass()
1568
1569 @classmethod
1570 def tearDownClass(cls):
1571 super(TestIPVlan0, cls).tearDownClass()
1572
Neale Ranns30d0fd42017-05-30 07:30:04 -07001573 def setUp(self):
1574 super(TestIPVlan0, self).setUp()
1575
1576 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001577 mpls_tbl = VppMplsTable(self, 0)
1578 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001579
1580 for i in self.pg_interfaces:
1581 i.admin_up()
1582 i.config_ip4()
1583 i.resolve_arp()
1584 i.enable_mpls()
1585
1586 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001587 for i in self.pg_interfaces:
1588 i.disable_mpls()
1589 i.unconfig_ip4()
1590 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001591 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001592
Neale Ranns30d0fd42017-05-30 07:30:04 -07001593 def test_ip_vlan_0(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001594 """IP VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001595
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001596 pkts = (
1597 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1598 / Dot1Q(vlan=0)
1599 / IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4)
1600 / UDP(sport=1234, dport=1234)
1601 / Raw(b"\xa5" * 100)
1602 ) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001603
1604 #
1605 # Expect that packets sent on VLAN-0 are forwarded on the
1606 # main interface.
1607 #
1608 self.send_and_expect(self.pg0, pkts, self.pg1)
1609
1610
Brian Russell318fdb82021-01-19 16:56:32 +00001611class IPPuntSetup(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001612 """Setup for IPv4 Punt Police/Redirect"""
Neale Rannsd91c1db2017-07-31 02:30:50 -07001613
Brian Russell318fdb82021-01-19 16:56:32 +00001614 def punt_setup(self):
Pavel Kotucek609e1212018-11-27 09:59:44 +01001615 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001616
1617 for i in self.pg_interfaces:
1618 i.admin_up()
1619 i.config_ip4()
1620 i.resolve_arp()
1621
Neale Ranns68577d22019-06-04 13:31:23 +00001622 # use UDP packet that have a port we need to explicitly
1623 # register to get punted.
1624 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1625 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1626 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1627 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001628 "type": pt_l4,
1629 "punt": {
1630 "l4": {
1631 "af": af_ip4,
1632 "protocol": udp_proto,
1633 "port": 1234,
Neale Ranns68577d22019-06-04 13:31:23 +00001634 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001635 },
Neale Ranns68577d22019-06-04 13:31:23 +00001636 }
1637
1638 self.vapi.set_punt(is_add=1, punt=punt_udp)
1639
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001640 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
1641 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001642 "type": pt_l4,
1643 "punt": {
1644 "l4": {
1645 "af": af_ip6,
1646 "protocol": udp_proto,
1647 "port": 1236,
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001648 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001649 },
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001650 }
1651
1652 self.vapi.set_punt(is_add=1, punt=punt_udp)
1653
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001654 self.pkt = (
1655 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1656 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1657 / UDP(sport=1234, dport=1234)
1658 / Raw(b"\xa5" * 100)
1659 )
Neale Rannsd91c1db2017-07-31 02:30:50 -07001660
Brian Russell318fdb82021-01-19 16:56:32 +00001661 def punt_teardown(self):
1662 for i in self.pg_interfaces:
1663 i.unconfig_ip4()
1664 i.admin_down()
1665
1666
1667class TestIPPunt(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001668 """IPv4 Punt Police/Redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001669
1670 def setUp(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001671 super().setUp()
1672 super().punt_setup()
Brian Russell318fdb82021-01-19 16:56:32 +00001673
1674 def tearDown(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001675 super().punt_teardown()
1676 super().tearDown()
1677
1678 def test_ip_punt_api_validation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001679 """IP punt API parameter validation"""
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001680
1681 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001682 punt = {
1683 "rx_sw_if_index": self.pg0.sw_if_index,
1684 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1685 "n_paths": 1000000,
1686 "paths": [],
1687 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001688
1689 with self.assertRaises(vpp_papi.VPPIOError):
1690 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
1691
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001692 punt = {
1693 "rx_sw_if_index": self.pg0.sw_if_index,
1694 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1695 "n_paths": 0,
1696 "paths": [],
1697 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001698
1699 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
Brian Russell318fdb82021-01-19 16:56:32 +00001700
1701 def test_ip_punt(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001702 """IP punt police and redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001703
1704 pkts = self.pkt * 1025
Neale Rannsd91c1db2017-07-31 02:30:50 -07001705
1706 #
1707 # Configure a punt redirect via pg1.
1708 #
Ole Troan0bcad322018-12-11 13:04:01 +01001709 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001710 ip_punt_redirect = VppIpPuntRedirect(
1711 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1712 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001713 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001714
1715 self.send_and_expect(self.pg0, pkts, self.pg1)
1716
1717 #
1718 # add a policer
1719 #
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001720 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1)
1721 policer.add_vpp_config()
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001722 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1723 ip_punt_policer.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001724
1725 self.vapi.cli("clear trace")
1726 self.pg0.add_stream(pkts)
1727 self.pg_enable_capture(self.pg_interfaces)
1728 self.pg_start()
1729
1730 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001731 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001732 # but not equal to the number sent, since some were policed
1733 #
1734 rx = self.pg1._get_capture(1)
Brian Russelle9887262021-01-27 14:45:22 +00001735
1736 stats = policer.get_stats()
1737
1738 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001739 self.assertGreater(stats["conform_packets"], 0)
1740 self.assertEqual(stats["exceed_packets"], 0)
1741 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00001742
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001743 self.assertGreater(len(rx), 0)
1744 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001745
1746 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001747 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001748 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001749 ip_punt_policer.remove_vpp_config()
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001750 policer.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001751 self.send_and_expect(self.pg0, pkts, self.pg1)
1752
1753 #
1754 # remove the redirect. expect full drop.
1755 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001756 ip_punt_redirect.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001757 self.send_and_assert_no_replies(self.pg0, pkts, "IP no punt config")
Neale Rannsd91c1db2017-07-31 02:30:50 -07001758
1759 #
1760 # Add a redirect that is not input port selective
1761 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001762 ip_punt_redirect = VppIpPuntRedirect(
1763 self, 0xFFFFFFFF, self.pg1.sw_if_index, nh_addr
1764 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001765 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001766 self.send_and_expect(self.pg0, pkts, self.pg1)
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001767 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001768
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001769 def test_ip_punt_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001770 """IP punt/local with VRFs"""
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001771
1772 # use a punt redirect to test if for-us packets are accepted
1773 pkts = self.pkt * 1025
1774
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001775 vlans_pg0 = [VppDot1QSubint(self, self.pg0, v) for v in range(100, 104)]
1776 vlans_pg1 = [VppDot1QSubint(self, self.pg1, v) for v in range(100, 104)]
1777 tbl4 = [VppIpTable(self, v).add_vpp_config() for v in range(100, 104)]
1778 tbl6 = [VppIpTable(self, v, True).add_vpp_config() for v in range(100, 104)]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001779
1780 for v in vlans_pg0 + vlans_pg1:
1781 v.admin_up()
1782 v.set_table_ip4(v.vlan)
1783 v.set_table_ip6(v.vlan)
1784 v.config_ip4()
1785 v.config_ip6()
1786 v.resolve_arp()
1787 v.resolve_ndp()
1788
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001789 [
1790 VppIpPuntRedirect(
1791 self,
1792 vlans_pg0[i].sw_if_index,
1793 vlans_pg1[i].sw_if_index,
1794 vlans_pg1[i].remote_ip4,
1795 ).add_vpp_config()
1796 for i in range(4)
1797 ]
1798 [
1799 VppIpPuntRedirect(
1800 self,
1801 vlans_pg0[i].sw_if_index,
1802 vlans_pg1[i].sw_if_index,
1803 vlans_pg1[i].remote_ip6,
1804 ).add_vpp_config()
1805 for i in range(4)
1806 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001807
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001808 pkts = [
1809 (
1810 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1811 / Dot1Q(vlan=i.vlan)
1812 / IP(src=i.remote_ip4, dst=i.local_ip4)
1813 / UDP(sport=1234, dport=1234)
1814 / Raw(b"\xa5" * 100)
1815 )
1816 for i in vlans_pg0
1817 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001818
1819 self.send_and_expect(self.pg0, pkts, self.pg1)
1820
1821 #
1822 # IPv4
1823 #
1824
1825 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001826 pkts = [
1827 (
1828 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1829 / Dot1Q(vlan=i.vlan)
1830 / IP(src="1.1.1.1", dst=i.local_ip4)
1831 / UDP(sport=1234, dport=1234)
1832 / Raw(b"\xa5" * 100)
1833 )
1834 for i in vlans_pg0
1835 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001836 # single and dual loop
1837 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1838 self.send_and_assert_no_replies(self.pg0, pkts)
1839
Neale Rannse22a7042022-08-09 03:03:29 +00001840 self.assert_error_counter_equal("/err/ip4-local/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001841
1842 # using the same source in different tables, should reject
1843 # for the table that the source is not present in
1844 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001845 pkts = [
1846 (
1847 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1848 / Dot1Q(vlan=i.vlan)
1849 / IP(src=vlans_pg0[0].remote_ip4, dst=i.local_ip4)
1850 / UDP(sport=1234, dport=1234)
1851 / Raw(b"\xa5" * 100)
1852 )
1853 for i in vlans_pg0
1854 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001855 # single loop accept and drop
1856 # followed by both in the same frame/loop
1857 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1858 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1859 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1860
1861 # using the same source in different tables, should reject
1862 # for the table that the source is not present in
1863 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001864 pkts = [
1865 (
1866 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1867 / Dot1Q(vlan=i.vlan)
1868 / IP(src=vlans_pg0[3].remote_ip4, dst=i.local_ip4)
1869 / UDP(sport=1234, dport=1234)
1870 / Raw(b"\xa5" * 100)
1871 )
1872 for i in vlans_pg0
1873 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001874
1875 # single loop accept and drop
1876 # followed by both in the same frame/loop
1877 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1878 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1879 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1880
1881 #
1882 # IPv6
1883 #
1884
1885 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001886 pkts = [
1887 (
1888 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1889 / Dot1Q(vlan=i.vlan)
1890 / IPv6(src="1::1", dst=i.local_ip6)
1891 / UDP(sport=1236, dport=1236)
1892 / Raw(b"\xa5" * 100)
1893 )
1894 for i in vlans_pg0
1895 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001896 # single and dual loop
1897 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1898 self.send_and_assert_no_replies(self.pg0, pkts)
1899
Neale Rannse22a7042022-08-09 03:03:29 +00001900 self.assert_error_counter_equal("/err/ip6-input/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001901
1902 # using the same source in different tables, should reject
1903 # for the table that the source is not present in
1904 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001905 pkts = [
1906 (
1907 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1908 / Dot1Q(vlan=i.vlan)
1909 / IPv6(src=vlans_pg0[0].remote_ip6, dst=i.local_ip6)
1910 / UDP(sport=1236, dport=1236)
1911 / Raw(b"\xa5" * 100)
1912 )
1913 for i in vlans_pg0
1914 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001915 # single loop accept and drop
1916 # followed by both in the same frame/loop
1917 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1918 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1919 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1920
1921 # using the same source in different tables, should reject
1922 # for the table that the source is not present in
1923 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001924 pkts = [
1925 (
1926 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1927 / Dot1Q(vlan=i.vlan)
1928 / IPv6(src=vlans_pg0[3].remote_ip6, dst=i.local_ip6)
1929 / UDP(sport=1236, dport=1236)
1930 / Raw(b"\xa5" * 100)
1931 )
1932 for i in vlans_pg0
1933 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001934
1935 # single loop accept and drop
1936 # followed by both in the same frame/loop
1937 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1938 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1939 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1940
1941 for v in vlans_pg0 + vlans_pg1:
1942 v.unconfig_ip4()
1943 v.unconfig_ip6()
1944 v.set_table_ip4(0)
1945 v.set_table_ip6(0)
1946
Pavel Kotucek609e1212018-11-27 09:59:44 +01001947 def test_ip_punt_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001948 """IP4 punt redirect dump"""
Pavel Kotucek609e1212018-11-27 09:59:44 +01001949
1950 #
1951 # Configure a punt redirects
1952 #
Ole Troan0bcad322018-12-11 13:04:01 +01001953 nh_address = self.pg3.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001954 ipr_03 = VppIpPuntRedirect(
1955 self, self.pg0.sw_if_index, self.pg3.sw_if_index, nh_address
1956 )
1957 ipr_13 = VppIpPuntRedirect(
1958 self, self.pg1.sw_if_index, self.pg3.sw_if_index, nh_address
1959 )
1960 ipr_23 = VppIpPuntRedirect(
1961 self, self.pg2.sw_if_index, self.pg3.sw_if_index, "0.0.0.0"
1962 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001963 ipr_03.add_vpp_config()
1964 ipr_13.add_vpp_config()
1965 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01001966
1967 #
1968 # Dump pg0 punt redirects
1969 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001970 self.assertTrue(ipr_03.query_vpp_config())
1971 self.assertTrue(ipr_13.query_vpp_config())
1972 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01001973
1974 #
1975 # Dump punt redirects for all interfaces
1976 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001977 punts = self.vapi.ip_punt_redirect_dump(0xFFFFFFFF)
Pavel Kotucek609e1212018-11-27 09:59:44 +01001978 self.assertEqual(len(punts), 3)
1979 for p in punts:
1980 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001981 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001982 self.assertEqual(str(punts[2].punt.nh), "0.0.0.0")
Pavel Kotucek609e1212018-11-27 09:59:44 +01001983
Neale Rannsd91c1db2017-07-31 02:30:50 -07001984
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001985class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001986 """IPv4 Punt Policer thread handoff"""
1987
Klement Sekera8d815022021-03-15 16:58:10 +01001988 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001989
1990 def setUp(self):
1991 super(TestIPPuntHandoff, self).setUp()
1992 super(TestIPPuntHandoff, self).punt_setup()
1993
1994 def tearDown(self):
1995 super(TestIPPuntHandoff, self).punt_teardown()
1996 super(TestIPPuntHandoff, self).tearDown()
1997
1998 def test_ip_punt_policer_handoff(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001999 """IP4 punt policer thread handoff"""
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002000 pkts = self.pkt * NUM_PKTS
2001
2002 #
2003 # Configure a punt redirect via pg1.
2004 #
2005 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002006 ip_punt_redirect = VppIpPuntRedirect(
2007 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
2008 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002009 ip_punt_redirect.add_vpp_config()
2010
2011 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002012 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
2013 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002014 #
2015 # This policer drops no packets, we are just
2016 # testing that they get to the right thread.
2017 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002018 policer = VppPolicer(
2019 self,
2020 "ip4-punt",
2021 400,
2022 0,
2023 10,
2024 0,
2025 1,
2026 0,
2027 0,
2028 False,
2029 action_tx,
2030 action_tx,
2031 action_tx,
2032 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002033 policer.add_vpp_config()
2034 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
2035 ip_punt_policer.add_vpp_config()
2036
2037 for worker in [0, 1]:
2038 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00002039 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002040
Brian Russelle9887262021-01-27 14:45:22 +00002041 # Combined stats, all threads
2042 stats = policer.get_stats()
2043
2044 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002045 self.assertGreater(stats["conform_packets"], 0)
2046 self.assertEqual(stats["exceed_packets"], 0)
2047 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002048
2049 # Worker 0, should have done all the policing
2050 stats0 = policer.get_stats(worker=0)
2051 self.assertEqual(stats, stats0)
2052
2053 # Worker 1, should have handed everything off
2054 stats1 = policer.get_stats(worker=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002055 self.assertEqual(stats1["conform_packets"], 0)
2056 self.assertEqual(stats1["exceed_packets"], 0)
2057 self.assertEqual(stats1["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002058
Brian Russellbb983142021-02-10 13:56:06 +00002059 # Bind the policer to worker 1 and repeat
2060 policer.bind_vpp_config(1, True)
2061 for worker in [0, 1]:
2062 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2063 self.logger.debug(self.vapi.cli("show trace max 100"))
2064
2065 # The 2 workers should now have policed the same amount
2066 stats = policer.get_stats()
2067 stats0 = policer.get_stats(worker=0)
2068 stats1 = policer.get_stats(worker=1)
2069
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002070 self.assertGreater(stats0["conform_packets"], 0)
2071 self.assertEqual(stats0["exceed_packets"], 0)
2072 self.assertGreater(stats0["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002073
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002074 self.assertGreater(stats1["conform_packets"], 0)
2075 self.assertEqual(stats1["exceed_packets"], 0)
2076 self.assertGreater(stats1["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002077
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002078 self.assertEqual(
2079 stats0["conform_packets"] + stats1["conform_packets"],
2080 stats["conform_packets"],
2081 )
Brian Russellbb983142021-02-10 13:56:06 +00002082
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002083 self.assertEqual(
2084 stats0["violate_packets"] + stats1["violate_packets"],
2085 stats["violate_packets"],
2086 )
Brian Russellbb983142021-02-10 13:56:06 +00002087
2088 # Unbind the policer and repeat
2089 policer.bind_vpp_config(1, False)
2090 for worker in [0, 1]:
2091 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2092 self.logger.debug(self.vapi.cli("show trace max 100"))
2093
2094 # The policer should auto-bind to worker 0 when packets arrive
2095 stats = policer.get_stats()
2096 stats0new = policer.get_stats(worker=0)
2097 stats1new = policer.get_stats(worker=1)
2098
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002099 self.assertGreater(stats0new["conform_packets"], stats0["conform_packets"])
2100 self.assertEqual(stats0new["exceed_packets"], 0)
2101 self.assertGreater(stats0new["violate_packets"], stats0["violate_packets"])
Brian Russellbb983142021-02-10 13:56:06 +00002102
2103 self.assertEqual(stats1, stats1new)
2104
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002105 #
2106 # Clean up
2107 #
2108 ip_punt_policer.remove_vpp_config()
2109 policer.remove_vpp_config()
2110 ip_punt_redirect.remove_vpp_config()
2111
2112
Neale Ranns054c03a2017-10-13 05:15:07 -07002113class TestIPDeag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002114 """IPv4 Deaggregate Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002115
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002116 @classmethod
2117 def setUpClass(cls):
2118 super(TestIPDeag, cls).setUpClass()
2119
2120 @classmethod
2121 def tearDownClass(cls):
2122 super(TestIPDeag, cls).tearDownClass()
2123
Neale Ranns054c03a2017-10-13 05:15:07 -07002124 def setUp(self):
2125 super(TestIPDeag, self).setUp()
2126
2127 self.create_pg_interfaces(range(3))
2128
2129 for i in self.pg_interfaces:
2130 i.admin_up()
2131 i.config_ip4()
2132 i.resolve_arp()
2133
2134 def tearDown(self):
2135 super(TestIPDeag, self).tearDown()
2136 for i in self.pg_interfaces:
2137 i.unconfig_ip4()
2138 i.admin_down()
2139
Neale Ranns054c03a2017-10-13 05:15:07 -07002140 def test_ip_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002141 """IP Deag Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002142
2143 #
2144 # Create a table to be used for:
2145 # 1 - another destination address lookup
2146 # 2 - a source address lookup
2147 #
2148 table_dst = VppIpTable(self, 1)
2149 table_src = VppIpTable(self, 2)
2150 table_dst.add_vpp_config()
2151 table_src.add_vpp_config()
2152
2153 #
2154 # Add a route in the default table to point to a deag/
2155 # second lookup in each of these tables
2156 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002157 route_to_dst = VppIpRoute(
2158 self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
2159 )
Neale Ranns097fa662018-05-01 05:17:55 -07002160 route_to_src = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002161 self,
2162 "1.1.1.2",
2163 32,
2164 [
2165 VppRoutePath(
2166 "0.0.0.0",
2167 0xFFFFFFFF,
2168 nh_table_id=2,
2169 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP,
2170 )
2171 ],
2172 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002173 route_to_dst.add_vpp_config()
2174 route_to_src.add_vpp_config()
2175
2176 #
2177 # packets to these destination are dropped, since they'll
2178 # hit the respective default routes in the second table
2179 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002180 p_dst = (
2181 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2182 / IP(src="5.5.5.5", dst="1.1.1.1")
2183 / TCP(sport=1234, dport=1234)
2184 / Raw(b"\xa5" * 100)
2185 )
2186 p_src = (
2187 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2188 / IP(src="2.2.2.2", dst="1.1.1.2")
2189 / TCP(sport=1234, dport=1234)
2190 / Raw(b"\xa5" * 100)
2191 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002192 pkts_dst = p_dst * 257
2193 pkts_src = p_src * 257
2194
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002195 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in dst table")
2196 self.send_and_assert_no_replies(self.pg0, pkts_src, "IP in src table")
Neale Ranns054c03a2017-10-13 05:15:07 -07002197
2198 #
2199 # add a route in the dst table to forward via pg1
2200 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002201 route_in_dst = VppIpRoute(
2202 self,
2203 "1.1.1.1",
2204 32,
2205 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2206 table_id=1,
2207 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002208 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07002209
Neale Ranns054c03a2017-10-13 05:15:07 -07002210 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
2211
2212 #
2213 # add a route in the src table to forward via pg2
2214 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002215 route_in_src = VppIpRoute(
2216 self,
2217 "2.2.2.2",
2218 32,
2219 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2220 table_id=2,
2221 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002222 route_in_src.add_vpp_config()
2223 self.send_and_expect(self.pg0, pkts_src, self.pg2)
2224
Neale Rannsce9e0b42018-08-01 12:53:17 -07002225 #
2226 # loop in the lookup DP
2227 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002228 route_loop = VppIpRoute(
2229 self, "2.2.2.3", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
2230 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002231 route_loop.add_vpp_config()
2232
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002233 p_l = (
2234 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2235 / IP(src="2.2.2.4", dst="2.2.2.3")
2236 / TCP(sport=1234, dport=1234)
2237 / Raw(b"\xa5" * 100)
2238 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002239
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002240 self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop")
Neale Rannsce9e0b42018-08-01 12:53:17 -07002241
Neale Ranns054c03a2017-10-13 05:15:07 -07002242
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002243class TestIPInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002244 """IPv4 Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002245
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002246 @classmethod
2247 def setUpClass(cls):
2248 super(TestIPInput, cls).setUpClass()
2249
2250 @classmethod
2251 def tearDownClass(cls):
2252 super(TestIPInput, cls).tearDownClass()
2253
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002254 def setUp(self):
2255 super(TestIPInput, self).setUp()
2256
2257 self.create_pg_interfaces(range(2))
2258
2259 for i in self.pg_interfaces:
2260 i.admin_up()
2261 i.config_ip4()
2262 i.resolve_arp()
2263
2264 def tearDown(self):
2265 super(TestIPInput, self).tearDown()
2266 for i in self.pg_interfaces:
2267 i.unconfig_ip4()
2268 i.admin_down()
2269
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002270 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002271 """IP Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002272
2273 # i can't find a way in scapy to construct an IP packet
2274 # with a length less than the IP header length
2275
2276 #
2277 # Packet too short - this is forwarded
2278 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002279 p_short = (
2280 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2281 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=40)
2282 / UDP(sport=1234, dport=1234)
2283 / Raw(b"\xa5" * 100)
2284 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002285
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002286 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002287
2288 #
2289 # Packet too long - this is dropped
2290 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002291 p_long = (
2292 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2293 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=400)
2294 / UDP(sport=1234, dport=1234)
2295 / Raw(b"\xa5" * 100)
2296 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002297
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002298 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002299
2300 #
2301 # bad chksum - this is dropped
2302 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002303 p_chksum = (
2304 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2305 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, chksum=400)
2306 / UDP(sport=1234, dport=1234)
2307 / Raw(b"\xa5" * 100)
2308 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002309
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002310 rx = self.send_and_assert_no_replies(
2311 self.pg0, p_chksum * NUM_PKTS, "bad checksum"
2312 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002313
2314 #
2315 # bad version - this is dropped
2316 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002317 p_ver = (
2318 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2319 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, version=3)
2320 / UDP(sport=1234, dport=1234)
2321 / Raw(b"\xa5" * 100)
2322 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002323
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002324 rx = self.send_and_assert_no_replies(
2325 self.pg0, p_ver * NUM_PKTS, "funky version"
2326 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002327
2328 #
2329 # fragment offset 1 - this is dropped
2330 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002331 p_frag = (
2332 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2333 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, frag=1)
2334 / UDP(sport=1234, dport=1234)
2335 / Raw(b"\xa5" * 100)
2336 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002337
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002338 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002339
2340 #
2341 # TTL expired packet
2342 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002343 p_ttl = (
2344 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2345 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=1)
2346 / UDP(sport=1234, dport=1234)
2347 / Raw(b"\xa5" * 100)
2348 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002349
Neale Ranns5c6dd172022-02-17 09:08:47 +00002350 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002351
Neale Ranns5c6dd172022-02-17 09:08:47 +00002352 for rx in rxs:
2353 icmp = rx[ICMP]
2354 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002355 self.assertEqual(icmpcodes[icmp.type][icmp.code], "ttl-zero-during-transit")
Neale Ranns5c6dd172022-02-17 09:08:47 +00002356 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2357 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002358
Neale Rannsffd78d12018-02-09 06:05:16 -08002359 #
2360 # MTU exceeded
2361 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002362 p_mtu = (
2363 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2364 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=10, flags="DF")
2365 / UDP(sport=1234, dport=1234)
2366 / Raw(b"\xa5" * 2000)
2367 )
Neale Rannsffd78d12018-02-09 06:05:16 -08002368
Ole Troand7231612018-06-07 10:17:57 +02002369 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002370
Neale Ranns5c6dd172022-02-17 09:08:47 +00002371 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002372
Neale Ranns5c6dd172022-02-17 09:08:47 +00002373 for rx in rxs:
2374 icmp = rx[ICMP]
2375 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002376 self.assertEqual(icmpcodes[icmp.type][icmp.code], "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002377 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002378 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2379 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002380
Ole Troand7231612018-06-07 10:17:57 +02002381 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002382 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002383
Ole Troand7231612018-06-07 10:17:57 +02002384 # Reset MTU for subsequent tests
2385 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002386
Neale Rannsbe2286b2018-12-09 12:54:51 -08002387 #
2388 # source address 0.0.0.0 and 25.255.255.255 and for-us
2389 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002390 p_s0 = (
2391 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2392 / IP(src="0.0.0.0", dst=self.pg0.local_ip4)
2393 / ICMP(id=4, seq=4)
2394 / Raw(load=b"\x0a" * 18)
2395 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002396 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2397
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002398 p_s0 = (
2399 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2400 / IP(src="255.255.255.255", dst=self.pg0.local_ip4)
2401 / ICMP(id=4, seq=4)
2402 / Raw(load=b"\x0a" * 18)
2403 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002404 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2405
Neale Ranns1855b8e2018-07-11 10:31:26 -07002406
2407class TestIPDirectedBroadcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002408 """IPv4 Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002409
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002410 @classmethod
2411 def setUpClass(cls):
2412 super(TestIPDirectedBroadcast, cls).setUpClass()
2413
2414 @classmethod
2415 def tearDownClass(cls):
2416 super(TestIPDirectedBroadcast, cls).tearDownClass()
2417
Neale Ranns1855b8e2018-07-11 10:31:26 -07002418 def setUp(self):
2419 super(TestIPDirectedBroadcast, self).setUp()
2420
2421 self.create_pg_interfaces(range(2))
2422
2423 for i in self.pg_interfaces:
2424 i.admin_up()
2425
2426 def tearDown(self):
2427 super(TestIPDirectedBroadcast, self).tearDown()
2428 for i in self.pg_interfaces:
2429 i.admin_down()
2430
2431 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002432 """IP Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002433
2434 #
2435 # set the directed broadcast on pg0 first, then config IP4 addresses
2436 # for pg1 directed broadcast is always disabled
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002437 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002438
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002439 p0 = (
2440 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2441 / IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast)
2442 / UDP(sport=1234, dport=1234)
2443 / Raw(b"\xa5" * 2000)
2444 )
2445 p1 = (
2446 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2447 / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast)
2448 / UDP(sport=1234, dport=1234)
2449 / Raw(b"\xa5" * 2000)
2450 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002451
2452 self.pg0.config_ip4()
2453 self.pg0.resolve_arp()
2454 self.pg1.config_ip4()
2455 self.pg1.resolve_arp()
2456
2457 #
2458 # test packet is L2 broadcast
2459 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002460 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002461 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002463 self.send_and_assert_no_replies(
2464 self.pg0, p1 * NUM_PKTS, "directed broadcast disabled"
2465 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002466
2467 #
2468 # toggle directed broadcast on pg0
2469 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002470 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 0)
2471 self.send_and_assert_no_replies(
2472 self.pg1, p0 * NUM_PKTS, "directed broadcast disabled"
2473 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002474
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002475 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002476 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002477
2478 self.pg0.unconfig_ip4()
2479 self.pg1.unconfig_ip4()
2480
2481
mu.duojiao59a82952018-10-11 14:27:30 +08002482class TestIPLPM(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002483 """IPv4 longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002484
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002485 @classmethod
2486 def setUpClass(cls):
2487 super(TestIPLPM, cls).setUpClass()
2488
2489 @classmethod
2490 def tearDownClass(cls):
2491 super(TestIPLPM, cls).tearDownClass()
2492
mu.duojiao59a82952018-10-11 14:27:30 +08002493 def setUp(self):
2494 super(TestIPLPM, self).setUp()
2495
2496 self.create_pg_interfaces(range(4))
2497
2498 for i in self.pg_interfaces:
2499 i.admin_up()
2500 i.config_ip4()
2501 i.resolve_arp()
2502
2503 def tearDown(self):
2504 super(TestIPLPM, self).tearDown()
2505 for i in self.pg_interfaces:
2506 i.admin_down()
2507 i.unconfig_ip4()
2508
2509 def test_ip_lpm(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002510 """IP longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002511
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002512 s_24 = VppIpRoute(
2513 self,
2514 "10.1.2.0",
2515 24,
2516 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2517 )
mu.duojiao59a82952018-10-11 14:27:30 +08002518 s_24.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002519 s_8 = VppIpRoute(
2520 self,
2521 "10.0.0.0",
2522 8,
2523 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2524 )
mu.duojiao59a82952018-10-11 14:27:30 +08002525 s_8.add_vpp_config()
2526
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002527 p_8 = (
2528 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2529 / IP(src="1.1.1.1", dst="10.1.1.1")
2530 / UDP(sport=1234, dport=1234)
2531 / Raw(b"\xa5" * 2000)
2532 )
2533 p_24 = (
2534 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2535 / IP(src="1.1.1.1", dst="10.1.2.1")
2536 / UDP(sport=1234, dport=1234)
2537 / Raw(b"\xa5" * 2000)
2538 )
mu.duojiao59a82952018-10-11 14:27:30 +08002539
2540 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002541 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2542 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002543
2544
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002545@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002546class TestIPv4Frag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002547 """IPv4 fragmentation"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002548
2549 @classmethod
2550 def setUpClass(cls):
2551 super(TestIPv4Frag, cls).setUpClass()
2552
2553 cls.create_pg_interfaces([0, 1])
2554 cls.src_if = cls.pg0
2555 cls.dst_if = cls.pg1
2556
2557 # setup all interfaces
2558 for i in cls.pg_interfaces:
2559 i.admin_up()
2560 i.config_ip4()
2561 i.resolve_arp()
2562
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002563 @classmethod
2564 def tearDownClass(cls):
2565 super(TestIPv4Frag, cls).tearDownClass()
2566
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002567 def test_frag_large_packets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002568 """Fragmentation of large packets"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002569
Neale Ranns0b6a8572019-10-30 17:34:14 +00002570 self.vapi.cli("adjacency counters enable")
2571
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002572 p = (
2573 Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac)
2574 / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4)
2575 / UDP(sport=1234, dport=5678)
2576 / Raw()
2577 )
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002578 self.extend_packet(p, 6000, "abcde")
2579 saved_payload = p[Raw].load
2580
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002581 nbr = VppNeighbor(
2582 self,
2583 self.dst_if.sw_if_index,
2584 self.dst_if.remote_mac,
2585 self.dst_if.remote_ip4,
2586 ).add_vpp_config()
Neale Ranns0b6a8572019-10-30 17:34:14 +00002587
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002588 # Force fragmentation by setting MTU of output interface
2589 # lower than packet size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002590 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, [5000, 0, 0, 0])
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002591
2592 self.pg_enable_capture()
2593 self.src_if.add_stream(p)
2594 self.pg_start()
2595
2596 # Expecting 3 fragments because size of created fragments currently
2597 # cannot be larger then VPP buffer size (which is 2048)
2598 packets = self.dst_if.get_capture(3)
2599
Neale Ranns0b6a8572019-10-30 17:34:14 +00002600 # we should show 3 packets thru the neighbor
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002601 self.assertEqual(3, nbr.get_stats()["packets"])
Neale Ranns0b6a8572019-10-30 17:34:14 +00002602
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002603 # Assume VPP sends the fragments in order
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002604 payload = b""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002605 for p in packets:
2606 payload_offset = p.frag * 8
2607 if payload_offset > 0:
2608 payload_offset -= 8 # UDP header is not in payload
2609 self.assert_equal(payload_offset, len(payload))
2610 payload += p[Raw].load
2611 self.assert_equal(payload, saved_payload, "payload")
2612
2613
Neale Ranns9db6ada2019-11-08 12:42:31 +00002614class TestIPReplace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002615 """IPv4 Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002616
2617 @classmethod
2618 def setUpClass(cls):
2619 super(TestIPReplace, cls).setUpClass()
2620
2621 @classmethod
2622 def tearDownClass(cls):
2623 super(TestIPReplace, cls).tearDownClass()
2624
2625 def setUp(self):
2626 super(TestIPReplace, self).setUp()
2627
2628 self.create_pg_interfaces(range(4))
2629
2630 table_id = 1
2631 self.tables = []
2632
2633 for i in self.pg_interfaces:
2634 i.admin_up()
2635 i.config_ip4()
2636 i.resolve_arp()
2637 i.generate_remote_hosts(2)
2638 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2639 table_id += 1
2640
2641 def tearDown(self):
2642 super(TestIPReplace, self).tearDown()
2643 for i in self.pg_interfaces:
2644 i.admin_down()
2645 i.unconfig_ip4()
2646
2647 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002648 """IP Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002649
Neale Ranns990f6942020-10-20 07:20:17 +00002650 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2651 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002652 N_ROUTES = 20
2653 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2654 routes = [[], [], [], []]
2655
2656 # load up the tables with some routes
2657 for ii, t in enumerate(self.tables):
2658 for jj in range(N_ROUTES):
2659 uni = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002660 self,
2661 "10.0.0.%d" % jj,
2662 32,
2663 [
2664 VppRoutePath(
2665 links[ii].remote_hosts[0].ip4, links[ii].sw_if_index
2666 ),
2667 VppRoutePath(
2668 links[ii].remote_hosts[1].ip4, links[ii].sw_if_index
2669 ),
2670 ],
2671 table_id=t.table_id,
2672 ).add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002673 multi = VppIpMRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002674 self,
2675 "0.0.0.0",
2676 "239.0.0.%d" % jj,
2677 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002678 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002679 [
2680 VppMRoutePath(
2681 self.pg0.sw_if_index,
2682 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
2683 ),
2684 VppMRoutePath(
2685 self.pg1.sw_if_index,
2686 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2687 ),
2688 VppMRoutePath(
2689 self.pg2.sw_if_index,
2690 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2691 ),
2692 VppMRoutePath(
2693 self.pg3.sw_if_index,
2694 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2695 ),
2696 ],
2697 table_id=t.table_id,
2698 ).add_vpp_config()
2699 routes[ii].append({"uni": uni, "multi": multi})
Neale Ranns9db6ada2019-11-08 12:42:31 +00002700
2701 #
2702 # replace the tables a few times
2703 #
2704 for kk in range(3):
2705 # replace_begin each table
2706 for t in self.tables:
2707 t.replace_begin()
2708
2709 # all the routes are still there
2710 for ii, t in enumerate(self.tables):
2711 dump = t.dump()
2712 mdump = t.mdump()
2713 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002714 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2715 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002716
2717 # redownload the even numbered routes
2718 for ii, t in enumerate(self.tables):
2719 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002720 routes[ii][jj]["uni"].add_vpp_config()
2721 routes[ii][jj]["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002722
2723 # signal each table replace_end
2724 for t in self.tables:
2725 t.replace_end()
2726
2727 # we should find the even routes, but not the odd
2728 for ii, t in enumerate(self.tables):
2729 dump = t.dump()
2730 mdump = t.mdump()
2731 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002732 self.assertTrue(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2733 self.assertTrue(
2734 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2735 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002736 for jj in range(1, N_ROUTES - 1, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002737 self.assertFalse(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2738 self.assertFalse(
2739 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2740 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002741
2742 # reload all the routes
2743 for ii, t in enumerate(self.tables):
2744 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002745 r["uni"].add_vpp_config()
2746 r["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002747
2748 # all the routes are still there
2749 for ii, t in enumerate(self.tables):
2750 dump = t.dump()
2751 mdump = t.mdump()
2752 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002753 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2754 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002755
2756 #
2757 # finally flush the tables for good measure
2758 #
2759 for t in self.tables:
2760 t.flush()
2761 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002762 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002763
2764
Neale Ranns9efcee62019-11-26 19:30:08 +00002765class TestIPCover(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002766 """IPv4 Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002767
2768 @classmethod
2769 def setUpClass(cls):
2770 super(TestIPCover, cls).setUpClass()
2771
2772 @classmethod
2773 def tearDownClass(cls):
2774 super(TestIPCover, cls).tearDownClass()
2775
2776 def setUp(self):
2777 super(TestIPCover, self).setUp()
2778
2779 self.create_pg_interfaces(range(4))
2780
2781 table_id = 1
2782 self.tables = []
2783
2784 for i in self.pg_interfaces:
2785 i.admin_up()
2786 i.config_ip4()
2787 i.resolve_arp()
2788 i.generate_remote_hosts(2)
2789 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2790 table_id += 1
2791
2792 def tearDown(self):
2793 super(TestIPCover, self).tearDown()
2794 for i in self.pg_interfaces:
2795 i.admin_down()
2796 i.unconfig_ip4()
2797
2798 def test_cover(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002799 """IP Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002800
2801 # add a loop back with a /32 prefix
2802 lo = VppLoInterface(self)
2803 lo.admin_up()
2804 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2805
2806 # add a neighbour that matches the loopback's /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002807 nbr = VppNeighbor(
2808 self, lo.sw_if_index, lo.remote_mac, "127.0.0.1"
2809 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002810
2811 # add the default route which will be the cover for /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002812 r = VppIpRoute(
2813 self,
2814 "0.0.0.0",
2815 0,
2816 [VppRoutePath("127.0.0.1", lo.sw_if_index)],
2817 register=False,
2818 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002819
2820 # add/remove/add a longer mask cover
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002821 r8 = VppIpRoute(
2822 self, "127.0.0.0", 8, [VppRoutePath("127.0.0.1", lo.sw_if_index)]
2823 ).add_vpp_config()
Neale Ranns87866032020-11-25 09:14:22 +00002824 r8.remove_vpp_config()
2825 r8.add_vpp_config()
2826 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002827
2828 # remove the default route
2829 r.remove_vpp_config()
2830
Neale Ranns87866032020-11-25 09:14:22 +00002831 # remove the interface prefix
2832 a.remove_vpp_config()
2833
Neale Ranns59f71132020-04-08 12:19:38 +00002834
2835class TestIP4Replace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002836 """IPv4 Interface Address Replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002837
2838 @classmethod
2839 def setUpClass(cls):
2840 super(TestIP4Replace, cls).setUpClass()
2841
2842 @classmethod
2843 def tearDownClass(cls):
2844 super(TestIP4Replace, cls).tearDownClass()
2845
2846 def setUp(self):
2847 super(TestIP4Replace, self).setUp()
2848
2849 self.create_pg_interfaces(range(4))
2850
2851 for i in self.pg_interfaces:
2852 i.admin_up()
2853
2854 def tearDown(self):
2855 super(TestIP4Replace, self).tearDown()
2856 for i in self.pg_interfaces:
2857 i.admin_down()
2858
2859 def get_n_pfxs(self, intf):
2860 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2861
2862 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002863 """IP interface address replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002864
2865 intf_pfxs = [[], [], [], []]
2866
2867 # add prefixes to each of the interfaces
2868 for i in range(len(self.pg_interfaces)):
2869 intf = self.pg_interfaces[i]
2870
2871 # 172.16.x.1/24
2872 addr = "172.16.%d.1" % intf.sw_if_index
2873 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2874 intf_pfxs[i].append(a)
2875
2876 # 172.16.x.2/24 - a different address in the same subnet as above
2877 addr = "172.16.%d.2" % intf.sw_if_index
2878 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2879 intf_pfxs[i].append(a)
2880
2881 # 172.15.x.2/24 - a different address and subnet
2882 addr = "172.15.%d.2" % intf.sw_if_index
2883 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2884 intf_pfxs[i].append(a)
2885
2886 # a dump should n_address in it
2887 for intf in self.pg_interfaces:
2888 self.assertEqual(self.get_n_pfxs(intf), 3)
2889
2890 #
2891 # remove all the address thru a replace
2892 #
2893 self.vapi.sw_interface_address_replace_begin()
2894 self.vapi.sw_interface_address_replace_end()
2895 for intf in self.pg_interfaces:
2896 self.assertEqual(self.get_n_pfxs(intf), 0)
2897
2898 #
2899 # add all the interface addresses back
2900 #
2901 for p in intf_pfxs:
2902 for v in p:
2903 v.add_vpp_config()
2904 for intf in self.pg_interfaces:
2905 self.assertEqual(self.get_n_pfxs(intf), 3)
2906
2907 #
2908 # replace again, but this time update/re-add the address on the first
2909 # two interfaces
2910 #
2911 self.vapi.sw_interface_address_replace_begin()
2912
2913 for p in intf_pfxs[:2]:
2914 for v in p:
2915 v.add_vpp_config()
2916
2917 self.vapi.sw_interface_address_replace_end()
2918
2919 # on the first two the address still exist,
2920 # on the other two they do not
2921 for intf in self.pg_interfaces[:2]:
2922 self.assertEqual(self.get_n_pfxs(intf), 3)
2923 for p in intf_pfxs[:2]:
2924 for v in p:
2925 self.assertTrue(v.query_vpp_config())
2926 for intf in self.pg_interfaces[2:]:
2927 self.assertEqual(self.get_n_pfxs(intf), 0)
2928
2929 #
2930 # add all the interface addresses back on the last two
2931 #
2932 for p in intf_pfxs[2:]:
2933 for v in p:
2934 v.add_vpp_config()
2935 for intf in self.pg_interfaces:
2936 self.assertEqual(self.get_n_pfxs(intf), 3)
2937
2938 #
2939 # replace again, this time add different prefixes on all the interfaces
2940 #
2941 self.vapi.sw_interface_address_replace_begin()
2942
2943 pfxs = []
2944 for intf in self.pg_interfaces:
2945 # 172.18.x.1/24
2946 addr = "172.18.%d.1" % intf.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002947 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002948
2949 self.vapi.sw_interface_address_replace_end()
2950
2951 # only .18 should exist on each interface
2952 for intf in self.pg_interfaces:
2953 self.assertEqual(self.get_n_pfxs(intf), 1)
2954 for pfx in pfxs:
2955 self.assertTrue(pfx.query_vpp_config())
2956
2957 #
2958 # remove everything
2959 #
2960 self.vapi.sw_interface_address_replace_begin()
2961 self.vapi.sw_interface_address_replace_end()
2962 for intf in self.pg_interfaces:
2963 self.assertEqual(self.get_n_pfxs(intf), 0)
2964
2965 #
2966 # add prefixes to each interface. post-begin add the prefix from
2967 # interface X onto interface Y. this would normally be an error
2968 # since it would generate a 'duplicate address' warning. but in
2969 # this case, since what is newly downloaded is sane, it's ok
2970 #
2971 for intf in self.pg_interfaces:
2972 # 172.18.x.1/24
2973 addr = "172.18.%d.1" % intf.sw_if_index
2974 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2975
2976 self.vapi.sw_interface_address_replace_begin()
2977
2978 pfxs = []
2979 for intf in self.pg_interfaces:
2980 # 172.18.x.1/24
2981 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002982 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00002983
2984 self.vapi.sw_interface_address_replace_end()
2985
2986 self.logger.info(self.vapi.cli("sh int addr"))
2987
2988 for intf in self.pg_interfaces:
2989 self.assertEqual(self.get_n_pfxs(intf), 1)
2990 for pfx in pfxs:
2991 self.assertTrue(pfx.query_vpp_config())
2992
2993
Neale Ranns8f5fef22020-12-21 08:29:34 +00002994class TestIPv4PathMTU(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002995 """IPv4 Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00002996
2997 @classmethod
2998 def setUpClass(cls):
2999 super(TestIPv4PathMTU, cls).setUpClass()
3000
3001 cls.create_pg_interfaces(range(2))
3002
3003 # setup all interfaces
3004 for i in cls.pg_interfaces:
3005 i.admin_up()
3006 i.config_ip4()
3007 i.resolve_arp()
3008
3009 @classmethod
3010 def tearDownClass(cls):
3011 super(TestIPv4PathMTU, cls).tearDownClass()
3012
3013 def test_path_mtu(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003014 """Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00003015
3016 #
3017 # The goal here is not to test that fragmentation works correctly,
3018 # that's done elsewhere, the intent is to ensure that the Path MTU
3019 # settings are honoured.
3020 #
3021 self.vapi.cli("adjacency counters enable")
3022
3023 # set the interface MTU to a reasonable value
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003024 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003025
3026 self.pg1.generate_remote_hosts(4)
3027
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003028 p_2k = (
3029 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3030 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3031 / UDP(sport=1234, dport=5678)
3032 / Raw(b"0xa" * 640)
3033 )
3034 p_1k = (
3035 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3036 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3037 / UDP(sport=1234, dport=5678)
3038 / Raw(b"0xa" * 320)
3039 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003040
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003041 nbr = VppNeighbor(
3042 self, self.pg1.sw_if_index, self.pg1.remote_mac, self.pg1.remote_ip4
3043 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003044
3045 # this is now the interface MTU frags
3046 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3047 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3048
3049 # drop the path MTU for this neighbour to below the interface MTU
3050 # expect more frags
3051 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
3052
3053 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3054 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3055
3056 # print/format the adj delegate
3057 self.logger.info(self.vapi.cli("sh adj 5"))
3058
3059 # increase the path MTU to more than the interface
3060 # expect to use the interface MTU
3061 pmtu.modify(8192)
3062
3063 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3064 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3065
3066 # go back to an MTU from the path
3067 # wrap the call around mark-n-sweep to enusre updates clear stale
3068 self.vapi.ip_path_mtu_replace_begin()
3069 pmtu.modify(900)
3070 self.vapi.ip_path_mtu_replace_end()
3071
3072 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3073 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3074
3075 # raise the interface's MTU
3076 # should still use that of the path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003077 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003078 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3079 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3080
3081 # set path high and interface low
3082 pmtu.modify(2000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003083 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [900, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003084 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3085 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3086
3087 # remove the path MTU using the mark-n-sweep semantics
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003088 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003089 self.vapi.ip_path_mtu_replace_begin()
3090 self.vapi.ip_path_mtu_replace_end()
3091
3092 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3093 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3094
3095 #
3096 # set path MTU for a neighbour that doesn't exist, yet
3097 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003098 pmtu2 = VppIpPathMtu(self, self.pg1.remote_hosts[2].ip4, 900).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003099
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003100 p_2k = (
3101 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3102 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3103 / UDP(sport=1234, dport=5678)
3104 / Raw(b"0xa" * 640)
3105 )
3106 p_1k = (
3107 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3108 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3109 / UDP(sport=1234, dport=5678)
3110 / Raw(b"0xa" * 320)
3111 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003112
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003113 nbr2 = VppNeighbor(
3114 self,
3115 self.pg1.sw_if_index,
3116 self.pg1.remote_hosts[2].mac,
3117 self.pg1.remote_hosts[2].ip4,
3118 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003119
3120 # should frag to the path MTU
3121 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3122 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3123
3124 # remove and re-add the neighbour
3125 nbr2.remove_vpp_config()
3126 nbr2.add_vpp_config()
3127
3128 # should frag to the path MTU
3129 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3130 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3131
3132 #
3133 # set PMTUs for many peers
3134 #
3135 N_HOSTS = 16
3136 self.pg1.generate_remote_hosts(16)
3137 self.pg1.configure_ipv4_neighbors()
3138
3139 for h in range(N_HOSTS):
3140 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
3141 pmtu.add_vpp_config()
3142 self.assertTrue(pmtu.query_vpp_config())
3143
3144 self.logger.info(self.vapi.cli("sh ip pmtu"))
3145 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
3146 self.assertEqual(N_HOSTS, len(dump))
3147
3148 for h in range(N_HOSTS):
3149 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
3150 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
3151
3152 # should frag to the path MTU
3153 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3154 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3155
3156
Neale Ranns50bd1d32021-10-08 07:16:12 +00003157class TestIPv4ItfRebind(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003158 """IPv4 Interface Bind w/ attached routes"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003159
3160 def setUp(self):
3161 super(TestIPv4ItfRebind, self).setUp()
3162
3163 self.create_pg_interfaces(range(3))
3164
3165 def tearDown(self):
3166 super(TestIPv4ItfRebind, self).tearDown()
3167
3168 def test_rebind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003169 """Import to no import"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003170
3171 TABLE_ID = 1
3172 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
3173 self.pg1.set_table_ip4(TABLE_ID)
3174
3175 for i in self.pg_interfaces:
3176 i.admin_up()
3177 i.config_ip4()
3178 i.resolve_arp()
3179
3180 # add an attached route via an pg0
3181 # in a different table. this prefix should import
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003182 rt = VppIpRoute(
3183 self,
3184 self.pg0.local_ip4,
3185 24,
3186 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
3187 table_id=TABLE_ID,
3188 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003189
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003190 p = (
3191 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3192 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3193 / UDP(sport=1234, dport=5678)
3194 / Raw(b"0xa" * 640)
3195 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003196
3197 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3198 self.assertFalse(rx[0].haslayer(ARP))
3199
3200 # then bind pg0 to a new table
3201 # so the prefix no longer imports
3202 self.pg0.unconfig_ip4()
3203 self.pg0.set_table_ip4(TABLE_ID)
3204 self.pg0.config_ip4()
3205 self.pg0.resolve_arp()
3206
3207 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3208 self.assertFalse(rx[0].haslayer(ARP))
3209
3210 # revert back to imported
3211 self.pg0.unconfig_ip4()
3212 self.pg0.set_table_ip4(0)
3213 self.pg0.config_ip4()
3214 self.pg0.resolve_arp()
3215
3216 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3217 self.assertFalse(rx[0].haslayer(ARP))
3218
3219 # cleanup
3220 for i in self.pg_interfaces:
3221 i.unconfig_ip4()
3222 i.set_table_ip4(0)
3223 i.admin_down()
3224
3225 rt.remove_vpp_config()
3226 tbl.remove_vpp_config()
3227
3228 def test_delete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003229 """Swap import tables"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003230
3231 TABLE_ID1 = 1
3232 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
3233 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
3234 TABLE_ID2 = 2
3235 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
3236 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
3237
3238 # table mappings
3239 self.pg1.set_table_ip4(TABLE_ID1)
3240 self.pg1.set_table_ip6(TABLE_ID1)
3241 self.pg2.set_table_ip4(TABLE_ID2)
3242 self.pg2.set_table_ip6(TABLE_ID2)
3243
3244 for i in self.pg_interfaces:
3245 i.admin_up()
3246 i.config_ip4()
3247 i.resolve_arp()
3248
3249 # add an attached route in the default table via pg0
3250 # this should import to table 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003251 rt4 = VppIpRoute(
3252 self,
3253 self.pg1.local_ip4,
3254 24,
3255 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3256 ).add_vpp_config()
3257 rt6 = VppIpRoute(
3258 self,
3259 self.pg1.local_ip6,
3260 64,
3261 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3262 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003263
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003264 p1 = (
3265 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3266 / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
3267 / UDP(sport=1234, dport=5678)
3268 / Raw(b"0xa" * 640)
3269 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003270
3271 # inject into table 0
3272 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3273 self.assertFalse(rx[0].haslayer(ARP))
3274
3275 # swap the attached interface to table 2
3276 self.pg1.unconfig_ip4()
3277 self.pg1.unconfig_ip6()
3278 self.pg1.set_table_ip4(TABLE_ID2)
3279 self.pg1.set_table_ip6(TABLE_ID2)
3280 self.pg1.config_ip4()
3281 self.pg1.config_ip6()
3282 self.pg1.resolve_arp()
3283
3284 # delete table 1
3285 tbl1_4.flush()
3286 tbl1_6.flush()
3287 tbl1_4.remove_vpp_config()
3288 tbl1_6.remove_vpp_config()
3289
3290 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3291 self.assertFalse(rx[0].haslayer(ARP))
3292
3293 for i in self.pg_interfaces:
3294 i.unconfig_ip4()
3295 i.unconfig_ip6()
3296 i.set_table_ip4(0)
3297 i.set_table_ip6(0)
3298 i.admin_down()
3299
3300
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003301if __name__ == "__main__":
Klement Sekeraf62ae122016-10-11 11:47:09 +02003302 unittest.main(testRunner=VppTestRunner)