blob: 5dd82f4aeeb3cd02d0d28021c9e2a9cb1f59989f [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Matej Klotton16a14cd2016-12-07 15:09:13 +01002import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02003import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01004import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02005
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08006from scapy.contrib.mpls import MPLS
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09007from scapy.contrib.gtp import GTP_U_Header
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08008from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
Neale Rannsaa7cfd02022-03-24 12:28:42 +00009from scapy.layers.inet6 import IPv6
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080010from scapy.layers.l2 import Ether, Dot1Q, ARP
11from scapy.packet import Raw
12from six import moves
13
Dave Wallace8800f732023-08-31 00:47:44 -040014from framework import VppTestCase
15from asfframework import VppTestRunner, tag_fixme_vpp_workers
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080016from util import ppp
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020017from vpp_ip_route import (
18 VppIpRoute,
19 VppRoutePath,
20 VppIpMRoute,
21 VppMRoutePath,
22 VppMplsIpBind,
23 VppMplsTable,
24 VppIpTable,
25 FibPathType,
26 find_route,
27 VppIpInterfaceAddress,
28 find_route_in_dump,
29 find_mroute_in_dump,
30)
Neale Ranns8f5fef22020-12-21 08:29:34 +000031from vpp_ip import VppIpPuntPolicer, VppIpPuntRedirect, VppIpPathMtu
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080032from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Klement Sekerafd1f56a2021-11-22 21:25:57 +010033from vpp_papi import vpp_papi, VppEnum
Neale Ranns0b6a8572019-10-30 17:34:14 +000034from vpp_neighbor import VppNeighbor
Neale Ranns9efcee62019-11-26 19:30:08 +000035from vpp_lo_interface import VppLoInterface
Brian Russellc8f3cdf2021-01-19 16:57:42 +000036from vpp_policer import VppPolicer, PolicerAction
Damjan Marionf56b77a2016-10-03 19:44:57 +020037
Paul Vinciguerra4271c972019-05-14 13:25:49 -040038NUM_PKTS = 67
39
Damjan Marionf56b77a2016-10-03 19:44:57 +020040
Klement Sekeraf62ae122016-10-11 11:47:09 +020041class TestIPv4(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020042 """IPv4 Test Case"""
Damjan Marionf56b77a2016-10-03 19:44:57 +020043
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070044 @classmethod
45 def setUpClass(cls):
46 super(TestIPv4, cls).setUpClass()
47
48 @classmethod
49 def tearDownClass(cls):
50 super(TestIPv4, cls).tearDownClass()
51
Klement Sekeraf62ae122016-10-11 11:47:09 +020052 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010053 """
54 Perform test setup before test case.
55
56 **Config:**
57 - create 3 pg interfaces
58 - untagged pg0 interface
59 - Dot1Q subinterface on pg1
60 - Dot1AD subinterface on pg2
61 - setup interfaces:
62 - put it into UP state
63 - set IPv4 addresses
64 - resolve neighbor address using ARP
65 - configure 200 fib entries
66
67 :ivar list interfaces: pg interfaces and subinterfaces.
68 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010069 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020070 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020071
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 # create 3 pg interfaces
73 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020074
Klement Sekeraf62ae122016-10-11 11:47:09 +020075 # create 2 subinterfaces for pg1 and pg2
76 self.sub_interfaces = [
77 VppDot1QSubint(self, self.pg1, 100),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078 VppDot1ADSubint(self, self.pg2, 200, 300, 400),
79 ]
Damjan Marionf56b77a2016-10-03 19:44:57 +020080
Klement Sekeraf62ae122016-10-11 11:47:09 +020081 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
82 self.flows = dict()
83 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
84 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
85 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020086
Klement Sekeraf62ae122016-10-11 11:47:09 +020087 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020088 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020089
Klement Sekeraf62ae122016-10-11 11:47:09 +020090 self.interfaces = list(self.pg_interfaces)
91 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020092
Klement Sekeraf62ae122016-10-11 11:47:09 +020093 # setup all interfaces
94 for i in self.interfaces:
95 i.admin_up()
96 i.config_ip4()
97 i.resolve_arp()
98
Matej Klotton86d87c42016-11-11 11:38:55 +010099 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200100
101 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100102 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +0200103 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700104
105 def show_commands_at_teardown(self):
Neale Rannscbe25aa2019-09-30 10:53:31 +0000106 self.logger.info(self.vapi.cli("show ip4 neighbors"))
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700107 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +0200108
Jan Geletye6c78ee2018-06-26 12:24:03 +0200109 def modify_packet(self, src_if, packet_size, pkt):
110 """Add load, set destination IP and extend packet to required packet
111 size for defined interface.
112
113 :param VppInterface src_if: Interface to create packet for.
114 :param int packet_size: Required packet size.
115 :param Scapy pkt: Packet to be modified.
116 """
Ole Troan6ed154f2019-10-15 19:31:55 +0200117 dst_if_idx = int(packet_size / 10 % 2)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200118 dst_if = self.flows[src_if][dst_if_idx]
119 info = self.create_packet_info(src_if, dst_if)
120 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200121 p = pkt / Raw(payload)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200122 p[IP].dst = dst_if.remote_ip4
123 info.data = p.copy()
124 if isinstance(src_if, VppSubInterface):
125 p = src_if.add_dot1_layer(p)
126 self.extend_packet(p, packet_size)
127
128 return p
129
130 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100131 """Create input packet stream for defined interface.
132
133 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100134 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200135 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200136 pkt_tmpl = (
137 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
138 / IP(src=src_if.remote_ip4)
139 / UDP(sport=1234, dport=1234)
140 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200141
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200142 pkts = [
143 self.modify_packet(src_if, i, pkt_tmpl)
144 for i in moves.range(
145 self.pg_if_packet_sizes[0], self.pg_if_packet_sizes[1], 10
146 )
147 ]
148 pkts_b = [
149 self.modify_packet(src_if, i, pkt_tmpl)
150 for i in moves.range(
151 self.pg_if_packet_sizes[1] + hdr_ext,
152 self.pg_if_packet_sizes[2] + hdr_ext,
153 50,
154 )
155 ]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200156 pkts.extend(pkts_b)
157
Damjan Marionf56b77a2016-10-03 19:44:57 +0200158 return pkts
159
Klement Sekeraf62ae122016-10-11 11:47:09 +0200160 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100161 """Verify captured input packet stream for defined interface.
162
163 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200164 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100165 :param list capture: Captured packet stream.
166 """
167 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200168 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200169 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200170 last_info[i.sw_if_index] = None
171 is_sub_if = False
172 dst_sw_if_index = dst_if.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200173 if hasattr(dst_if, "parent"):
Klement Sekeraf62ae122016-10-11 11:47:09 +0200174 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200175 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200176 if is_sub_if:
177 # Check VLAN tags and Ethernet header
178 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200179 self.assertTrue(Dot1Q not in packet)
180 try:
181 ip = packet[IP]
182 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800183 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200184 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200185 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100186 self.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187 "Got packet on port %s: src=%u (id=%u)"
188 % (dst_if.name, payload_info.src, packet_index)
189 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200190 next_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200191 payload_info.src, dst_sw_if_index, last_info[payload_info.src]
192 )
Klement Sekeraf62ae122016-10-11 11:47:09 +0200193 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200194 self.assertTrue(next_info is not None)
195 self.assertEqual(packet_index, next_info.index)
196 saved_packet = next_info.data
197 # Check standard fields
198 self.assertEqual(ip.src, saved_packet[IP].src)
199 self.assertEqual(ip.dst, saved_packet[IP].dst)
200 self.assertEqual(udp.sport, saved_packet[UDP].sport)
201 self.assertEqual(udp.dport, saved_packet[UDP].dport)
202 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100203 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200204 raise
205 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200206 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200207 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index]
208 )
209 self.assertTrue(
210 remaining_packet is None,
211 "Interface %s: Packet expected from interface %s "
212 "didn't arrive" % (dst_if.name, i.name),
213 )
Damjan Marionf56b77a2016-10-03 19:44:57 +0200214
215 def test_fib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200216 """IPv4 FIB test
Matej Klotton86d87c42016-11-11 11:38:55 +0100217
218 Test scenario:
219
220 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200221 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100222 - Send and verify received packets on each interface.
223 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200224
Jan Geletye6c78ee2018-06-26 12:24:03 +0200225 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200226 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200227
Klement Sekeraf62ae122016-10-11 11:47:09 +0200228 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200229 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200230 i.parent.add_stream(pkts)
231
232 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200233 self.pg_start()
234
Klement Sekeraf62ae122016-10-11 11:47:09 +0200235 pkts = self.pg0.get_capture()
236 self.verify_capture(self.pg0, pkts)
237
238 for i in self.sub_interfaces:
239 pkts = i.parent.get_capture()
240 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200241
242
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400243class TestIPv4RouteLookup(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200244 """IPv4 Route Lookup Test Case"""
245
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400246 routes = []
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000247 tables = []
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400248
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000249 def route_lookup(self, prefix, exact, table_id=0):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200250 return self.vapi.api(
251 self.vapi.papi.ip_route_lookup,
252 {
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000253 "table_id": table_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 "exact": exact,
255 "prefix": prefix,
256 },
257 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400258
259 @classmethod
260 def setUpClass(cls):
261 super(TestIPv4RouteLookup, cls).setUpClass()
262
263 @classmethod
264 def tearDownClass(cls):
265 super(TestIPv4RouteLookup, cls).tearDownClass()
266
267 def setUp(self):
268 super(TestIPv4RouteLookup, self).setUp()
269
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 drop_nh = VppRoutePath(
271 "127.0.0.1", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP
272 )
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400273
274 # Add 3 routes
275 r = VppIpRoute(self, "1.1.0.0", 16, [drop_nh])
276 r.add_vpp_config()
277 self.routes.append(r)
278
279 r = VppIpRoute(self, "1.1.1.0", 24, [drop_nh])
280 r.add_vpp_config()
281 self.routes.append(r)
282
283 r = VppIpRoute(self, "1.1.1.1", 32, [drop_nh])
284 r.add_vpp_config()
285 self.routes.append(r)
286
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000287 custom_vrf = VppIpTable(self, 200)
288 custom_vrf.add_vpp_config()
289 self.tables.append(custom_vrf)
290
291 r = VppIpRoute(self, "2.2.0.0", 16, [drop_nh], 200)
292 r.add_vpp_config()
293 self.routes.append(r)
294
295 r = VppIpRoute(self, "2.2.2.0", 24, [drop_nh], 200)
296 r.add_vpp_config()
297 self.routes.append(r)
298
299 r = VppIpRoute(self, "2.2.2.2", 32, [drop_nh], 200)
300 r.add_vpp_config()
301 self.routes.append(r)
302
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400303 def tearDown(self):
304 # Remove the routes we added
305 for r in self.routes:
306 r.remove_vpp_config()
307
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000308 for vrf in self.tables:
309 vrf.remove_vpp_config()
310
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400311 super(TestIPv4RouteLookup, self).tearDown()
312
313 def test_exact_match(self):
314 # Verify we find the host route
315 prefix = "1.1.1.1/32"
316 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200317 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400318
319 # Verify we find a middle prefix route
320 prefix = "1.1.1.0/24"
321 result = self.route_lookup(prefix, True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322 assert prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400323
324 # Verify we do not find an available LPM.
325 with self.vapi.assert_negative_api_retval():
326 self.route_lookup("1.1.1.2/32", True)
327
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000328 # Verify we find the host route
329 prefix = "2.2.2.2/32"
330 result = self.route_lookup(prefix, True, 200)
331 assert prefix == str(result.route.prefix)
332
333 # Verify we find a middle prefix route
334 prefix = "2.2.2.0/24"
335 result = self.route_lookup(prefix, True, 200)
336 assert prefix == str(result.route.prefix)
337
338 # Verify we do not find an available LPM.
339 with self.vapi.assert_negative_api_retval():
340 self.route_lookup("2.2.2.1/32", True, 200)
341
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400342 def test_longest_prefix_match(self):
343 # verify we find lpm
344 lpm_prefix = "1.1.1.0/24"
345 result = self.route_lookup("1.1.1.2/32", False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400347
348 # Verify we find the exact when not requested
349 result = self.route_lookup(lpm_prefix, False)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200350 assert lpm_prefix == str(result.route.prefix)
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400351
Mohsin Kazmi5f694322024-04-19 09:10:46 +0000352 # verify we find lpm
353 lpm_prefix = "2.2.2.0/24"
354 result = self.route_lookup("2.2.2.1/32", False, 200)
355 assert lpm_prefix == str(result.route.prefix)
356
357 # Verify we find the exact when not requested
358 result = self.route_lookup(lpm_prefix, False, 200)
359 assert lpm_prefix == str(result.route.prefix)
360
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400361 # Can't seem to delete the default route so no negative LPM test.
362
363
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500364class TestIPv4IfAddrRoute(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200365 """IPv4 Interface Addr Route Test Case"""
Matthew G Smith88d29a92019-07-17 10:01:17 -0500366
367 @classmethod
368 def setUpClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500369 super(TestIPv4IfAddrRoute, cls).setUpClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500370
371 @classmethod
372 def tearDownClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500373 super(TestIPv4IfAddrRoute, cls).tearDownClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500374
375 def setUp(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500376 super(TestIPv4IfAddrRoute, self).setUp()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500377
378 # create 1 pg interface
379 self.create_pg_interfaces(range(1))
380
381 for i in self.pg_interfaces:
382 i.admin_up()
383 i.config_ip4()
384 i.resolve_arp()
385
386 def tearDown(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500387 super(TestIPv4IfAddrRoute, self).tearDown()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500388 for i in self.pg_interfaces:
389 i.unconfig_ip4()
390 i.admin_down()
391
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500392 def test_ipv4_ifaddrs_same_prefix(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200393 """IPv4 Interface Addresses Same Prefix test
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500394
395 Test scenario:
396
397 - Verify no route in FIB for prefix 10.10.10.0/24
398 - Configure IPv4 address 10.10.10.10/24 on an interface
399 - Verify route in FIB for prefix 10.10.10.0/24
400 - Configure IPv4 address 10.10.10.20/24 on an interface
401 - Delete 10.10.10.10/24 from interface
402 - Verify route in FIB for prefix 10.10.10.0/24
403 - Delete 10.10.10.20/24 from interface
404 - Verify no route in FIB for prefix 10.10.10.0/24
405 """
406
407 # create two addresses, verify route not present
Neale Rannsefd7bc22019-11-11 08:32:34 +0000408 if_addr1 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.10", 24)
409 if_addr2 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.20", 24)
410 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500411 self.assertFalse(find_route(self, "10.10.10.10", 32))
412 self.assertFalse(find_route(self, "10.10.10.20", 32))
413 self.assertFalse(find_route(self, "10.10.10.255", 32))
414 self.assertFalse(find_route(self, "10.10.10.0", 32))
415
416 # configure first address, verify route present
417 if_addr1.add_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000418 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500419 self.assertTrue(find_route(self, "10.10.10.10", 32))
420 self.assertFalse(find_route(self, "10.10.10.20", 32))
421 self.assertTrue(find_route(self, "10.10.10.255", 32))
422 self.assertTrue(find_route(self, "10.10.10.0", 32))
423
424 # configure second address, delete first, verify route not removed
425 if_addr2.add_vpp_config()
426 if_addr1.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000427 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
428 self.assertTrue(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500429 self.assertFalse(find_route(self, "10.10.10.10", 32))
430 self.assertTrue(find_route(self, "10.10.10.20", 32))
431 self.assertTrue(find_route(self, "10.10.10.255", 32))
432 self.assertTrue(find_route(self, "10.10.10.0", 32))
433
434 # delete second address, verify route removed
435 if_addr2.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000436 self.assertFalse(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500437 self.assertFalse(find_route(self, "10.10.10.10", 32))
438 self.assertFalse(find_route(self, "10.10.10.20", 32))
439 self.assertFalse(find_route(self, "10.10.10.255", 32))
440 self.assertFalse(find_route(self, "10.10.10.0", 32))
441
Matthew G Smith88d29a92019-07-17 10:01:17 -0500442 def test_ipv4_ifaddr_route(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200443 """IPv4 Interface Address Route test
Matthew G Smith88d29a92019-07-17 10:01:17 -0500444
445 Test scenario:
446
447 - Create loopback
448 - Configure IPv4 address on loopback
449 - Verify that address is not in the FIB
450 - Bring loopback up
451 - Verify that address is in the FIB now
452 - Bring loopback down
453 - Verify that address is not in the FIB anymore
454 - Bring loopback up
455 - Configure IPv4 address on loopback
456 - Verify that address is in the FIB now
457 """
458
459 # create a loopback and configure IPv4
460 loopbacks = self.create_loopback_interfaces(1)
461 lo_if = self.lo_interfaces[0]
462
463 lo_if.local_ip4_prefix_len = 32
464 lo_if.config_ip4()
465
466 # The intf was down when addr was added -> entry not in FIB
467 fib4_dump = self.vapi.ip_route_dump(0)
468 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
469
470 # When intf is brought up, entry is added
471 lo_if.admin_up()
472 fib4_dump = self.vapi.ip_route_dump(0)
473 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
474
475 # When intf is brought down, entry is removed
476 lo_if.admin_down()
477 fib4_dump = self.vapi.ip_route_dump(0)
478 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
479
480 # Remove addr, bring up interface, re-add -> entry in FIB
481 lo_if.unconfig_ip4()
482 lo_if.admin_up()
483 lo_if.config_ip4()
484 fib4_dump = self.vapi.ip_route_dump(0)
485 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
486
yedgdbd366b2020-05-14 10:51:53 +0800487 def test_ipv4_ifaddr_del(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200488 """Delete an interface address that does not exist"""
yedgdbd366b2020-05-14 10:51:53 +0800489
490 loopbacks = self.create_loopback_interfaces(1)
491 lo = self.lo_interfaces[0]
492
493 lo.config_ip4()
494 lo.admin_up()
495
496 #
497 # try and remove pg0's subnet from lo
498 #
499 with self.vapi.assert_negative_api_retval():
500 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200501 sw_if_index=lo.sw_if_index, prefix=self.pg0.local_ip4_prefix, is_add=0
502 )
yedgdbd366b2020-05-14 10:51:53 +0800503
Matthew G Smith88d29a92019-07-17 10:01:17 -0500504
Jan Geletye6c78ee2018-06-26 12:24:03 +0200505class TestICMPEcho(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200506 """ICMP Echo Test Case"""
Jan Geletye6c78ee2018-06-26 12:24:03 +0200507
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700508 @classmethod
509 def setUpClass(cls):
510 super(TestICMPEcho, cls).setUpClass()
511
512 @classmethod
513 def tearDownClass(cls):
514 super(TestICMPEcho, cls).tearDownClass()
515
Jan Geletye6c78ee2018-06-26 12:24:03 +0200516 def setUp(self):
517 super(TestICMPEcho, self).setUp()
518
519 # create 1 pg interface
520 self.create_pg_interfaces(range(1))
521
522 for i in self.pg_interfaces:
523 i.admin_up()
524 i.config_ip4()
525 i.resolve_arp()
526
527 def tearDown(self):
528 super(TestICMPEcho, self).tearDown()
529 for i in self.pg_interfaces:
530 i.unconfig_ip4()
531 i.admin_down()
532
533 def test_icmp_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 """VPP replies to ICMP Echo Request
Jan Geletye6c78ee2018-06-26 12:24:03 +0200535
536 Test scenario:
537
538 - Receive ICMP Echo Request message on pg0 interface.
539 - Check outgoing ICMP Echo Reply message on pg0 interface.
540 """
541
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200542 icmp_id = 0xB
Jan Geletye6c78ee2018-06-26 12:24:03 +0200543 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200544 icmp_load = b"\x0a" * 18
545 p_echo_request = (
546 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
547 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
548 / ICMP(id=icmp_id, seq=icmp_seq)
549 / Raw(load=icmp_load)
550 )
Jan Geletye6c78ee2018-06-26 12:24:03 +0200551
552 self.pg0.add_stream(p_echo_request)
553 self.pg_enable_capture(self.pg_interfaces)
554 self.pg_start()
555
556 rx = self.pg0.get_capture(1)
557 rx = rx[0]
558 ether = rx[Ether]
559 ipv4 = rx[IP]
560 icmp = rx[ICMP]
561
562 self.assertEqual(ether.src, self.pg0.local_mac)
563 self.assertEqual(ether.dst, self.pg0.remote_mac)
564
565 self.assertEqual(ipv4.src, self.pg0.local_ip4)
566 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
567
568 self.assertEqual(icmptypes[icmp.type], "echo-reply")
569 self.assertEqual(icmp.id, icmp_id)
570 self.assertEqual(icmp.seq, icmp_seq)
571 self.assertEqual(icmp[Raw].load, icmp_load)
572
573
Matej Klotton16a14cd2016-12-07 15:09:13 +0100574class TestIPv4FibCrud(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200575 """FIB - add/update/delete - ip4 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100576
577 Test scenario:
578 - add 1k,
579 - del 100,
580 - add new 1k,
581 - del 1.5k
582
Klement Sekerada505f62017-01-04 12:58:53 +0100583 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100584 """
585
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100587 """
588
589 :param start_dest_addr:
590 :param next_hop_addr:
591 :param count:
592 :return list: added ips with 32 prefix
593 """
Neale Ranns097fa662018-05-01 05:17:55 -0700594 routes = []
595 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200596 r = VppIpRoute(
597 self,
598 start_dest_addr % (i + start),
599 32,
600 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
601 )
Neale Ranns097fa662018-05-01 05:17:55 -0700602 r.add_vpp_config()
603 routes.append(r)
604 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100605
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200606 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count, start=0):
Neale Ranns097fa662018-05-01 05:17:55 -0700607 routes = []
608 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 r = VppIpRoute(
610 self,
611 start_dest_addr % (i + start),
612 32,
613 [VppRoutePath(next_hop_addr, 0xFFFFFFFF)],
614 )
Neale Ranns097fa662018-05-01 05:17:55 -0700615 r.remove_vpp_config()
616 routes.append(r)
617 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100618
Neale Ranns097fa662018-05-01 05:17:55 -0700619 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100620 pkts = []
621
622 for _ in range(count):
Neale Rannsefd7bc22019-11-11 08:32:34 +0000623 dst_addr = random.choice(routes).prefix.network_address
Klement Sekeradab231a2016-12-21 08:50:14 +0100624 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100625 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200626 p = (
627 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
628 / IP(src=src_if.remote_ip4, dst=str(dst_addr))
629 / UDP(sport=1234, dport=1234)
630 / Raw(payload)
631 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100632 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100633 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
634 pkts.append(p)
635
636 return pkts
637
638 def _find_ip_match(self, find_in, pkt):
639 for p in find_in:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200640 if self.payload_to_info(p[Raw]) == self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100641 if p[IP].src != pkt[IP].src:
642 break
643 if p[IP].dst != pkt[IP].dst:
644 break
645 if p[UDP].sport != pkt[UDP].sport:
646 break
647 if p[UDP].dport != pkt[UDP].dport:
648 break
649 return p
650 return None
651
Matej Klotton16a14cd2016-12-07 15:09:13 +0100652 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
653 self.assertEqual(len(received_pkts), len(expected_pkts))
654 to_verify = list(expected_pkts)
655 for p in received_pkts:
656 self.assertEqual(p.src, dst_interface.local_mac)
657 self.assertEqual(p.dst, dst_interface.remote_mac)
658 x = self._find_ip_match(to_verify, p)
659 to_verify.remove(x)
660 self.assertListEqual(to_verify, [])
661
Neale Ranns097fa662018-05-01 05:17:55 -0700662 def verify_route_dump(self, routes):
663 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200664 self.assertTrue(
665 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
666 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100667
Neale Ranns097fa662018-05-01 05:17:55 -0700668 def verify_not_in_route_dump(self, routes):
669 for r in routes:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200670 self.assertFalse(
671 find_route(self, r.prefix.network_address, r.prefix.prefixlen)
672 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100673
674 @classmethod
675 def setUpClass(cls):
676 """
677 #. Create and initialize 3 pg interfaces.
678 #. initialize class attributes configured_routes and deleted_routes
679 to store information between tests.
680 """
681 super(TestIPv4FibCrud, cls).setUpClass()
682
683 try:
684 # create 3 pg interfaces
685 cls.create_pg_interfaces(range(3))
686
687 cls.interfaces = list(cls.pg_interfaces)
688
689 # setup all interfaces
690 for i in cls.interfaces:
691 i.admin_up()
692 i.config_ip4()
693 i.resolve_arp()
694
695 cls.configured_routes = []
696 cls.deleted_routes = []
697 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
698
699 except Exception:
700 super(TestIPv4FibCrud, cls).tearDownClass()
701 raise
702
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700703 @classmethod
704 def tearDownClass(cls):
705 super(TestIPv4FibCrud, cls).tearDownClass()
706
Matej Klotton16a14cd2016-12-07 15:09:13 +0100707 def setUp(self):
708 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100709 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100710
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800711 self.configured_routes = []
712 self.deleted_routes = []
713
Matej Klotton16a14cd2016-12-07 15:09:13 +0100714 def test_1_add_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200715 """Add 1k routes"""
Matej Klotton16a14cd2016-12-07 15:09:13 +0100716
Neale Ranns097fa662018-05-01 05:17:55 -0700717 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200718 self.configured_routes.extend(
719 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
720 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100721
Neale Ranns097fa662018-05-01 05:17:55 -0700722 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100723
724 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200725 self.pg1, self.pg0, self.configured_routes, 100
726 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100727 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200728 self.pg2, self.pg0, self.configured_routes, 100
729 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100730 self.pg1.add_stream(self.stream_1)
731 self.pg2.add_stream(self.stream_2)
732
733 self.pg_enable_capture(self.pg_interfaces)
734 self.pg_start()
735
Klement Sekeradab231a2016-12-21 08:50:14 +0100736 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100737 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
738
Matej Klotton16a14cd2016-12-07 15:09:13 +0100739 def test_2_del_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200740 """Delete 100 routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100741
742 - delete 10 routes check with traffic script.
743 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800744 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200745 self.configured_routes.extend(
746 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
747 )
748 self.deleted_routes.extend(
749 self.unconfig_fib_many_to_one(
750 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
751 )
752 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100753 for x in self.deleted_routes:
754 self.configured_routes.remove(x)
755
Neale Ranns097fa662018-05-01 05:17:55 -0700756 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100757
758 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200759 self.pg1, self.pg0, self.configured_routes, 100
760 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100761 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200762 self.pg2, self.pg0, self.configured_routes, 100
763 )
764 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
765 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100766 self.pg1.add_stream(self.stream_1 + self.stream_3)
767 self.pg2.add_stream(self.stream_2 + self.stream_4)
768 self.pg_enable_capture(self.pg_interfaces)
769 self.pg_start()
770
Klement Sekeradab231a2016-12-21 08:50:14 +0100771 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100772 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
773
774 def test_3_add_new_routes(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 """Add 1k routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100776
777 - re-add 5 routes check with traffic script.
778 - add 100 routes check with traffic script.
779 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800780 # config 1M FIB entries
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200781 self.configured_routes.extend(
782 self.config_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 100)
783 )
784 self.deleted_routes.extend(
785 self.unconfig_fib_many_to_one(
786 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10
787 )
788 )
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800789 for x in self.deleted_routes:
790 self.configured_routes.remove(x)
791
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200792 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 +0100793 self.configured_routes.extend(tmp)
794 for x in tmp:
795 self.deleted_routes.remove(x)
796
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 self.configured_routes.extend(
798 self.config_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
799 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100800
Neale Ranns097fa662018-05-01 05:17:55 -0700801 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100802
803 self.stream_1 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200804 self.pg1, self.pg0, self.configured_routes, 300
805 )
Matej Klotton16a14cd2016-12-07 15:09:13 +0100806 self.stream_2 = self.create_stream(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200807 self.pg2, self.pg0, self.configured_routes, 300
808 )
809 self.stream_3 = self.create_stream(self.pg1, self.pg0, self.deleted_routes, 100)
810 self.stream_4 = self.create_stream(self.pg2, self.pg0, self.deleted_routes, 100)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100811
812 self.pg1.add_stream(self.stream_1 + self.stream_3)
813 self.pg2.add_stream(self.stream_2 + self.stream_4)
814 self.pg_enable_capture(self.pg_interfaces)
815 self.pg_start()
816
Klement Sekeradab231a2016-12-21 08:50:14 +0100817 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100818 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
819
Neale Ranns097fa662018-05-01 05:17:55 -0700820 # delete 5 routes check with traffic script.
821 # add 100 routes check with traffic script.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200822 self.deleted_routes.extend(
823 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 15)
824 )
825 self.deleted_routes.extend(
826 self.unconfig_fib_many_to_one("10.0.0.%d", self.pg0.remote_ip4, 85)
827 )
828 self.deleted_routes.extend(
829 self.unconfig_fib_many_to_one("10.0.1.%d", self.pg0.remote_ip4, 100)
830 )
Neale Ranns097fa662018-05-01 05:17:55 -0700831 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100832
833
Neale Ranns37be7362017-02-21 17:30:26 -0800834class TestIPNull(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200835 """IPv4 routes via NULL"""
Neale Ranns37be7362017-02-21 17:30:26 -0800836
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700837 @classmethod
838 def setUpClass(cls):
839 super(TestIPNull, cls).setUpClass()
840
841 @classmethod
842 def tearDownClass(cls):
843 super(TestIPNull, cls).tearDownClass()
844
Neale Ranns37be7362017-02-21 17:30:26 -0800845 def setUp(self):
846 super(TestIPNull, self).setUp()
847
848 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700849 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800850
851 for i in self.pg_interfaces:
852 i.admin_up()
853 i.config_ip4()
854 i.resolve_arp()
855
856 def tearDown(self):
857 super(TestIPNull, self).tearDown()
858 for i in self.pg_interfaces:
859 i.unconfig_ip4()
860 i.admin_down()
861
862 def test_ip_null(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 """IP NULL route"""
Neale Ranns37be7362017-02-21 17:30:26 -0800864
865 #
866 # A route via IP NULL that will reply with ICMP unreachables
867 #
Neale Ranns097fa662018-05-01 05:17:55 -0700868 ip_unreach = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200869 self,
870 "10.0.0.1",
871 32,
872 [
873 VppRoutePath(
874 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH
875 )
876 ],
877 )
Neale Ranns37be7362017-02-21 17:30:26 -0800878 ip_unreach.add_vpp_config()
879
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200880 p_unreach = (
881 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
882 / IP(src=self.pg0.remote_ip4, dst="10.0.0.1")
883 / UDP(sport=1234, dport=1234)
884 / Raw(b"\xa5" * 100)
885 )
Neale Ranns37be7362017-02-21 17:30:26 -0800886 self.pg0.add_stream(p_unreach)
887 self.pg_enable_capture(self.pg_interfaces)
888 self.pg_start()
889
890 rx = self.pg0.get_capture(1)
891 rx = rx[0]
892 icmp = rx[ICMP]
893
894 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
895 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
896 self.assertEqual(icmp.src, self.pg0.remote_ip4)
897 self.assertEqual(icmp.dst, "10.0.0.1")
898
899 #
900 # ICMP replies are rate limited. so sit and spin.
901 #
902 self.sleep(1)
903
904 #
905 # A route via IP NULL that will reply with ICMP prohibited
906 #
Neale Ranns097fa662018-05-01 05:17:55 -0700907 ip_prohibit = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200908 self,
909 "10.0.0.2",
910 32,
911 [
912 VppRoutePath(
913 "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT
914 )
915 ],
916 )
Neale Ranns37be7362017-02-21 17:30:26 -0800917 ip_prohibit.add_vpp_config()
918
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200919 p_prohibit = (
920 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
921 / IP(src=self.pg0.remote_ip4, dst="10.0.0.2")
922 / UDP(sport=1234, dport=1234)
923 / Raw(b"\xa5" * 100)
924 )
Neale Ranns37be7362017-02-21 17:30:26 -0800925
926 self.pg0.add_stream(p_prohibit)
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pg_start()
929
930 rx = self.pg0.get_capture(1)
931
932 rx = rx[0]
933 icmp = rx[ICMP]
934
935 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
936 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
937 self.assertEqual(icmp.src, self.pg0.remote_ip4)
938 self.assertEqual(icmp.dst, "10.0.0.2")
939
Neale Ranns3b93be52018-09-07 01:48:54 -0700940 def test_ip_drop(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200941 """IP Drop Routes"""
Neale Ranns3b93be52018-09-07 01:48:54 -0700942
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200943 p = (
944 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
945 / IP(src=self.pg0.remote_ip4, dst="1.1.1.1")
946 / UDP(sport=1234, dport=1234)
947 / Raw(b"\xa5" * 100)
948 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700949
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200950 r1 = VppIpRoute(
951 self,
952 "1.1.1.0",
953 24,
954 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
955 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700956 r1.add_vpp_config()
957
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400958 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700959
960 #
961 # insert a more specific as a drop
962 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200963 r2 = VppIpRoute(
964 self,
965 "1.1.1.1",
966 32,
967 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP)],
968 )
Neale Ranns3b93be52018-09-07 01:48:54 -0700969 r2.add_vpp_config()
970
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400971 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700972 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400973 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700974
Dmitry Valtere95687b2023-12-20 10:47:35 +0000975 t = VppIpTable(self, 2, False)
976 t.add_vpp_config()
977 r3 = VppIpRoute(
978 self,
979 "1.1.1.0",
980 31,
981 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_DROP)],
982 table_id=2,
983 )
984 r3.add_vpp_config()
985 r3.remove_vpp_config()
986 t.remove_vpp_config()
987
Neale Ranns37be7362017-02-21 17:30:26 -0800988
Neale Ranns180279b2017-03-16 15:49:09 -0400989class TestIPDisabled(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200990 """IPv4 disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -0400991
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700992 @classmethod
993 def setUpClass(cls):
994 super(TestIPDisabled, cls).setUpClass()
995
996 @classmethod
997 def tearDownClass(cls):
998 super(TestIPDisabled, cls).tearDownClass()
999
Neale Ranns180279b2017-03-16 15:49:09 -04001000 def setUp(self):
1001 super(TestIPDisabled, self).setUp()
1002
1003 # create 2 pg interfaces
1004 self.create_pg_interfaces(range(2))
1005
1006 # PG0 is IP enalbed
1007 self.pg0.admin_up()
1008 self.pg0.config_ip4()
1009 self.pg0.resolve_arp()
1010
1011 # PG 1 is not IP enabled
1012 self.pg1.admin_up()
1013
1014 def tearDown(self):
1015 super(TestIPDisabled, self).tearDown()
1016 for i in self.pg_interfaces:
1017 i.unconfig_ip4()
1018 i.admin_down()
1019
Neale Ranns180279b2017-03-16 15:49:09 -04001020 def test_ip_disabled(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001021 """IP Disabled"""
Neale Ranns180279b2017-03-16 15:49:09 -04001022
Neale Ranns990f6942020-10-20 07:20:17 +00001023 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1024 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1025
Neale Ranns180279b2017-03-16 15:49:09 -04001026 #
1027 # An (S,G).
1028 # one accepting interface, pg0, 2 forwarding interfaces
1029 #
1030 route_232_1_1_1 = VppIpMRoute(
1031 self,
1032 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001033 "232.1.1.1",
1034 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001035 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 [
1037 VppMRoutePath(
1038 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1039 ),
1040 VppMRoutePath(
1041 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1042 ),
1043 ],
1044 )
Neale Ranns180279b2017-03-16 15:49:09 -04001045 route_232_1_1_1.add_vpp_config()
1046
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001047 pu = (
1048 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1049 / IP(src="10.10.10.10", dst=self.pg0.remote_ip4)
1050 / UDP(sport=1234, dport=1234)
1051 / Raw(b"\xa5" * 100)
1052 )
1053 pm = (
1054 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1055 / IP(src="10.10.10.10", dst="232.1.1.1")
1056 / UDP(sport=1234, dport=1234)
1057 / Raw(b"\xa5" * 100)
1058 )
Neale Ranns180279b2017-03-16 15:49:09 -04001059
1060 #
1061 # PG1 does not forward IP traffic
1062 #
1063 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1064 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1065
1066 #
1067 # IP enable PG1
1068 #
1069 self.pg1.config_ip4()
1070
1071 #
1072 # Now we get packets through
1073 #
1074 self.pg1.add_stream(pu)
1075 self.pg_enable_capture(self.pg_interfaces)
1076 self.pg_start()
1077 rx = self.pg0.get_capture(1)
1078
1079 self.pg1.add_stream(pm)
1080 self.pg_enable_capture(self.pg_interfaces)
1081 self.pg_start()
1082 rx = self.pg0.get_capture(1)
1083
1084 #
1085 # Disable PG1
1086 #
1087 self.pg1.unconfig_ip4()
1088
1089 #
1090 # PG1 does not forward IP traffic
1091 #
1092 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
1093 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
1094
1095
Neale Ranns9a69a602017-03-26 10:56:33 -07001096class TestIPSubNets(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001097 """IPv4 Subnets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001098
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001099 @classmethod
1100 def setUpClass(cls):
1101 super(TestIPSubNets, cls).setUpClass()
1102
1103 @classmethod
1104 def tearDownClass(cls):
1105 super(TestIPSubNets, cls).tearDownClass()
1106
Neale Ranns9a69a602017-03-26 10:56:33 -07001107 def setUp(self):
1108 super(TestIPSubNets, self).setUp()
1109
1110 # create a 2 pg interfaces
1111 self.create_pg_interfaces(range(2))
1112
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001113 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -07001114 self.pg0.admin_up()
1115
1116 # pg1 is setup normally
1117 self.pg1.admin_up()
1118 self.pg1.config_ip4()
1119 self.pg1.resolve_arp()
1120
1121 def tearDown(self):
1122 super(TestIPSubNets, self).tearDown()
1123 for i in self.pg_interfaces:
1124 i.admin_down()
1125
Neale Ranns9a69a602017-03-26 10:56:33 -07001126 def test_ip_sub_nets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 """IP Sub Nets"""
Neale Ranns9a69a602017-03-26 10:56:33 -07001128
1129 #
1130 # Configure a covering route to forward so we know
1131 # when we are dropping
1132 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001133 cover_route = VppIpRoute(
1134 self,
1135 "10.0.0.0",
1136 8,
1137 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
1138 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001139 cover_route.add_vpp_config()
1140
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001141 p = (
1142 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1143 / IP(dst="10.10.10.10", src=self.pg0.local_ip4)
1144 / UDP(sport=1234, dport=1234)
1145 / Raw(b"\xa5" * 100)
1146 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001147
1148 self.pg1.add_stream(p)
1149 self.pg_enable_capture(self.pg_interfaces)
1150 self.pg_start()
1151 rx = self.pg1.get_capture(1)
1152
1153 #
1154 # Configure some non-/24 subnets on an IP interface
1155 #
1156 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1157
Ole Troan9a475372019-03-05 16:58:24 +01001158 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001159 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16"
1160 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001161
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 pn = (
1163 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1164 / IP(dst="10.10.0.0", src=self.pg0.local_ip4)
1165 / UDP(sport=1234, dport=1234)
1166 / Raw(b"\xa5" * 100)
1167 )
1168 pb = (
1169 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1170 / IP(dst="10.10.255.255", src=self.pg0.local_ip4)
1171 / UDP(sport=1234, dport=1234)
1172 / Raw(b"\xa5" * 100)
1173 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001174
1175 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
1176 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
1177
1178 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001179 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001180 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/16", is_add=0
1181 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001182
Neale Ranns9a69a602017-03-26 10:56:33 -07001183 self.pg1.add_stream(pn)
1184 self.pg_enable_capture(self.pg_interfaces)
1185 self.pg_start()
1186 rx = self.pg1.get_capture(1)
1187 self.pg1.add_stream(pb)
1188 self.pg_enable_capture(self.pg_interfaces)
1189 self.pg_start()
1190 rx = self.pg1.get_capture(1)
1191
1192 #
1193 # A /31 is a special case where the 'other-side' is an attached host
1194 # packets to that peer generate ARP requests
1195 #
1196 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1197
Ole Troan9a475372019-03-05 16:58:24 +01001198 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001199 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31"
1200 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001201
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001202 pn = (
1203 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1204 / IP(dst="10.10.10.11", src=self.pg0.local_ip4)
1205 / UDP(sport=1234, dport=1234)
1206 / Raw(b"\xa5" * 100)
1207 )
Neale Ranns9a69a602017-03-26 10:56:33 -07001208
1209 self.pg1.add_stream(pn)
1210 self.pg_enable_capture(self.pg_interfaces)
1211 self.pg_start()
1212 rx = self.pg0.get_capture(1)
1213 rx[ARP]
1214
1215 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001216 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001217 sw_if_index=self.pg0.sw_if_index, prefix="10.10.10.10/31", is_add=0
1218 )
Jakub Grajciar053204a2019-03-18 13:17:53 +01001219
Neale Ranns9a69a602017-03-26 10:56:33 -07001220 self.pg1.add_stream(pn)
1221 self.pg_enable_capture(self.pg_interfaces)
1222 self.pg_start()
1223 rx = self.pg1.get_capture(1)
1224
1225
Neale Ranns227038a2017-04-21 01:07:59 -07001226class TestIPLoadBalance(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001227 """IPv4 Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001228
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001229 @classmethod
1230 def setUpClass(cls):
1231 super(TestIPLoadBalance, cls).setUpClass()
1232
1233 @classmethod
1234 def tearDownClass(cls):
1235 super(TestIPLoadBalance, cls).tearDownClass()
1236
Neale Ranns227038a2017-04-21 01:07:59 -07001237 def setUp(self):
1238 super(TestIPLoadBalance, self).setUp()
1239
1240 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -07001241 mpls_tbl = VppMplsTable(self, 0)
1242 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -07001243
1244 for i in self.pg_interfaces:
1245 i.admin_up()
1246 i.config_ip4()
1247 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -07001248 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001249
1250 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -07001251 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -07001252 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001253 i.unconfig_ip4()
1254 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001255 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -07001256
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001257 def total_len(self, rxs):
1258 n = 0
1259 for rx in rxs:
1260 n += len(rx)
1261 return n
1262
Neale Ranns227038a2017-04-21 01:07:59 -07001263 def test_ip_load_balance(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001264 """IP Load-Balancing"""
Neale Ranns227038a2017-04-21 01:07:59 -07001265
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001266 fhc = VppEnum.vl_api_ip_flow_hash_config_t
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001267 fhcv2 = VppEnum.vl_api_ip_flow_hash_config_v2_t
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001268 af = VppEnum.vl_api_address_family_t
1269
Neale Ranns227038a2017-04-21 01:07:59 -07001270 #
1271 # An array of packets that differ only in the destination port
1272 #
Neale Ranns71275e32017-05-25 12:38:58 -07001273 port_ip_pkts = []
1274 port_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001275 port_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001276
1277 #
1278 # An array of packets that differ only in the source address
1279 #
Neale Ranns71275e32017-05-25 12:38:58 -07001280 src_ip_pkts = []
1281 src_mpls_pkts = []
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001282 src_gtp_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001283
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001284 for ii in range(NUM_PKTS):
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001285 internal_src_ip_hdr = IP(dst="10.0.0.1", src="20.0.0.1")
1286
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001287 port_ip_hdr = (
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001288 internal_src_ip_hdr
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001289 / UDP(sport=1234, dport=1234 + ii)
1290 / Raw(b"\xa5" * 100)
1291 )
1292 port_ip_pkts.append(
1293 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)
1294 )
1295 port_mpls_pkts.append(
1296 (
1297 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1298 / MPLS(label=66, ttl=2)
1299 / port_ip_hdr
1300 )
1301 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001302 port_gtp_pkts.append(
1303 (
1304 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1305 / internal_src_ip_hdr
1306 / UDP(sport=2152, dport=2152, chksum=0)
1307 / GTP_U_Header(gtp_type="g_pdu", teid=200)
1308 / Raw(b"\xa5" * 100)
1309 )
1310 )
Neale Ranns71275e32017-05-25 12:38:58 -07001311
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001312 src_ip_hdr = (
1313 IP(dst="10.0.0.1", src="20.0.0.%d" % ii)
1314 / UDP(sport=1234, dport=1234)
1315 / Raw(b"\xa5" * 100)
1316 )
1317 src_ip_pkts.append(
1318 (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)
1319 )
1320 src_mpls_pkts.append(
1321 (
1322 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1323 / MPLS(label=66, ttl=2)
1324 / src_ip_hdr
1325 )
1326 )
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001327 src_gtp_pkts.append(
1328 (
1329 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1330 / IP(dst="10.0.0.1", src="20.0.0.1")
1331 / UDP(sport=2152, dport=2152, chksum=0)
1332 / GTP_U_Header(gtp_type="g_pdu", teid=ii)
1333 / Raw(b"\xa5" * 100)
1334 )
1335 )
Neale Ranns227038a2017-04-21 01:07:59 -07001336
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001337 route_10_0_0_1 = VppIpRoute(
1338 self,
1339 "10.0.0.1",
1340 32,
1341 [
1342 VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index),
1343 VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index),
1344 ],
1345 )
Neale Ranns227038a2017-04-21 01:07:59 -07001346 route_10_0_0_1.add_vpp_config()
1347
Neale Ranns71275e32017-05-25 12:38:58 -07001348 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1349 binding.add_vpp_config()
1350
Neale Ranns227038a2017-04-21 01:07:59 -07001351 #
1352 # inject the packet on pg0 - expect load-balancing across the 2 paths
1353 # - since the default hash config is to use IP src,dst and port
1354 # src,dst
1355 # We are not going to ensure equal amounts of packets across each link,
1356 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001357 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001358 # balancing. So instead just ensure there is traffic on each link.
1359 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001360 rx = self.send_and_expect_load_balancing(
1361 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1362 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001363 n_ip_pg0 = len(rx[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001364 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1365 self.send_and_expect_load_balancing(
1366 self.pg0, port_mpls_pkts, [self.pg1, self.pg2]
1367 )
1368 rx = self.send_and_expect_load_balancing(
1369 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1370 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001371 n_mpls_pg0 = len(rx[0])
1372
1373 #
1374 # change the router ID and expect the distribution changes
1375 #
1376 self.vapi.set_ip_flow_hash_router_id(router_id=0x11111111)
1377
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001378 rx = self.send_and_expect_load_balancing(
1379 self.pg0, port_ip_pkts, [self.pg1, self.pg2]
1380 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001381 self.assertNotEqual(n_ip_pg0, len(rx[0]))
1382
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001383 rx = self.send_and_expect_load_balancing(
1384 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1385 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001386 self.assertNotEqual(n_mpls_pg0, len(rx[0]))
Neale Ranns227038a2017-04-21 01:07:59 -07001387
1388 #
1389 # change the flow hash config so it's only IP src,dst
1390 # - now only the stream with differing source address will
1391 # load-balance
1392 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001393 self.vapi.set_ip_flow_hash_v2(
1394 af=af.ADDRESS_IP4,
1395 table_id=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001396 flow_hash_config=(
1397 fhc.IP_API_FLOW_HASH_SRC_IP
1398 | fhc.IP_API_FLOW_HASH_DST_IP
1399 | fhc.IP_API_FLOW_HASH_PROTO
1400 ),
1401 )
Neale Ranns227038a2017-04-21 01:07:59 -07001402
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001403 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2])
1404 self.send_and_expect_load_balancing(
1405 self.pg0, src_mpls_pkts, [self.pg1, self.pg2]
1406 )
Neale Ranns227038a2017-04-21 01:07:59 -07001407
Neale Ranns699bea22022-02-17 09:22:16 +00001408 self.send_and_expect_only(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001409
1410 #
Takeru Hayasakab23c6f42023-01-17 04:45:58 +09001411 # this case gtp v1 teid key LB
1412 #
1413 self.vapi.set_ip_flow_hash_v3(
1414 af=af.ADDRESS_IP4,
1415 table_id=0,
1416 flow_hash_config=(
1417 fhcv2.IP_API_V2_FLOW_HASH_SRC_IP
1418 | fhcv2.IP_API_V2_FLOW_HASH_PROTO
1419 | fhcv2.IP_API_V2_FLOW_HASH_GTPV1_TEID
1420 ),
1421 )
1422 self.logger.info(self.vapi.cli("show ip fib"))
1423
1424 self.send_and_expect_load_balancing(
1425 self.pg0, src_gtp_pkts, [self.pg1, self.pg2]
1426 )
1427
1428 self.send_and_expect_only(self.pg0, port_gtp_pkts, self.pg2)
1429
1430 #
Neale Ranns227038a2017-04-21 01:07:59 -07001431 # change the flow hash config back to defaults
1432 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 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 -07001434
1435 #
1436 # Recursive prefixes
1437 # - testing that 2 stages of load-balancing occurs and there is no
1438 # polarisation (i.e. only 2 of 4 paths are used)
1439 #
1440 port_pkts = []
1441 src_pkts = []
1442
1443 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001444 port_pkts.append(
1445 (
1446 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1447 / IP(dst="1.1.1.1", src="20.0.0.1")
1448 / UDP(sport=1234, dport=1234 + ii)
1449 / Raw(b"\xa5" * 100)
1450 )
1451 )
1452 src_pkts.append(
1453 (
1454 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1455 / IP(dst="1.1.1.1", src="20.0.0.%d" % ii)
1456 / UDP(sport=1234, dport=1234)
1457 / Raw(b"\xa5" * 100)
1458 )
1459 )
Neale Ranns227038a2017-04-21 01:07:59 -07001460
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001461 route_10_0_0_2 = VppIpRoute(
1462 self,
1463 "10.0.0.2",
1464 32,
1465 [
1466 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1467 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1468 ],
1469 )
Neale Ranns227038a2017-04-21 01:07:59 -07001470 route_10_0_0_2.add_vpp_config()
1471
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001472 route_1_1_1_1 = VppIpRoute(
1473 self,
1474 "1.1.1.1",
1475 32,
1476 [
1477 VppRoutePath("10.0.0.2", 0xFFFFFFFF),
1478 VppRoutePath("10.0.0.1", 0xFFFFFFFF),
1479 ],
1480 )
Neale Ranns227038a2017-04-21 01:07:59 -07001481 route_1_1_1_1.add_vpp_config()
1482
1483 #
1484 # inject the packet on pg0 - expect load-balancing across all 4 paths
1485 #
1486 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001487 self.send_and_expect_load_balancing(
1488 self.pg0, port_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1489 )
1490 self.send_and_expect_load_balancing(
1491 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1492 )
Neale Ranns227038a2017-04-21 01:07:59 -07001493
Neale Ranns42e6b092017-07-31 02:56:03 -07001494 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001495 # bring down pg1 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001496 #
1497 self.pg1.link_down()
1498
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001499 rx = self.send_and_expect_load_balancing(
1500 self.pg0, src_pkts, [self.pg2, self.pg3, self.pg4]
1501 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001502 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001503
1504 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001505 # bring down pg2 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001506 #
1507 self.pg2.link_down()
1508
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001509 rx = self.send_and_expect_load_balancing(
1510 self.pg0, src_pkts, [self.pg3, self.pg4]
1511 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001512 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001513
1514 #
1515 # bring the links back up - expect LB over all again
1516 #
1517 self.pg1.link_up()
1518 self.pg2.link_up()
1519
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001520 rx = self.send_and_expect_load_balancing(
1521 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1522 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001523 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001524
1525 #
1526 # The same link-up/down but this time admin state
1527 #
1528 self.pg1.admin_down()
1529 self.pg2.admin_down()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001530 rx = self.send_and_expect_load_balancing(
1531 self.pg0, src_pkts, [self.pg3, self.pg4]
1532 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001533 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001534 self.pg1.admin_up()
1535 self.pg2.admin_up()
1536 self.pg1.resolve_arp()
1537 self.pg2.resolve_arp()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001538 rx = self.send_and_expect_load_balancing(
1539 self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]
1540 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001541 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001542
1543 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001544 # Recursive prefixes
1545 # - testing that 2 stages of load-balancing, no choices
1546 #
1547 port_pkts = []
1548
1549 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001550 port_pkts.append(
1551 (
1552 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1553 / IP(dst="1.1.1.2", src="20.0.0.2")
1554 / UDP(sport=1234, dport=1234 + ii)
1555 / Raw(b"\xa5" * 100)
1556 )
1557 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001558
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001559 route_10_0_0_3 = VppIpRoute(
1560 self,
1561 "10.0.0.3",
1562 32,
1563 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
1564 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001565 route_10_0_0_3.add_vpp_config()
1566
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001567 route_1_1_1_2 = VppIpRoute(
1568 self, "1.1.1.2", 32, [VppRoutePath("10.0.0.3", 0xFFFFFFFF)]
1569 )
Neale Ranns42e6b092017-07-31 02:56:03 -07001570 route_1_1_1_2.add_vpp_config()
1571
1572 #
Neale Ranns63480742019-03-13 06:41:52 -07001573 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001574 #
1575 self.vapi.cli("clear trace")
Neale Ranns699bea22022-02-17 09:22:16 +00001576 self.send_and_expect_only(self.pg0, port_pkts, self.pg3)
Neale Ranns42e6b092017-07-31 02:56:03 -07001577
Neale Ranns63480742019-03-13 06:41:52 -07001578 #
1579 # Add a LB route in the presence of a down link - expect no
1580 # packets over the down link
1581 #
1582 self.pg3.link_down()
1583
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001584 route_10_0_0_3 = VppIpRoute(
1585 self,
1586 "10.0.0.3",
1587 32,
1588 [
1589 VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index),
1590 VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index),
1591 ],
1592 )
Neale Ranns63480742019-03-13 06:41:52 -07001593 route_10_0_0_3.add_vpp_config()
1594
1595 port_pkts = []
1596 for ii in range(257):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001597 port_pkts.append(
1598 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1599 / IP(dst="10.0.0.3", src="20.0.0.2")
1600 / UDP(sport=1234, dport=1234 + ii)
1601 / Raw(b"\xa5" * 100)
1602 )
Neale Ranns63480742019-03-13 06:41:52 -07001603
Neale Ranns699bea22022-02-17 09:22:16 +00001604 self.send_and_expect_only(self.pg0, port_pkts, self.pg4)
Neale Ranns63480742019-03-13 06:41:52 -07001605
1606 # bring the link back up
1607 self.pg3.link_up()
1608
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001609 rx = self.send_and_expect_load_balancing(
1610 self.pg0, port_pkts, [self.pg3, self.pg4]
1611 )
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001612 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001613
Neale Ranns30d0fd42017-05-30 07:30:04 -07001614
1615class TestIPVlan0(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001616 """IPv4 VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001617
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001618 @classmethod
1619 def setUpClass(cls):
1620 super(TestIPVlan0, cls).setUpClass()
1621
1622 @classmethod
1623 def tearDownClass(cls):
1624 super(TestIPVlan0, cls).tearDownClass()
1625
Neale Ranns30d0fd42017-05-30 07:30:04 -07001626 def setUp(self):
1627 super(TestIPVlan0, self).setUp()
1628
1629 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001630 mpls_tbl = VppMplsTable(self, 0)
1631 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001632
1633 for i in self.pg_interfaces:
1634 i.admin_up()
1635 i.config_ip4()
1636 i.resolve_arp()
1637 i.enable_mpls()
1638
1639 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001640 for i in self.pg_interfaces:
1641 i.disable_mpls()
1642 i.unconfig_ip4()
1643 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001644 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001645
Neale Ranns30d0fd42017-05-30 07:30:04 -07001646 def test_ip_vlan_0(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001647 """IP VLAN-0"""
Neale Ranns30d0fd42017-05-30 07:30:04 -07001648
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001649 pkts = (
1650 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1651 / Dot1Q(vlan=0)
1652 / IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4)
1653 / UDP(sport=1234, dport=1234)
1654 / Raw(b"\xa5" * 100)
1655 ) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001656
1657 #
1658 # Expect that packets sent on VLAN-0 are forwarded on the
1659 # main interface.
1660 #
1661 self.send_and_expect(self.pg0, pkts, self.pg1)
1662
1663
Brian Russell318fdb82021-01-19 16:56:32 +00001664class IPPuntSetup(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001665 """Setup for IPv4 Punt Police/Redirect"""
Neale Rannsd91c1db2017-07-31 02:30:50 -07001666
Brian Russell318fdb82021-01-19 16:56:32 +00001667 def punt_setup(self):
Pavel Kotucek609e1212018-11-27 09:59:44 +01001668 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001669
1670 for i in self.pg_interfaces:
1671 i.admin_up()
1672 i.config_ip4()
1673 i.resolve_arp()
1674
Neale Ranns68577d22019-06-04 13:31:23 +00001675 # use UDP packet that have a port we need to explicitly
1676 # register to get punted.
1677 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1678 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1679 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1680 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001681 "type": pt_l4,
1682 "punt": {
1683 "l4": {
1684 "af": af_ip4,
1685 "protocol": udp_proto,
1686 "port": 1234,
Neale Ranns68577d22019-06-04 13:31:23 +00001687 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001688 },
Neale Ranns68577d22019-06-04 13:31:23 +00001689 }
1690
1691 self.vapi.set_punt(is_add=1, punt=punt_udp)
1692
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001693 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
1694 punt_udp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001695 "type": pt_l4,
1696 "punt": {
1697 "l4": {
1698 "af": af_ip6,
1699 "protocol": udp_proto,
1700 "port": 1236,
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001701 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001702 },
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001703 }
1704
1705 self.vapi.set_punt(is_add=1, punt=punt_udp)
1706
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001707 self.pkt = (
1708 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1709 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
1710 / UDP(sport=1234, dport=1234)
1711 / Raw(b"\xa5" * 100)
1712 )
Neale Rannsd91c1db2017-07-31 02:30:50 -07001713
Brian Russell318fdb82021-01-19 16:56:32 +00001714 def punt_teardown(self):
1715 for i in self.pg_interfaces:
1716 i.unconfig_ip4()
1717 i.admin_down()
1718
1719
1720class TestIPPunt(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001721 """IPv4 Punt Police/Redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001722
1723 def setUp(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001724 super().setUp()
1725 super().punt_setup()
Brian Russell318fdb82021-01-19 16:56:32 +00001726
1727 def tearDown(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001728 super().punt_teardown()
1729 super().tearDown()
1730
1731 def test_ip_punt_api_validation(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001732 """IP punt API parameter validation"""
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001733
1734 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001735 punt = {
1736 "rx_sw_if_index": self.pg0.sw_if_index,
1737 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1738 "n_paths": 1000000,
1739 "paths": [],
1740 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001741
1742 with self.assertRaises(vpp_papi.VPPIOError):
1743 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
1744
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001745 punt = {
1746 "rx_sw_if_index": self.pg0.sw_if_index,
1747 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1748 "n_paths": 0,
1749 "paths": [],
1750 }
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001751
1752 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
Brian Russell318fdb82021-01-19 16:56:32 +00001753
1754 def test_ip_punt(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001755 """IP punt police and redirect"""
Brian Russell318fdb82021-01-19 16:56:32 +00001756
1757 pkts = self.pkt * 1025
Neale Rannsd91c1db2017-07-31 02:30:50 -07001758
1759 #
1760 # Configure a punt redirect via pg1.
1761 #
Ole Troan0bcad322018-12-11 13:04:01 +01001762 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001763 ip_punt_redirect = VppIpPuntRedirect(
1764 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
1765 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001766 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001767
1768 self.send_and_expect(self.pg0, pkts, self.pg1)
1769
1770 #
1771 # add a policer
1772 #
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001773 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1)
1774 policer.add_vpp_config()
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001775 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1776 ip_punt_policer.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001777
1778 self.vapi.cli("clear trace")
1779 self.pg0.add_stream(pkts)
1780 self.pg_enable_capture(self.pg_interfaces)
1781 self.pg_start()
1782
1783 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001784 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001785 # but not equal to the number sent, since some were policed
1786 #
1787 rx = self.pg1._get_capture(1)
Brian Russelle9887262021-01-27 14:45:22 +00001788
1789 stats = policer.get_stats()
1790
1791 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001792 self.assertGreater(stats["conform_packets"], 0)
1793 self.assertEqual(stats["exceed_packets"], 0)
1794 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00001795
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001796 self.assertGreater(len(rx), 0)
1797 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001798
1799 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001800 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001801 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001802 ip_punt_policer.remove_vpp_config()
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001803 policer.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001804 self.send_and_expect(self.pg0, pkts, self.pg1)
1805
1806 #
1807 # remove the redirect. expect full drop.
1808 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001809 ip_punt_redirect.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001810 self.send_and_assert_no_replies(self.pg0, pkts, "IP no punt config")
Neale Rannsd91c1db2017-07-31 02:30:50 -07001811
1812 #
1813 # Add a redirect that is not input port selective
1814 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001815 ip_punt_redirect = VppIpPuntRedirect(
1816 self, 0xFFFFFFFF, self.pg1.sw_if_index, nh_addr
1817 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001818 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001819 self.send_and_expect(self.pg0, pkts, self.pg1)
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001820 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001821
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001822 def test_ip_punt_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001823 """IP punt/local with VRFs"""
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001824
1825 # use a punt redirect to test if for-us packets are accepted
1826 pkts = self.pkt * 1025
1827
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001828 vlans_pg0 = [VppDot1QSubint(self, self.pg0, v) for v in range(100, 104)]
1829 vlans_pg1 = [VppDot1QSubint(self, self.pg1, v) for v in range(100, 104)]
1830 tbl4 = [VppIpTable(self, v).add_vpp_config() for v in range(100, 104)]
1831 tbl6 = [VppIpTable(self, v, True).add_vpp_config() for v in range(100, 104)]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001832
1833 for v in vlans_pg0 + vlans_pg1:
1834 v.admin_up()
1835 v.set_table_ip4(v.vlan)
1836 v.set_table_ip6(v.vlan)
1837 v.config_ip4()
1838 v.config_ip6()
1839 v.resolve_arp()
1840 v.resolve_ndp()
1841
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001842 [
1843 VppIpPuntRedirect(
1844 self,
1845 vlans_pg0[i].sw_if_index,
1846 vlans_pg1[i].sw_if_index,
1847 vlans_pg1[i].remote_ip4,
1848 ).add_vpp_config()
1849 for i in range(4)
1850 ]
1851 [
1852 VppIpPuntRedirect(
1853 self,
1854 vlans_pg0[i].sw_if_index,
1855 vlans_pg1[i].sw_if_index,
1856 vlans_pg1[i].remote_ip6,
1857 ).add_vpp_config()
1858 for i in range(4)
1859 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001860
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001861 pkts = [
1862 (
1863 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1864 / Dot1Q(vlan=i.vlan)
1865 / IP(src=i.remote_ip4, dst=i.local_ip4)
1866 / UDP(sport=1234, dport=1234)
1867 / Raw(b"\xa5" * 100)
1868 )
1869 for i in vlans_pg0
1870 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001871
1872 self.send_and_expect(self.pg0, pkts, self.pg1)
1873
1874 #
1875 # IPv4
1876 #
1877
1878 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001879 pkts = [
1880 (
1881 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1882 / Dot1Q(vlan=i.vlan)
1883 / IP(src="1.1.1.1", dst=i.local_ip4)
1884 / UDP(sport=1234, dport=1234)
1885 / Raw(b"\xa5" * 100)
1886 )
1887 for i in vlans_pg0
1888 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001889 # single and dual loop
1890 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1891 self.send_and_assert_no_replies(self.pg0, pkts)
1892
Neale Rannse22a7042022-08-09 03:03:29 +00001893 self.assert_error_counter_equal("/err/ip4-local/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001894
1895 # using the same source in different tables, should reject
1896 # for the table that the source is not present in
1897 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001898 pkts = [
1899 (
1900 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1901 / Dot1Q(vlan=i.vlan)
1902 / IP(src=vlans_pg0[0].remote_ip4, dst=i.local_ip4)
1903 / UDP(sport=1234, dport=1234)
1904 / Raw(b"\xa5" * 100)
1905 )
1906 for i in vlans_pg0
1907 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001908 # single loop accept and drop
1909 # followed by both in the same frame/loop
1910 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1911 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1912 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1913
1914 # using the same source in different tables, should reject
1915 # for the table that the source is not present in
1916 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001917 pkts = [
1918 (
1919 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1920 / Dot1Q(vlan=i.vlan)
1921 / IP(src=vlans_pg0[3].remote_ip4, dst=i.local_ip4)
1922 / UDP(sport=1234, dport=1234)
1923 / Raw(b"\xa5" * 100)
1924 )
1925 for i in vlans_pg0
1926 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001927
1928 # single loop accept and drop
1929 # followed by both in the same frame/loop
1930 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1931 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1932 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1933
1934 #
1935 # IPv6
1936 #
1937
1938 # we reject packets for source addresses in the wrong vlan/VRF
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001939 pkts = [
1940 (
1941 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1942 / Dot1Q(vlan=i.vlan)
1943 / IPv6(src="1::1", dst=i.local_ip6)
1944 / UDP(sport=1236, dport=1236)
1945 / Raw(b"\xa5" * 100)
1946 )
1947 for i in vlans_pg0
1948 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001949 # single and dual loop
1950 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1951 self.send_and_assert_no_replies(self.pg0, pkts)
1952
Neale Rannse22a7042022-08-09 03:03:29 +00001953 self.assert_error_counter_equal("/err/ip6-input/src_lookup_miss", len(pkts) + 1)
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001954
1955 # using the same source in different tables, should reject
1956 # for the table that the source is not present in
1957 # the first packet in the stream is drop
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001958 pkts = [
1959 (
1960 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1961 / Dot1Q(vlan=i.vlan)
1962 / IPv6(src=vlans_pg0[0].remote_ip6, dst=i.local_ip6)
1963 / UDP(sport=1236, dport=1236)
1964 / Raw(b"\xa5" * 100)
1965 )
1966 for i in vlans_pg0
1967 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001968 # single loop accept and drop
1969 # followed by both in the same frame/loop
1970 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1971 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1972 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1973
1974 # using the same source in different tables, should reject
1975 # for the table that the source is not present in
1976 # the first packet in the stream is accept
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001977 pkts = [
1978 (
1979 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1980 / Dot1Q(vlan=i.vlan)
1981 / IPv6(src=vlans_pg0[3].remote_ip6, dst=i.local_ip6)
1982 / UDP(sport=1236, dport=1236)
1983 / Raw(b"\xa5" * 100)
1984 )
1985 for i in vlans_pg0
1986 ]
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001987
1988 # single loop accept and drop
1989 # followed by both in the same frame/loop
1990 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1991 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1992 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1993
1994 for v in vlans_pg0 + vlans_pg1:
1995 v.unconfig_ip4()
1996 v.unconfig_ip6()
1997 v.set_table_ip4(0)
1998 v.set_table_ip6(0)
1999
Pavel Kotucek609e1212018-11-27 09:59:44 +01002000 def test_ip_punt_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002001 """IP4 punt redirect dump"""
Pavel Kotucek609e1212018-11-27 09:59:44 +01002002
2003 #
2004 # Configure a punt redirects
2005 #
Ole Troan0bcad322018-12-11 13:04:01 +01002006 nh_address = self.pg3.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002007 ipr_03 = VppIpPuntRedirect(
2008 self, self.pg0.sw_if_index, self.pg3.sw_if_index, nh_address
2009 )
2010 ipr_13 = VppIpPuntRedirect(
2011 self, self.pg1.sw_if_index, self.pg3.sw_if_index, nh_address
2012 )
2013 ipr_23 = VppIpPuntRedirect(
2014 self, self.pg2.sw_if_index, self.pg3.sw_if_index, "0.0.0.0"
2015 )
Jakub Grajciar2df2f752020-12-01 11:23:44 +01002016 ipr_03.add_vpp_config()
2017 ipr_13.add_vpp_config()
2018 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01002019
2020 #
2021 # Dump pg0 punt redirects
2022 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01002023 self.assertTrue(ipr_03.query_vpp_config())
2024 self.assertTrue(ipr_13.query_vpp_config())
2025 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01002026
2027 #
2028 # Dump punt redirects for all interfaces
2029 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002030 punts = self.vapi.ip_punt_redirect_dump(0xFFFFFFFF)
Pavel Kotucek609e1212018-11-27 09:59:44 +01002031 self.assertEqual(len(punts), 3)
2032 for p in punts:
2033 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01002034 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002035 self.assertEqual(str(punts[2].punt.nh), "0.0.0.0")
Pavel Kotucek609e1212018-11-27 09:59:44 +01002036
Neale Rannsd91c1db2017-07-31 02:30:50 -07002037
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002038class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002039 """IPv4 Punt Policer thread handoff"""
2040
Klement Sekera8d815022021-03-15 16:58:10 +01002041 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002042
2043 def setUp(self):
2044 super(TestIPPuntHandoff, self).setUp()
2045 super(TestIPPuntHandoff, self).punt_setup()
2046
2047 def tearDown(self):
2048 super(TestIPPuntHandoff, self).punt_teardown()
2049 super(TestIPPuntHandoff, self).tearDown()
2050
2051 def test_ip_punt_policer_handoff(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002052 """IP4 punt policer thread handoff"""
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002053 pkts = self.pkt * NUM_PKTS
2054
2055 #
2056 # Configure a punt redirect via pg1.
2057 #
2058 nh_addr = self.pg1.remote_ip4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002059 ip_punt_redirect = VppIpPuntRedirect(
2060 self, self.pg0.sw_if_index, self.pg1.sw_if_index, nh_addr
2061 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002062 ip_punt_redirect.add_vpp_config()
2063
2064 action_tx = PolicerAction(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002065 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
2066 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002067 #
2068 # This policer drops no packets, we are just
2069 # testing that they get to the right thread.
2070 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002071 policer = VppPolicer(
2072 self,
2073 "ip4-punt",
2074 400,
2075 0,
2076 10,
2077 0,
2078 1,
2079 0,
2080 0,
2081 False,
2082 action_tx,
2083 action_tx,
2084 action_tx,
2085 )
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002086 policer.add_vpp_config()
2087 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
2088 ip_punt_policer.add_vpp_config()
2089
2090 for worker in [0, 1]:
2091 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00002092 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002093
Brian Russelle9887262021-01-27 14:45:22 +00002094 # Combined stats, all threads
2095 stats = policer.get_stats()
2096
2097 # Single rate policer - expect conform, violate but no exceed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002098 self.assertGreater(stats["conform_packets"], 0)
2099 self.assertEqual(stats["exceed_packets"], 0)
2100 self.assertGreater(stats["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002101
2102 # Worker 0, should have done all the policing
2103 stats0 = policer.get_stats(worker=0)
2104 self.assertEqual(stats, stats0)
2105
2106 # Worker 1, should have handed everything off
2107 stats1 = policer.get_stats(worker=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002108 self.assertEqual(stats1["conform_packets"], 0)
2109 self.assertEqual(stats1["exceed_packets"], 0)
2110 self.assertEqual(stats1["violate_packets"], 0)
Brian Russelle9887262021-01-27 14:45:22 +00002111
Brian Russellbb983142021-02-10 13:56:06 +00002112 # Bind the policer to worker 1 and repeat
2113 policer.bind_vpp_config(1, True)
2114 for worker in [0, 1]:
2115 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2116 self.logger.debug(self.vapi.cli("show trace max 100"))
2117
2118 # The 2 workers should now have policed the same amount
2119 stats = policer.get_stats()
2120 stats0 = policer.get_stats(worker=0)
2121 stats1 = policer.get_stats(worker=1)
2122
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002123 self.assertGreater(stats0["conform_packets"], 0)
2124 self.assertEqual(stats0["exceed_packets"], 0)
2125 self.assertGreater(stats0["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002126
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002127 self.assertGreater(stats1["conform_packets"], 0)
2128 self.assertEqual(stats1["exceed_packets"], 0)
2129 self.assertGreater(stats1["violate_packets"], 0)
Brian Russellbb983142021-02-10 13:56:06 +00002130
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002131 self.assertEqual(
2132 stats0["conform_packets"] + stats1["conform_packets"],
2133 stats["conform_packets"],
2134 )
Brian Russellbb983142021-02-10 13:56:06 +00002135
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002136 self.assertEqual(
2137 stats0["violate_packets"] + stats1["violate_packets"],
2138 stats["violate_packets"],
2139 )
Brian Russellbb983142021-02-10 13:56:06 +00002140
2141 # Unbind the policer and repeat
2142 policer.bind_vpp_config(1, False)
2143 for worker in [0, 1]:
2144 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
2145 self.logger.debug(self.vapi.cli("show trace max 100"))
2146
2147 # The policer should auto-bind to worker 0 when packets arrive
2148 stats = policer.get_stats()
2149 stats0new = policer.get_stats(worker=0)
2150 stats1new = policer.get_stats(worker=1)
2151
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002152 self.assertGreater(stats0new["conform_packets"], stats0["conform_packets"])
2153 self.assertEqual(stats0new["exceed_packets"], 0)
2154 self.assertGreater(stats0new["violate_packets"], stats0["violate_packets"])
Brian Russellbb983142021-02-10 13:56:06 +00002155
2156 self.assertEqual(stats1, stats1new)
2157
Brian Russellc8f3cdf2021-01-19 16:57:42 +00002158 #
2159 # Clean up
2160 #
2161 ip_punt_policer.remove_vpp_config()
2162 policer.remove_vpp_config()
2163 ip_punt_redirect.remove_vpp_config()
2164
2165
Neale Ranns054c03a2017-10-13 05:15:07 -07002166class TestIPDeag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002167 """IPv4 Deaggregate Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002168
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002169 @classmethod
2170 def setUpClass(cls):
2171 super(TestIPDeag, cls).setUpClass()
2172
2173 @classmethod
2174 def tearDownClass(cls):
2175 super(TestIPDeag, cls).tearDownClass()
2176
Neale Ranns054c03a2017-10-13 05:15:07 -07002177 def setUp(self):
2178 super(TestIPDeag, self).setUp()
2179
2180 self.create_pg_interfaces(range(3))
2181
2182 for i in self.pg_interfaces:
2183 i.admin_up()
2184 i.config_ip4()
2185 i.resolve_arp()
2186
2187 def tearDown(self):
2188 super(TestIPDeag, self).tearDown()
2189 for i in self.pg_interfaces:
2190 i.unconfig_ip4()
2191 i.admin_down()
2192
Neale Ranns054c03a2017-10-13 05:15:07 -07002193 def test_ip_deag(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002194 """IP Deag Routes"""
Neale Ranns054c03a2017-10-13 05:15:07 -07002195
2196 #
2197 # Create a table to be used for:
2198 # 1 - another destination address lookup
2199 # 2 - a source address lookup
2200 #
2201 table_dst = VppIpTable(self, 1)
2202 table_src = VppIpTable(self, 2)
2203 table_dst.add_vpp_config()
2204 table_src.add_vpp_config()
2205
2206 #
2207 # Add a route in the default table to point to a deag/
2208 # second lookup in each of these tables
2209 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002210 route_to_dst = VppIpRoute(
2211 self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)]
2212 )
Neale Ranns097fa662018-05-01 05:17:55 -07002213 route_to_src = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002214 self,
2215 "1.1.1.2",
2216 32,
2217 [
2218 VppRoutePath(
2219 "0.0.0.0",
2220 0xFFFFFFFF,
2221 nh_table_id=2,
2222 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP,
2223 )
2224 ],
2225 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002226 route_to_dst.add_vpp_config()
2227 route_to_src.add_vpp_config()
2228
2229 #
2230 # packets to these destination are dropped, since they'll
2231 # hit the respective default routes in the second table
2232 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002233 p_dst = (
2234 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2235 / IP(src="5.5.5.5", dst="1.1.1.1")
2236 / TCP(sport=1234, dport=1234)
2237 / Raw(b"\xa5" * 100)
2238 )
2239 p_src = (
2240 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2241 / IP(src="2.2.2.2", dst="1.1.1.2")
2242 / TCP(sport=1234, dport=1234)
2243 / Raw(b"\xa5" * 100)
2244 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002245 pkts_dst = p_dst * 257
2246 pkts_src = p_src * 257
2247
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002248 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in dst table")
2249 self.send_and_assert_no_replies(self.pg0, pkts_src, "IP in src table")
Neale Ranns054c03a2017-10-13 05:15:07 -07002250
2251 #
2252 # add a route in the dst table to forward via pg1
2253 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002254 route_in_dst = VppIpRoute(
2255 self,
2256 "1.1.1.1",
2257 32,
2258 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2259 table_id=1,
2260 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002261 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07002262
Neale Ranns054c03a2017-10-13 05:15:07 -07002263 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
2264
2265 #
2266 # add a route in the src table to forward via pg2
2267 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002268 route_in_src = VppIpRoute(
2269 self,
2270 "2.2.2.2",
2271 32,
2272 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2273 table_id=2,
2274 )
Neale Ranns054c03a2017-10-13 05:15:07 -07002275 route_in_src.add_vpp_config()
2276 self.send_and_expect(self.pg0, pkts_src, self.pg2)
2277
Neale Rannsce9e0b42018-08-01 12:53:17 -07002278 #
2279 # loop in the lookup DP
2280 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002281 route_loop = VppIpRoute(
2282 self, "2.2.2.3", 32, [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)]
2283 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002284 route_loop.add_vpp_config()
2285
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002286 p_l = (
2287 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2288 / IP(src="2.2.2.4", dst="2.2.2.3")
2289 / TCP(sport=1234, dport=1234)
2290 / Raw(b"\xa5" * 100)
2291 )
Neale Rannsce9e0b42018-08-01 12:53:17 -07002292
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002293 self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop")
Neale Rannsce9e0b42018-08-01 12:53:17 -07002294
Neale Ranns054c03a2017-10-13 05:15:07 -07002295
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002296class TestIPInput(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002297 """IPv4 Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002298
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002299 @classmethod
2300 def setUpClass(cls):
2301 super(TestIPInput, cls).setUpClass()
2302
2303 @classmethod
2304 def tearDownClass(cls):
2305 super(TestIPInput, cls).tearDownClass()
2306
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002307 def setUp(self):
2308 super(TestIPInput, self).setUp()
2309
2310 self.create_pg_interfaces(range(2))
2311
2312 for i in self.pg_interfaces:
2313 i.admin_up()
2314 i.config_ip4()
2315 i.resolve_arp()
2316
2317 def tearDown(self):
2318 super(TestIPInput, self).tearDown()
2319 for i in self.pg_interfaces:
2320 i.unconfig_ip4()
2321 i.admin_down()
2322
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002323 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002324 """IP Input Exceptions"""
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002325
2326 # i can't find a way in scapy to construct an IP packet
2327 # with a length less than the IP header length
2328
2329 #
2330 # Packet too short - this is forwarded
2331 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 p_short = (
2333 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2334 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=40)
2335 / UDP(sport=1234, dport=1234)
2336 / Raw(b"\xa5" * 100)
2337 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002338
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002339 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002340
2341 #
2342 # Packet too long - this is dropped
2343 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002344 p_long = (
2345 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2346 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, len=400)
2347 / UDP(sport=1234, dport=1234)
2348 / Raw(b"\xa5" * 100)
2349 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002350
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002351 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002352
2353 #
2354 # bad chksum - this is dropped
2355 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002356 p_chksum = (
2357 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2358 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, chksum=400)
2359 / UDP(sport=1234, dport=1234)
2360 / Raw(b"\xa5" * 100)
2361 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002362
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002363 rx = self.send_and_assert_no_replies(
2364 self.pg0, p_chksum * NUM_PKTS, "bad checksum"
2365 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002366
2367 #
2368 # bad version - this is dropped
2369 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002370 p_ver = (
2371 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2372 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, version=3)
2373 / UDP(sport=1234, dport=1234)
2374 / Raw(b"\xa5" * 100)
2375 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002376
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002377 rx = self.send_and_assert_no_replies(
2378 self.pg0, p_ver * NUM_PKTS, "funky version"
2379 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002380
2381 #
2382 # fragment offset 1 - this is dropped
2383 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002384 p_frag = (
2385 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2386 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, frag=1)
2387 / UDP(sport=1234, dport=1234)
2388 / Raw(b"\xa5" * 100)
2389 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002390
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002391 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset")
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002392
2393 #
2394 # TTL expired packet
2395 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002396 p_ttl = (
2397 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2398 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=1)
2399 / UDP(sport=1234, dport=1234)
2400 / Raw(b"\xa5" * 100)
2401 )
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002402
Neale Ranns5c6dd172022-02-17 09:08:47 +00002403 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002404
Neale Ranns5c6dd172022-02-17 09:08:47 +00002405 for rx in rxs:
2406 icmp = rx[ICMP]
2407 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002408 self.assertEqual(icmpcodes[icmp.type][icmp.code], "ttl-zero-during-transit")
Neale Ranns5c6dd172022-02-17 09:08:47 +00002409 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2410 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002411
Neale Rannsffd78d12018-02-09 06:05:16 -08002412 #
2413 # MTU exceeded
2414 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002415 p_mtu = (
2416 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2417 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=10, flags="DF")
2418 / UDP(sport=1234, dport=1234)
2419 / Raw(b"\xa5" * 2000)
2420 )
Neale Rannsffd78d12018-02-09 06:05:16 -08002421
Ole Troand7231612018-06-07 10:17:57 +02002422 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002423
Neale Ranns5c6dd172022-02-17 09:08:47 +00002424 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002425
Neale Ranns5c6dd172022-02-17 09:08:47 +00002426 for rx in rxs:
2427 icmp = rx[ICMP]
2428 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002429 self.assertEqual(icmpcodes[icmp.type][icmp.code], "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002430 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002431 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2432 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002433
Ole Troand7231612018-06-07 10:17:57 +02002434 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002435 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002436
Ole Troand7231612018-06-07 10:17:57 +02002437 # Reset MTU for subsequent tests
2438 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002439
Neale Rannsbe2286b2018-12-09 12:54:51 -08002440 #
2441 # source address 0.0.0.0 and 25.255.255.255 and for-us
2442 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002443 p_s0 = (
2444 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2445 / IP(src="0.0.0.0", dst=self.pg0.local_ip4)
2446 / ICMP(id=4, seq=4)
2447 / Raw(load=b"\x0a" * 18)
2448 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002449 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2450
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002451 p_s0 = (
2452 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2453 / IP(src="255.255.255.255", dst=self.pg0.local_ip4)
2454 / ICMP(id=4, seq=4)
2455 / Raw(load=b"\x0a" * 18)
2456 )
Neale Rannsbe2286b2018-12-09 12:54:51 -08002457 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2458
Neale Ranns1855b8e2018-07-11 10:31:26 -07002459
2460class TestIPDirectedBroadcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002461 """IPv4 Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002462
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002463 @classmethod
2464 def setUpClass(cls):
2465 super(TestIPDirectedBroadcast, cls).setUpClass()
2466
2467 @classmethod
2468 def tearDownClass(cls):
2469 super(TestIPDirectedBroadcast, cls).tearDownClass()
2470
Neale Ranns1855b8e2018-07-11 10:31:26 -07002471 def setUp(self):
2472 super(TestIPDirectedBroadcast, self).setUp()
2473
2474 self.create_pg_interfaces(range(2))
2475
2476 for i in self.pg_interfaces:
2477 i.admin_up()
2478
2479 def tearDown(self):
2480 super(TestIPDirectedBroadcast, self).tearDown()
2481 for i in self.pg_interfaces:
2482 i.admin_down()
2483
2484 def test_ip_input(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002485 """IP Directed Broadcast"""
Neale Ranns1855b8e2018-07-11 10:31:26 -07002486
2487 #
2488 # set the directed broadcast on pg0 first, then config IP4 addresses
2489 # for pg1 directed broadcast is always disabled
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002490 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002491
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002492 p0 = (
2493 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
2494 / IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast)
2495 / UDP(sport=1234, dport=1234)
2496 / Raw(b"\xa5" * 2000)
2497 )
2498 p1 = (
2499 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2500 / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast)
2501 / UDP(sport=1234, dport=1234)
2502 / Raw(b"\xa5" * 2000)
2503 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002504
2505 self.pg0.config_ip4()
2506 self.pg0.resolve_arp()
2507 self.pg1.config_ip4()
2508 self.pg1.resolve_arp()
2509
2510 #
2511 # test packet is L2 broadcast
2512 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002513 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002514 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2515
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002516 self.send_and_assert_no_replies(
2517 self.pg0, p1 * NUM_PKTS, "directed broadcast disabled"
2518 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002519
2520 #
2521 # toggle directed broadcast on pg0
2522 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002523 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 0)
2524 self.send_and_assert_no_replies(
2525 self.pg1, p0 * NUM_PKTS, "directed broadcast disabled"
2526 )
Neale Ranns1855b8e2018-07-11 10:31:26 -07002527
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002528 self.vapi.sw_interface_set_ip_directed_broadcast(self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002529 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002530
2531 self.pg0.unconfig_ip4()
2532 self.pg1.unconfig_ip4()
2533
2534
mu.duojiao59a82952018-10-11 14:27:30 +08002535class TestIPLPM(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002536 """IPv4 longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002537
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002538 @classmethod
2539 def setUpClass(cls):
2540 super(TestIPLPM, cls).setUpClass()
2541
2542 @classmethod
2543 def tearDownClass(cls):
2544 super(TestIPLPM, cls).tearDownClass()
2545
mu.duojiao59a82952018-10-11 14:27:30 +08002546 def setUp(self):
2547 super(TestIPLPM, self).setUp()
2548
2549 self.create_pg_interfaces(range(4))
2550
2551 for i in self.pg_interfaces:
2552 i.admin_up()
2553 i.config_ip4()
2554 i.resolve_arp()
2555
2556 def tearDown(self):
2557 super(TestIPLPM, self).tearDown()
2558 for i in self.pg_interfaces:
2559 i.admin_down()
2560 i.unconfig_ip4()
2561
2562 def test_ip_lpm(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002563 """IP longest Prefix Match"""
mu.duojiao59a82952018-10-11 14:27:30 +08002564
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002565 s_24 = VppIpRoute(
2566 self,
2567 "10.1.2.0",
2568 24,
2569 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
2570 )
mu.duojiao59a82952018-10-11 14:27:30 +08002571 s_24.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002572 s_8 = VppIpRoute(
2573 self,
2574 "10.0.0.0",
2575 8,
2576 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
2577 )
mu.duojiao59a82952018-10-11 14:27:30 +08002578 s_8.add_vpp_config()
2579
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002580 p_8 = (
2581 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2582 / IP(src="1.1.1.1", dst="10.1.1.1")
2583 / UDP(sport=1234, dport=1234)
2584 / Raw(b"\xa5" * 2000)
2585 )
2586 p_24 = (
2587 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2588 / IP(src="1.1.1.1", dst="10.1.2.1")
2589 / UDP(sport=1234, dport=1234)
2590 / Raw(b"\xa5" * 2000)
2591 )
mu.duojiao59a82952018-10-11 14:27:30 +08002592
2593 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002594 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2595 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002596
2597
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002598@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002599class TestIPv4Frag(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002600 """IPv4 fragmentation"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002601
2602 @classmethod
2603 def setUpClass(cls):
2604 super(TestIPv4Frag, cls).setUpClass()
2605
2606 cls.create_pg_interfaces([0, 1])
2607 cls.src_if = cls.pg0
2608 cls.dst_if = cls.pg1
2609
2610 # setup all interfaces
2611 for i in cls.pg_interfaces:
2612 i.admin_up()
2613 i.config_ip4()
2614 i.resolve_arp()
2615
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002616 @classmethod
2617 def tearDownClass(cls):
2618 super(TestIPv4Frag, cls).tearDownClass()
2619
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002620 def test_frag_large_packets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002621 """Fragmentation of large packets"""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002622
Neale Ranns0b6a8572019-10-30 17:34:14 +00002623 self.vapi.cli("adjacency counters enable")
2624
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002625 p = (
2626 Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac)
2627 / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4)
2628 / UDP(sport=1234, dport=5678)
2629 / Raw()
2630 )
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002631 self.extend_packet(p, 6000, "abcde")
2632 saved_payload = p[Raw].load
2633
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002634 nbr = VppNeighbor(
2635 self,
2636 self.dst_if.sw_if_index,
2637 self.dst_if.remote_mac,
2638 self.dst_if.remote_ip4,
2639 ).add_vpp_config()
Neale Ranns0b6a8572019-10-30 17:34:14 +00002640
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002641 # Force fragmentation by setting MTU of output interface
2642 # lower than packet size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002643 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, [5000, 0, 0, 0])
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002644
2645 self.pg_enable_capture()
2646 self.src_if.add_stream(p)
2647 self.pg_start()
2648
2649 # Expecting 3 fragments because size of created fragments currently
2650 # cannot be larger then VPP buffer size (which is 2048)
2651 packets = self.dst_if.get_capture(3)
2652
Neale Ranns0b6a8572019-10-30 17:34:14 +00002653 # we should show 3 packets thru the neighbor
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002654 self.assertEqual(3, nbr.get_stats()["packets"])
Neale Ranns0b6a8572019-10-30 17:34:14 +00002655
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002656 # Assume VPP sends the fragments in order
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002657 payload = b""
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002658 for p in packets:
2659 payload_offset = p.frag * 8
2660 if payload_offset > 0:
2661 payload_offset -= 8 # UDP header is not in payload
2662 self.assert_equal(payload_offset, len(payload))
2663 payload += p[Raw].load
2664 self.assert_equal(payload, saved_payload, "payload")
2665
2666
Neale Ranns9db6ada2019-11-08 12:42:31 +00002667class TestIPReplace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002668 """IPv4 Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002669
2670 @classmethod
2671 def setUpClass(cls):
2672 super(TestIPReplace, cls).setUpClass()
2673
2674 @classmethod
2675 def tearDownClass(cls):
2676 super(TestIPReplace, cls).tearDownClass()
2677
2678 def setUp(self):
2679 super(TestIPReplace, self).setUp()
2680
2681 self.create_pg_interfaces(range(4))
2682
2683 table_id = 1
2684 self.tables = []
2685
2686 for i in self.pg_interfaces:
2687 i.admin_up()
2688 i.config_ip4()
2689 i.resolve_arp()
2690 i.generate_remote_hosts(2)
2691 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2692 table_id += 1
2693
2694 def tearDown(self):
2695 super(TestIPReplace, self).tearDown()
2696 for i in self.pg_interfaces:
2697 i.admin_down()
2698 i.unconfig_ip4()
2699
2700 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002701 """IP Table Replace"""
Neale Ranns9db6ada2019-11-08 12:42:31 +00002702
Neale Ranns990f6942020-10-20 07:20:17 +00002703 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2704 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002705 N_ROUTES = 20
2706 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2707 routes = [[], [], [], []]
2708
2709 # load up the tables with some routes
2710 for ii, t in enumerate(self.tables):
2711 for jj in range(N_ROUTES):
2712 uni = VppIpRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002713 self,
2714 "10.0.0.%d" % jj,
2715 32,
2716 [
2717 VppRoutePath(
2718 links[ii].remote_hosts[0].ip4, links[ii].sw_if_index
2719 ),
2720 VppRoutePath(
2721 links[ii].remote_hosts[1].ip4, links[ii].sw_if_index
2722 ),
2723 ],
2724 table_id=t.table_id,
2725 ).add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002726 multi = VppIpMRoute(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002727 self,
2728 "0.0.0.0",
2729 "239.0.0.%d" % jj,
2730 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002731 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002732 [
2733 VppMRoutePath(
2734 self.pg0.sw_if_index,
2735 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
2736 ),
2737 VppMRoutePath(
2738 self.pg1.sw_if_index,
2739 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2740 ),
2741 VppMRoutePath(
2742 self.pg2.sw_if_index,
2743 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2744 ),
2745 VppMRoutePath(
2746 self.pg3.sw_if_index,
2747 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
2748 ),
2749 ],
2750 table_id=t.table_id,
2751 ).add_vpp_config()
2752 routes[ii].append({"uni": uni, "multi": multi})
Neale Ranns9db6ada2019-11-08 12:42:31 +00002753
2754 #
2755 # replace the tables a few times
2756 #
2757 for kk in range(3):
2758 # replace_begin each table
2759 for t in self.tables:
2760 t.replace_begin()
2761
2762 # all the routes are still there
2763 for ii, t in enumerate(self.tables):
2764 dump = t.dump()
2765 mdump = t.mdump()
2766 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002767 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2768 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002769
2770 # redownload the even numbered routes
2771 for ii, t in enumerate(self.tables):
2772 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002773 routes[ii][jj]["uni"].add_vpp_config()
2774 routes[ii][jj]["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002775
2776 # signal each table replace_end
2777 for t in self.tables:
2778 t.replace_end()
2779
2780 # we should find the even routes, but not the odd
2781 for ii, t in enumerate(self.tables):
2782 dump = t.dump()
2783 mdump = t.mdump()
2784 for jj in range(0, N_ROUTES, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002785 self.assertTrue(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2786 self.assertTrue(
2787 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2788 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002789 for jj in range(1, N_ROUTES - 1, 2):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002790 self.assertFalse(find_route_in_dump(dump, routes[ii][jj]["uni"], t))
2791 self.assertFalse(
2792 find_mroute_in_dump(mdump, routes[ii][jj]["multi"], t)
2793 )
Neale Ranns9db6ada2019-11-08 12:42:31 +00002794
2795 # reload all the routes
2796 for ii, t in enumerate(self.tables):
2797 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002798 r["uni"].add_vpp_config()
2799 r["multi"].add_vpp_config()
Neale Ranns9db6ada2019-11-08 12:42:31 +00002800
2801 # all the routes are still there
2802 for ii, t in enumerate(self.tables):
2803 dump = t.dump()
2804 mdump = t.mdump()
2805 for r in routes[ii]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002806 self.assertTrue(find_route_in_dump(dump, r["uni"], t))
2807 self.assertTrue(find_mroute_in_dump(mdump, r["multi"], t))
Neale Ranns9db6ada2019-11-08 12:42:31 +00002808
2809 #
2810 # finally flush the tables for good measure
2811 #
2812 for t in self.tables:
2813 t.flush()
2814 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002815 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002816
2817
Neale Ranns9efcee62019-11-26 19:30:08 +00002818class TestIPCover(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002819 """IPv4 Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002820
2821 @classmethod
2822 def setUpClass(cls):
2823 super(TestIPCover, cls).setUpClass()
2824
2825 @classmethod
2826 def tearDownClass(cls):
2827 super(TestIPCover, cls).tearDownClass()
2828
2829 def setUp(self):
2830 super(TestIPCover, self).setUp()
2831
2832 self.create_pg_interfaces(range(4))
2833
2834 table_id = 1
2835 self.tables = []
2836
2837 for i in self.pg_interfaces:
2838 i.admin_up()
2839 i.config_ip4()
2840 i.resolve_arp()
2841 i.generate_remote_hosts(2)
2842 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2843 table_id += 1
2844
2845 def tearDown(self):
2846 super(TestIPCover, self).tearDown()
2847 for i in self.pg_interfaces:
2848 i.admin_down()
2849 i.unconfig_ip4()
2850
2851 def test_cover(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002852 """IP Table Cover"""
Neale Ranns9efcee62019-11-26 19:30:08 +00002853
2854 # add a loop back with a /32 prefix
2855 lo = VppLoInterface(self)
2856 lo.admin_up()
2857 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2858
2859 # add a neighbour that matches the loopback's /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002860 nbr = VppNeighbor(
2861 self, lo.sw_if_index, lo.remote_mac, "127.0.0.1"
2862 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002863
2864 # add the default route which will be the cover for /32
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002865 r = VppIpRoute(
2866 self,
2867 "0.0.0.0",
2868 0,
2869 [VppRoutePath("127.0.0.1", lo.sw_if_index)],
2870 register=False,
2871 ).add_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002872
2873 # add/remove/add a longer mask cover
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002874 r8 = VppIpRoute(
2875 self, "127.0.0.0", 8, [VppRoutePath("127.0.0.1", lo.sw_if_index)]
2876 ).add_vpp_config()
Neale Ranns87866032020-11-25 09:14:22 +00002877 r8.remove_vpp_config()
2878 r8.add_vpp_config()
2879 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002880
2881 # remove the default route
2882 r.remove_vpp_config()
2883
Neale Ranns87866032020-11-25 09:14:22 +00002884 # remove the interface prefix
2885 a.remove_vpp_config()
2886
Neale Ranns59f71132020-04-08 12:19:38 +00002887
2888class TestIP4Replace(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002889 """IPv4 Interface Address Replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002890
2891 @classmethod
2892 def setUpClass(cls):
2893 super(TestIP4Replace, cls).setUpClass()
2894
2895 @classmethod
2896 def tearDownClass(cls):
2897 super(TestIP4Replace, cls).tearDownClass()
2898
2899 def setUp(self):
2900 super(TestIP4Replace, self).setUp()
2901
2902 self.create_pg_interfaces(range(4))
2903
2904 for i in self.pg_interfaces:
2905 i.admin_up()
2906
2907 def tearDown(self):
2908 super(TestIP4Replace, self).tearDown()
2909 for i in self.pg_interfaces:
2910 i.admin_down()
2911
2912 def get_n_pfxs(self, intf):
2913 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2914
2915 def test_replace(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002916 """IP interface address replace"""
Neale Ranns59f71132020-04-08 12:19:38 +00002917
2918 intf_pfxs = [[], [], [], []]
2919
2920 # add prefixes to each of the interfaces
2921 for i in range(len(self.pg_interfaces)):
2922 intf = self.pg_interfaces[i]
2923
2924 # 172.16.x.1/24
2925 addr = "172.16.%d.1" % intf.sw_if_index
2926 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2927 intf_pfxs[i].append(a)
2928
2929 # 172.16.x.2/24 - a different address in the same subnet as above
2930 addr = "172.16.%d.2" % intf.sw_if_index
2931 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2932 intf_pfxs[i].append(a)
2933
2934 # 172.15.x.2/24 - a different address and subnet
2935 addr = "172.15.%d.2" % intf.sw_if_index
2936 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2937 intf_pfxs[i].append(a)
2938
2939 # a dump should n_address in it
2940 for intf in self.pg_interfaces:
2941 self.assertEqual(self.get_n_pfxs(intf), 3)
2942
2943 #
2944 # remove all the address thru a replace
2945 #
2946 self.vapi.sw_interface_address_replace_begin()
2947 self.vapi.sw_interface_address_replace_end()
2948 for intf in self.pg_interfaces:
2949 self.assertEqual(self.get_n_pfxs(intf), 0)
2950
2951 #
2952 # add all the interface addresses back
2953 #
2954 for p in intf_pfxs:
2955 for v in p:
2956 v.add_vpp_config()
2957 for intf in self.pg_interfaces:
2958 self.assertEqual(self.get_n_pfxs(intf), 3)
2959
2960 #
2961 # replace again, but this time update/re-add the address on the first
2962 # two interfaces
2963 #
2964 self.vapi.sw_interface_address_replace_begin()
2965
2966 for p in intf_pfxs[:2]:
2967 for v in p:
2968 v.add_vpp_config()
2969
2970 self.vapi.sw_interface_address_replace_end()
2971
2972 # on the first two the address still exist,
2973 # on the other two they do not
2974 for intf in self.pg_interfaces[:2]:
2975 self.assertEqual(self.get_n_pfxs(intf), 3)
2976 for p in intf_pfxs[:2]:
2977 for v in p:
2978 self.assertTrue(v.query_vpp_config())
2979 for intf in self.pg_interfaces[2:]:
2980 self.assertEqual(self.get_n_pfxs(intf), 0)
2981
2982 #
2983 # add all the interface addresses back on the last two
2984 #
2985 for p in intf_pfxs[2:]:
2986 for v in p:
2987 v.add_vpp_config()
2988 for intf in self.pg_interfaces:
2989 self.assertEqual(self.get_n_pfxs(intf), 3)
2990
2991 #
2992 # replace again, this time add different prefixes on all the interfaces
2993 #
2994 self.vapi.sw_interface_address_replace_begin()
2995
2996 pfxs = []
2997 for intf in self.pg_interfaces:
2998 # 172.18.x.1/24
2999 addr = "172.18.%d.1" % intf.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003000 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00003001
3002 self.vapi.sw_interface_address_replace_end()
3003
3004 # only .18 should exist on each interface
3005 for intf in self.pg_interfaces:
3006 self.assertEqual(self.get_n_pfxs(intf), 1)
3007 for pfx in pfxs:
3008 self.assertTrue(pfx.query_vpp_config())
3009
3010 #
3011 # remove everything
3012 #
3013 self.vapi.sw_interface_address_replace_begin()
3014 self.vapi.sw_interface_address_replace_end()
3015 for intf in self.pg_interfaces:
3016 self.assertEqual(self.get_n_pfxs(intf), 0)
3017
3018 #
3019 # add prefixes to each interface. post-begin add the prefix from
3020 # interface X onto interface Y. this would normally be an error
3021 # since it would generate a 'duplicate address' warning. but in
3022 # this case, since what is newly downloaded is sane, it's ok
3023 #
3024 for intf in self.pg_interfaces:
3025 # 172.18.x.1/24
3026 addr = "172.18.%d.1" % intf.sw_if_index
3027 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
3028
3029 self.vapi.sw_interface_address_replace_begin()
3030
3031 pfxs = []
3032 for intf in self.pg_interfaces:
3033 # 172.18.x.1/24
3034 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003035 pfxs.append(VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config())
Neale Ranns59f71132020-04-08 12:19:38 +00003036
3037 self.vapi.sw_interface_address_replace_end()
3038
3039 self.logger.info(self.vapi.cli("sh int addr"))
3040
3041 for intf in self.pg_interfaces:
3042 self.assertEqual(self.get_n_pfxs(intf), 1)
3043 for pfx in pfxs:
3044 self.assertTrue(pfx.query_vpp_config())
3045
3046
Neale Ranns8f5fef22020-12-21 08:29:34 +00003047class TestIPv4PathMTU(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003048 """IPv4 Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00003049
3050 @classmethod
3051 def setUpClass(cls):
3052 super(TestIPv4PathMTU, cls).setUpClass()
3053
3054 cls.create_pg_interfaces(range(2))
3055
3056 # setup all interfaces
3057 for i in cls.pg_interfaces:
3058 i.admin_up()
3059 i.config_ip4()
3060 i.resolve_arp()
3061
3062 @classmethod
3063 def tearDownClass(cls):
3064 super(TestIPv4PathMTU, cls).tearDownClass()
3065
3066 def test_path_mtu(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003067 """Path MTU"""
Neale Ranns8f5fef22020-12-21 08:29:34 +00003068
3069 #
3070 # The goal here is not to test that fragmentation works correctly,
3071 # that's done elsewhere, the intent is to ensure that the Path MTU
3072 # settings are honoured.
3073 #
3074 self.vapi.cli("adjacency counters enable")
3075
3076 # set the interface MTU to a reasonable value
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003077 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003078
3079 self.pg1.generate_remote_hosts(4)
3080
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003081 p_2k = (
3082 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3083 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3084 / UDP(sport=1234, dport=5678)
3085 / Raw(b"0xa" * 640)
3086 )
3087 p_1k = (
3088 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3089 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3090 / UDP(sport=1234, dport=5678)
3091 / Raw(b"0xa" * 320)
3092 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003093
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003094 nbr = VppNeighbor(
3095 self, self.pg1.sw_if_index, self.pg1.remote_mac, self.pg1.remote_ip4
3096 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003097
3098 # this is now the interface MTU frags
3099 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3100 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3101
3102 # drop the path MTU for this neighbour to below the interface MTU
3103 # expect more frags
3104 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
3105
3106 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3107 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3108
3109 # print/format the adj delegate
3110 self.logger.info(self.vapi.cli("sh adj 5"))
3111
3112 # increase the path MTU to more than the interface
3113 # expect to use the interface MTU
3114 pmtu.modify(8192)
3115
3116 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3117 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3118
3119 # go back to an MTU from the path
3120 # wrap the call around mark-n-sweep to enusre updates clear stale
3121 self.vapi.ip_path_mtu_replace_begin()
3122 pmtu.modify(900)
3123 self.vapi.ip_path_mtu_replace_end()
3124
3125 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3126 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3127
3128 # raise the interface's MTU
3129 # should still use that of the path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003130 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2000, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003131 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3132 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3133
3134 # set path high and interface low
3135 pmtu.modify(2000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003136 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [900, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003137 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3138 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3139
3140 # remove the path MTU using the mark-n-sweep semantics
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003141 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1800, 0, 0, 0])
Neale Ranns8f5fef22020-12-21 08:29:34 +00003142 self.vapi.ip_path_mtu_replace_begin()
3143 self.vapi.ip_path_mtu_replace_end()
3144
3145 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
3146 self.send_and_expect(self.pg0, [p_1k], self.pg1)
3147
3148 #
3149 # set path MTU for a neighbour that doesn't exist, yet
3150 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003151 pmtu2 = VppIpPathMtu(self, self.pg1.remote_hosts[2].ip4, 900).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003152
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003153 p_2k = (
3154 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3155 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3156 / UDP(sport=1234, dport=5678)
3157 / Raw(b"0xa" * 640)
3158 )
3159 p_1k = (
3160 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3161 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4)
3162 / UDP(sport=1234, dport=5678)
3163 / Raw(b"0xa" * 320)
3164 )
Neale Ranns8f5fef22020-12-21 08:29:34 +00003165
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003166 nbr2 = VppNeighbor(
3167 self,
3168 self.pg1.sw_if_index,
3169 self.pg1.remote_hosts[2].mac,
3170 self.pg1.remote_hosts[2].ip4,
3171 ).add_vpp_config()
Neale Ranns8f5fef22020-12-21 08:29:34 +00003172
3173 # should frag to the path MTU
3174 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3175 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3176
3177 # remove and re-add the neighbour
3178 nbr2.remove_vpp_config()
3179 nbr2.add_vpp_config()
3180
3181 # should frag to the path MTU
3182 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3183 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3184
3185 #
3186 # set PMTUs for many peers
3187 #
3188 N_HOSTS = 16
3189 self.pg1.generate_remote_hosts(16)
3190 self.pg1.configure_ipv4_neighbors()
3191
3192 for h in range(N_HOSTS):
3193 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
3194 pmtu.add_vpp_config()
3195 self.assertTrue(pmtu.query_vpp_config())
3196
3197 self.logger.info(self.vapi.cli("sh ip pmtu"))
3198 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
3199 self.assertEqual(N_HOSTS, len(dump))
3200
3201 for h in range(N_HOSTS):
3202 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
3203 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
3204
3205 # should frag to the path MTU
3206 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
3207 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
3208
3209
Neale Ranns50bd1d32021-10-08 07:16:12 +00003210class TestIPv4ItfRebind(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003211 """IPv4 Interface Bind w/ attached routes"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003212
3213 def setUp(self):
3214 super(TestIPv4ItfRebind, self).setUp()
3215
3216 self.create_pg_interfaces(range(3))
3217
3218 def tearDown(self):
3219 super(TestIPv4ItfRebind, self).tearDown()
3220
3221 def test_rebind(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003222 """Import to no import"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003223
3224 TABLE_ID = 1
3225 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
3226 self.pg1.set_table_ip4(TABLE_ID)
3227
3228 for i in self.pg_interfaces:
3229 i.admin_up()
3230 i.config_ip4()
3231 i.resolve_arp()
3232
3233 # add an attached route via an pg0
3234 # in a different table. this prefix should import
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003235 rt = VppIpRoute(
3236 self,
3237 self.pg0.local_ip4,
3238 24,
3239 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
3240 table_id=TABLE_ID,
3241 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003242
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003243 p = (
3244 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3245 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3246 / UDP(sport=1234, dport=5678)
3247 / Raw(b"0xa" * 640)
3248 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003249
3250 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3251 self.assertFalse(rx[0].haslayer(ARP))
3252
3253 # then bind pg0 to a new table
3254 # so the prefix no longer imports
3255 self.pg0.unconfig_ip4()
3256 self.pg0.set_table_ip4(TABLE_ID)
3257 self.pg0.config_ip4()
3258 self.pg0.resolve_arp()
3259
3260 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3261 self.assertFalse(rx[0].haslayer(ARP))
3262
3263 # revert back to imported
3264 self.pg0.unconfig_ip4()
3265 self.pg0.set_table_ip4(0)
3266 self.pg0.config_ip4()
3267 self.pg0.resolve_arp()
3268
3269 rx = self.send_and_expect(self.pg1, [p], self.pg0)
3270 self.assertFalse(rx[0].haslayer(ARP))
3271
3272 # cleanup
3273 for i in self.pg_interfaces:
3274 i.unconfig_ip4()
3275 i.set_table_ip4(0)
3276 i.admin_down()
3277
3278 rt.remove_vpp_config()
3279 tbl.remove_vpp_config()
3280
3281 def test_delete(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003282 """Swap import tables"""
Neale Ranns50bd1d32021-10-08 07:16:12 +00003283
3284 TABLE_ID1 = 1
3285 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
3286 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
3287 TABLE_ID2 = 2
3288 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
3289 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
3290
3291 # table mappings
3292 self.pg1.set_table_ip4(TABLE_ID1)
3293 self.pg1.set_table_ip6(TABLE_ID1)
3294 self.pg2.set_table_ip4(TABLE_ID2)
3295 self.pg2.set_table_ip6(TABLE_ID2)
3296
3297 for i in self.pg_interfaces:
3298 i.admin_up()
3299 i.config_ip4()
3300 i.resolve_arp()
3301
3302 # add an attached route in the default table via pg0
3303 # this should import to table 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003304 rt4 = VppIpRoute(
3305 self,
3306 self.pg1.local_ip4,
3307 24,
3308 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3309 ).add_vpp_config()
3310 rt6 = VppIpRoute(
3311 self,
3312 self.pg1.local_ip6,
3313 64,
3314 [VppRoutePath("0.0.0.0", self.pg1.sw_if_index)],
3315 ).add_vpp_config()
Neale Ranns50bd1d32021-10-08 07:16:12 +00003316
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003317 p1 = (
3318 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3319 / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
3320 / UDP(sport=1234, dport=5678)
3321 / Raw(b"0xa" * 640)
3322 )
Neale Ranns50bd1d32021-10-08 07:16:12 +00003323
3324 # inject into table 0
3325 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3326 self.assertFalse(rx[0].haslayer(ARP))
3327
3328 # swap the attached interface to table 2
3329 self.pg1.unconfig_ip4()
3330 self.pg1.unconfig_ip6()
3331 self.pg1.set_table_ip4(TABLE_ID2)
3332 self.pg1.set_table_ip6(TABLE_ID2)
3333 self.pg1.config_ip4()
3334 self.pg1.config_ip6()
3335 self.pg1.resolve_arp()
3336
3337 # delete table 1
3338 tbl1_4.flush()
3339 tbl1_6.flush()
3340 tbl1_4.remove_vpp_config()
3341 tbl1_6.remove_vpp_config()
3342
3343 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3344 self.assertFalse(rx[0].haslayer(ARP))
3345
3346 for i in self.pg_interfaces:
3347 i.unconfig_ip4()
3348 i.unconfig_ip6()
3349 i.set_table_ip4(0)
3350 i.set_table_ip6(0)
3351 i.admin_down()
3352
3353
Vladislav Grishenkodea806d2024-02-20 11:58:01 +05003354class TestIP4InterfaceRx(VppTestCase):
3355 """IPv4 Interface Receive"""
3356
3357 @classmethod
3358 def setUpClass(cls):
3359 super(TestIP4InterfaceRx, cls).setUpClass()
3360
3361 @classmethod
3362 def tearDownClass(cls):
3363 super(TestIP4InterfaceRx, cls).tearDownClass()
3364
3365 def setUp(self):
3366 super(TestIP4InterfaceRx, self).setUp()
3367
3368 self.create_pg_interfaces(range(3))
3369
3370 table_id = 0
3371
3372 for i in self.pg_interfaces:
3373 i.admin_up()
3374
3375 if table_id != 0:
3376 table = VppIpTable(self, table_id)
3377 table.add_vpp_config()
3378
3379 i.set_table_ip4(table_id)
3380 i.config_ip4()
3381 i.resolve_arp()
3382 table_id += 1
3383
3384 def tearDown(self):
3385 for i in self.pg_interfaces:
3386 i.unconfig_ip4()
3387 i.admin_down()
3388 i.set_table_ip4(0)
3389
3390 super(TestIP4InterfaceRx, self).tearDown()
3391
3392 def test_interface_rx(self):
3393 """IPv4 Interface Receive"""
3394
3395 #
3396 # add a route in the default table to receive ...
3397 #
3398 route_to_dst = VppIpRoute(
3399 self,
3400 "1.1.1.0",
3401 24,
3402 [
3403 VppRoutePath(
3404 "0.0.0.0",
3405 self.pg1.sw_if_index,
3406 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
3407 )
3408 ],
3409 )
3410 route_to_dst.add_vpp_config()
3411
3412 #
3413 # packets to these destination are dropped, since they'll
3414 # hit the respective default routes in table 1
3415 #
3416 p_dst = (
3417 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3418 / IP(src="5.5.5.5", dst="1.1.1.1")
3419 / TCP(sport=1234, dport=1234)
3420 / Raw(b"\xa5" * 100)
3421 )
3422 pkts_dst = p_dst * 10
3423
3424 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in table 1")
3425
3426 #
3427 # add a route in the dst table to forward via pg1
3428 #
3429 route_in_dst = VppIpRoute(
3430 self,
3431 "1.1.1.1",
3432 32,
3433 [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
3434 table_id=1,
3435 )
3436 route_in_dst.add_vpp_config()
3437
3438 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
3439
3440 #
3441 # add a route in the default table to receive ...
3442 #
3443 route_to_dst = VppIpRoute(
3444 self,
3445 "1.1.1.0",
3446 24,
3447 [
3448 VppRoutePath(
3449 "0.0.0.0",
3450 self.pg2.sw_if_index,
3451 type=FibPathType.FIB_PATH_TYPE_INTERFACE_RX,
3452 )
3453 ],
3454 table_id=1,
3455 )
3456 route_to_dst.add_vpp_config()
3457
3458 #
3459 # packets to these destination are dropped, since they'll
3460 # hit the respective default routes in table 2
3461 #
3462 p_dst = (
3463 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3464 / IP(src="6.6.6.6", dst="1.1.1.2")
3465 / TCP(sport=1234, dport=1234)
3466 / Raw(b"\xa5" * 100)
3467 )
3468 pkts_dst = p_dst * 10
3469
3470 self.send_and_assert_no_replies(self.pg0, pkts_dst, "IP in table 2")
3471
3472 #
3473 # add a route in the table 2 to forward via pg2
3474 #
3475 route_in_dst = VppIpRoute(
3476 self,
3477 "1.1.1.2",
3478 32,
3479 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
3480 table_id=2,
3481 )
3482 route_in_dst.add_vpp_config()
3483
3484 self.send_and_expect(self.pg0, pkts_dst, self.pg2)
3485
3486
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003487if __name__ == "__main__":
Klement Sekeraf62ae122016-10-11 11:47:09 +02003488 unittest.main(testRunner=VppTestRunner)