blob: 3a48274691a871a64845322512203509e6739bb8 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08002import binascii
Matej Klotton16a14cd2016-12-07 15:09:13 +01003import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02004import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01005import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02006
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07007import scapy.compat
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08008from scapy.contrib.mpls import MPLS
9from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
Neale Rannsaa7cfd02022-03-24 12:28:42 +000010from scapy.layers.inet6 import IPv6
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080011from scapy.layers.l2 import Ether, Dot1Q, ARP
12from scapy.packet import Raw
13from six import moves
14
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000015from framework import tag_fixme_vpp_workers
Damjan Marionf56b77a2016-10-03 19:44:57 +020016from framework import VppTestCase, VppTestRunner
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080017from util import ppp
Neale Ranns180279b2017-03-16 15:49:09 -040018from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
Neale Ranns990f6942020-10-20 07:20:17 +000019 VppMRoutePath, VppMplsIpBind, \
Matthew Smith6c92f5b2019-08-07 11:46:30 -050020 VppMplsTable, VppIpTable, FibPathType, find_route, \
Neale Ranns9db6ada2019-11-08 12:42:31 +000021 VppIpInterfaceAddress, find_route_in_dump, find_mroute_in_dump
Neale Ranns8f5fef22020-12-21 08:29:34 +000022from vpp_ip import VppIpPuntPolicer, VppIpPuntRedirect, VppIpPathMtu
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080023from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Klement Sekerafd1f56a2021-11-22 21:25:57 +010024from vpp_papi import vpp_papi, VppEnum
Neale Ranns0b6a8572019-10-30 17:34:14 +000025from vpp_neighbor import VppNeighbor
Neale Ranns9efcee62019-11-26 19:30:08 +000026from vpp_lo_interface import VppLoInterface
Brian Russellc8f3cdf2021-01-19 16:57:42 +000027from vpp_policer import VppPolicer, PolicerAction
Damjan Marionf56b77a2016-10-03 19:44:57 +020028
Paul Vinciguerra4271c972019-05-14 13:25:49 -040029NUM_PKTS = 67
30
Damjan Marionf56b77a2016-10-03 19:44:57 +020031
Klement Sekeraf62ae122016-10-11 11:47:09 +020032class TestIPv4(VppTestCase):
Damjan Marionf56b77a2016-10-03 19:44:57 +020033 """ IPv4 Test Case """
34
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070035 @classmethod
36 def setUpClass(cls):
37 super(TestIPv4, cls).setUpClass()
38
39 @classmethod
40 def tearDownClass(cls):
41 super(TestIPv4, cls).tearDownClass()
42
Klement Sekeraf62ae122016-10-11 11:47:09 +020043 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010044 """
45 Perform test setup before test case.
46
47 **Config:**
48 - create 3 pg interfaces
49 - untagged pg0 interface
50 - Dot1Q subinterface on pg1
51 - Dot1AD subinterface on pg2
52 - setup interfaces:
53 - put it into UP state
54 - set IPv4 addresses
55 - resolve neighbor address using ARP
56 - configure 200 fib entries
57
58 :ivar list interfaces: pg interfaces and subinterfaces.
59 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010060 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020061 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020062
Klement Sekeraf62ae122016-10-11 11:47:09 +020063 # create 3 pg interfaces
64 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020065
Klement Sekeraf62ae122016-10-11 11:47:09 +020066 # create 2 subinterfaces for pg1 and pg2
67 self.sub_interfaces = [
68 VppDot1QSubint(self, self.pg1, 100),
69 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
Damjan Marionf56b77a2016-10-03 19:44:57 +020070
Klement Sekeraf62ae122016-10-11 11:47:09 +020071 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
72 self.flows = dict()
73 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
74 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
75 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020076
Klement Sekeraf62ae122016-10-11 11:47:09 +020077 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020078 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020079
Klement Sekeraf62ae122016-10-11 11:47:09 +020080 self.interfaces = list(self.pg_interfaces)
81 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020082
Klement Sekeraf62ae122016-10-11 11:47:09 +020083 # setup all interfaces
84 for i in self.interfaces:
85 i.admin_up()
86 i.config_ip4()
87 i.resolve_arp()
88
Matej Klotton86d87c42016-11-11 11:38:55 +010089 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020090
91 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010092 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020093 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070094
95 def show_commands_at_teardown(self):
Neale Rannscbe25aa2019-09-30 10:53:31 +000096 self.logger.info(self.vapi.cli("show ip4 neighbors"))
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070097 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020098
Jan Geletye6c78ee2018-06-26 12:24:03 +020099 def modify_packet(self, src_if, packet_size, pkt):
100 """Add load, set destination IP and extend packet to required packet
101 size for defined interface.
102
103 :param VppInterface src_if: Interface to create packet for.
104 :param int packet_size: Required packet size.
105 :param Scapy pkt: Packet to be modified.
106 """
Ole Troan6ed154f2019-10-15 19:31:55 +0200107 dst_if_idx = int(packet_size / 10 % 2)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200108 dst_if = self.flows[src_if][dst_if_idx]
109 info = self.create_packet_info(src_if, dst_if)
110 payload = self.info_to_payload(info)
111 p = pkt/Raw(payload)
112 p[IP].dst = dst_if.remote_ip4
113 info.data = p.copy()
114 if isinstance(src_if, VppSubInterface):
115 p = src_if.add_dot1_layer(p)
116 self.extend_packet(p, packet_size)
117
118 return p
119
120 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100121 """Create input packet stream for defined interface.
122
123 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100124 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200125 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
126 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
127 IP(src=src_if.remote_ip4) /
128 UDP(sport=1234, dport=1234))
129
130 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800131 for i in moves.range(self.pg_if_packet_sizes[0],
132 self.pg_if_packet_sizes[1], 10)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200133 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800134 for i in moves.range(self.pg_if_packet_sizes[1] + hdr_ext,
135 self.pg_if_packet_sizes[2] + hdr_ext,
136 50)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200137 pkts.extend(pkts_b)
138
Damjan Marionf56b77a2016-10-03 19:44:57 +0200139 return pkts
140
Klement Sekeraf62ae122016-10-11 11:47:09 +0200141 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100142 """Verify captured input packet stream for defined interface.
143
144 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200145 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100146 :param list capture: Captured packet stream.
147 """
148 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200149 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200150 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200151 last_info[i.sw_if_index] = None
152 is_sub_if = False
153 dst_sw_if_index = dst_if.sw_if_index
154 if hasattr(dst_if, 'parent'):
155 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200156 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200157 if is_sub_if:
158 # Check VLAN tags and Ethernet header
159 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200160 self.assertTrue(Dot1Q not in packet)
161 try:
162 ip = packet[IP]
163 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800164 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200165 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200166 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100167 self.logger.debug(
168 "Got packet on port %s: src=%u (id=%u)" %
169 (dst_if.name, payload_info.src, packet_index))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200170 next_info = self.get_next_packet_info_for_interface2(
171 payload_info.src, dst_sw_if_index,
172 last_info[payload_info.src])
173 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200174 self.assertTrue(next_info is not None)
175 self.assertEqual(packet_index, next_info.index)
176 saved_packet = next_info.data
177 # Check standard fields
178 self.assertEqual(ip.src, saved_packet[IP].src)
179 self.assertEqual(ip.dst, saved_packet[IP].dst)
180 self.assertEqual(udp.sport, saved_packet[UDP].sport)
181 self.assertEqual(udp.dport, saved_packet[UDP].dport)
182 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100183 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200184 raise
185 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200186 remaining_packet = self.get_next_packet_info_for_interface2(
187 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
Klement Sekera7bb873a2016-11-18 07:38:42 +0100188 self.assertTrue(remaining_packet is None,
189 "Interface %s: Packet expected from interface %s "
190 "didn't arrive" % (dst_if.name, i.name))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200191
192 def test_fib(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100193 """ IPv4 FIB test
194
195 Test scenario:
196
197 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200198 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100199 - Send and verify received packets on each interface.
200 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200201
Jan Geletye6c78ee2018-06-26 12:24:03 +0200202 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200203 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200204
Klement Sekeraf62ae122016-10-11 11:47:09 +0200205 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200206 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200207 i.parent.add_stream(pkts)
208
209 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200210 self.pg_start()
211
Klement Sekeraf62ae122016-10-11 11:47:09 +0200212 pkts = self.pg0.get_capture()
213 self.verify_capture(self.pg0, pkts)
214
215 for i in self.sub_interfaces:
216 pkts = i.parent.get_capture()
217 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200218
219
Christian Hoppsf5d38e02020-05-04 10:28:03 -0400220class TestIPv4RouteLookup(VppTestCase):
221 """ IPv4 Route Lookup Test Case """
222 routes = []
223
224 def route_lookup(self, prefix, exact):
225 return self.vapi.api(self.vapi.papi.ip_route_lookup,
226 {
227 'table_id': 0,
228 'exact': exact,
229 'prefix': prefix,
230 })
231
232 @classmethod
233 def setUpClass(cls):
234 super(TestIPv4RouteLookup, cls).setUpClass()
235
236 @classmethod
237 def tearDownClass(cls):
238 super(TestIPv4RouteLookup, cls).tearDownClass()
239
240 def setUp(self):
241 super(TestIPv4RouteLookup, self).setUp()
242
243 drop_nh = VppRoutePath("127.0.0.1", 0xffffffff,
244 type=FibPathType.FIB_PATH_TYPE_DROP)
245
246 # Add 3 routes
247 r = VppIpRoute(self, "1.1.0.0", 16, [drop_nh])
248 r.add_vpp_config()
249 self.routes.append(r)
250
251 r = VppIpRoute(self, "1.1.1.0", 24, [drop_nh])
252 r.add_vpp_config()
253 self.routes.append(r)
254
255 r = VppIpRoute(self, "1.1.1.1", 32, [drop_nh])
256 r.add_vpp_config()
257 self.routes.append(r)
258
259 def tearDown(self):
260 # Remove the routes we added
261 for r in self.routes:
262 r.remove_vpp_config()
263
264 super(TestIPv4RouteLookup, self).tearDown()
265
266 def test_exact_match(self):
267 # Verify we find the host route
268 prefix = "1.1.1.1/32"
269 result = self.route_lookup(prefix, True)
270 assert (prefix == str(result.route.prefix))
271
272 # Verify we find a middle prefix route
273 prefix = "1.1.1.0/24"
274 result = self.route_lookup(prefix, True)
275 assert (prefix == str(result.route.prefix))
276
277 # Verify we do not find an available LPM.
278 with self.vapi.assert_negative_api_retval():
279 self.route_lookup("1.1.1.2/32", True)
280
281 def test_longest_prefix_match(self):
282 # verify we find lpm
283 lpm_prefix = "1.1.1.0/24"
284 result = self.route_lookup("1.1.1.2/32", False)
285 assert (lpm_prefix == str(result.route.prefix))
286
287 # Verify we find the exact when not requested
288 result = self.route_lookup(lpm_prefix, False)
289 assert (lpm_prefix == str(result.route.prefix))
290
291 # Can't seem to delete the default route so no negative LPM test.
292
293
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500294class TestIPv4IfAddrRoute(VppTestCase):
Matthew G Smith88d29a92019-07-17 10:01:17 -0500295 """ IPv4 Interface Addr Route Test Case """
296
297 @classmethod
298 def setUpClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500299 super(TestIPv4IfAddrRoute, cls).setUpClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500300
301 @classmethod
302 def tearDownClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500303 super(TestIPv4IfAddrRoute, cls).tearDownClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500304
305 def setUp(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500306 super(TestIPv4IfAddrRoute, self).setUp()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500307
308 # create 1 pg interface
309 self.create_pg_interfaces(range(1))
310
311 for i in self.pg_interfaces:
312 i.admin_up()
313 i.config_ip4()
314 i.resolve_arp()
315
316 def tearDown(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500317 super(TestIPv4IfAddrRoute, self).tearDown()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500318 for i in self.pg_interfaces:
319 i.unconfig_ip4()
320 i.admin_down()
321
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500322 def test_ipv4_ifaddrs_same_prefix(self):
323 """ IPv4 Interface Addresses Same Prefix test
324
325 Test scenario:
326
327 - Verify no route in FIB for prefix 10.10.10.0/24
328 - Configure IPv4 address 10.10.10.10/24 on an interface
329 - Verify route in FIB for prefix 10.10.10.0/24
330 - Configure IPv4 address 10.10.10.20/24 on an interface
331 - Delete 10.10.10.10/24 from interface
332 - Verify route in FIB for prefix 10.10.10.0/24
333 - Delete 10.10.10.20/24 from interface
334 - Verify no route in FIB for prefix 10.10.10.0/24
335 """
336
337 # create two addresses, verify route not present
Neale Rannsefd7bc22019-11-11 08:32:34 +0000338 if_addr1 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.10", 24)
339 if_addr2 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.20", 24)
340 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500341 self.assertFalse(find_route(self, "10.10.10.10", 32))
342 self.assertFalse(find_route(self, "10.10.10.20", 32))
343 self.assertFalse(find_route(self, "10.10.10.255", 32))
344 self.assertFalse(find_route(self, "10.10.10.0", 32))
345
346 # configure first address, verify route present
347 if_addr1.add_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000348 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.10/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500349 self.assertTrue(find_route(self, "10.10.10.10", 32))
350 self.assertFalse(find_route(self, "10.10.10.20", 32))
351 self.assertTrue(find_route(self, "10.10.10.255", 32))
352 self.assertTrue(find_route(self, "10.10.10.0", 32))
353
354 # configure second address, delete first, verify route not removed
355 if_addr2.add_vpp_config()
356 if_addr1.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000357 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24
358 self.assertTrue(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500359 self.assertFalse(find_route(self, "10.10.10.10", 32))
360 self.assertTrue(find_route(self, "10.10.10.20", 32))
361 self.assertTrue(find_route(self, "10.10.10.255", 32))
362 self.assertTrue(find_route(self, "10.10.10.0", 32))
363
364 # delete second address, verify route removed
365 if_addr2.remove_vpp_config()
Neale Rannsefd7bc22019-11-11 08:32:34 +0000366 self.assertFalse(if_addr2.query_vpp_config()) # 10.10.10.20/24
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500367 self.assertFalse(find_route(self, "10.10.10.10", 32))
368 self.assertFalse(find_route(self, "10.10.10.20", 32))
369 self.assertFalse(find_route(self, "10.10.10.255", 32))
370 self.assertFalse(find_route(self, "10.10.10.0", 32))
371
Matthew G Smith88d29a92019-07-17 10:01:17 -0500372 def test_ipv4_ifaddr_route(self):
373 """ IPv4 Interface Address Route test
374
375 Test scenario:
376
377 - Create loopback
378 - Configure IPv4 address on loopback
379 - Verify that address is not in the FIB
380 - Bring loopback up
381 - Verify that address is in the FIB now
382 - Bring loopback down
383 - Verify that address is not in the FIB anymore
384 - Bring loopback up
385 - Configure IPv4 address on loopback
386 - Verify that address is in the FIB now
387 """
388
389 # create a loopback and configure IPv4
390 loopbacks = self.create_loopback_interfaces(1)
391 lo_if = self.lo_interfaces[0]
392
393 lo_if.local_ip4_prefix_len = 32
394 lo_if.config_ip4()
395
396 # The intf was down when addr was added -> entry not in FIB
397 fib4_dump = self.vapi.ip_route_dump(0)
398 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
399
400 # When intf is brought up, entry is added
401 lo_if.admin_up()
402 fib4_dump = self.vapi.ip_route_dump(0)
403 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
404
405 # When intf is brought down, entry is removed
406 lo_if.admin_down()
407 fib4_dump = self.vapi.ip_route_dump(0)
408 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
409
410 # Remove addr, bring up interface, re-add -> entry in FIB
411 lo_if.unconfig_ip4()
412 lo_if.admin_up()
413 lo_if.config_ip4()
414 fib4_dump = self.vapi.ip_route_dump(0)
415 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
416
yedgdbd366b2020-05-14 10:51:53 +0800417 def test_ipv4_ifaddr_del(self):
418 """ Delete an interface address that does not exist """
419
420 loopbacks = self.create_loopback_interfaces(1)
421 lo = self.lo_interfaces[0]
422
423 lo.config_ip4()
424 lo.admin_up()
425
426 #
427 # try and remove pg0's subnet from lo
428 #
429 with self.vapi.assert_negative_api_retval():
430 self.vapi.sw_interface_add_del_address(
431 sw_if_index=lo.sw_if_index,
432 prefix=self.pg0.local_ip4_prefix,
433 is_add=0)
434
Matthew G Smith88d29a92019-07-17 10:01:17 -0500435
Jan Geletye6c78ee2018-06-26 12:24:03 +0200436class TestICMPEcho(VppTestCase):
437 """ ICMP Echo Test Case """
438
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700439 @classmethod
440 def setUpClass(cls):
441 super(TestICMPEcho, cls).setUpClass()
442
443 @classmethod
444 def tearDownClass(cls):
445 super(TestICMPEcho, cls).tearDownClass()
446
Jan Geletye6c78ee2018-06-26 12:24:03 +0200447 def setUp(self):
448 super(TestICMPEcho, self).setUp()
449
450 # create 1 pg interface
451 self.create_pg_interfaces(range(1))
452
453 for i in self.pg_interfaces:
454 i.admin_up()
455 i.config_ip4()
456 i.resolve_arp()
457
458 def tearDown(self):
459 super(TestICMPEcho, self).tearDown()
460 for i in self.pg_interfaces:
461 i.unconfig_ip4()
462 i.admin_down()
463
464 def test_icmp_echo(self):
465 """ VPP replies to ICMP Echo Request
466
467 Test scenario:
468
469 - Receive ICMP Echo Request message on pg0 interface.
470 - Check outgoing ICMP Echo Reply message on pg0 interface.
471 """
472
473 icmp_id = 0xb
474 icmp_seq = 5
Ole Troan6ed154f2019-10-15 19:31:55 +0200475 icmp_load = b'\x0a' * 18
Jan Geletye6c78ee2018-06-26 12:24:03 +0200476 p_echo_request = (Ether(src=self.pg0.remote_mac,
477 dst=self.pg0.local_mac) /
478 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
479 ICMP(id=icmp_id, seq=icmp_seq) /
480 Raw(load=icmp_load))
481
482 self.pg0.add_stream(p_echo_request)
483 self.pg_enable_capture(self.pg_interfaces)
484 self.pg_start()
485
486 rx = self.pg0.get_capture(1)
487 rx = rx[0]
488 ether = rx[Ether]
489 ipv4 = rx[IP]
490 icmp = rx[ICMP]
491
492 self.assertEqual(ether.src, self.pg0.local_mac)
493 self.assertEqual(ether.dst, self.pg0.remote_mac)
494
495 self.assertEqual(ipv4.src, self.pg0.local_ip4)
496 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
497
498 self.assertEqual(icmptypes[icmp.type], "echo-reply")
499 self.assertEqual(icmp.id, icmp_id)
500 self.assertEqual(icmp.seq, icmp_seq)
501 self.assertEqual(icmp[Raw].load, icmp_load)
502
503
Matej Klotton16a14cd2016-12-07 15:09:13 +0100504class TestIPv4FibCrud(VppTestCase):
505 """ FIB - add/update/delete - ip4 routes
506
507 Test scenario:
508 - add 1k,
509 - del 100,
510 - add new 1k,
511 - del 1.5k
512
Klement Sekerada505f62017-01-04 12:58:53 +0100513 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100514 """
515
Neale Ranns097fa662018-05-01 05:17:55 -0700516 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr,
517 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100518 """
519
520 :param start_dest_addr:
521 :param next_hop_addr:
522 :param count:
523 :return list: added ips with 32 prefix
524 """
Neale Ranns097fa662018-05-01 05:17:55 -0700525 routes = []
526 for i in range(count):
527 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
528 [VppRoutePath(next_hop_addr, 0xffffffff)])
529 r.add_vpp_config()
530 routes.append(r)
531 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100532
Neale Ranns097fa662018-05-01 05:17:55 -0700533 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr,
534 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100535
Neale Ranns097fa662018-05-01 05:17:55 -0700536 routes = []
537 for i in range(count):
538 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
539 [VppRoutePath(next_hop_addr, 0xffffffff)])
540 r.remove_vpp_config()
541 routes.append(r)
542 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100543
Neale Ranns097fa662018-05-01 05:17:55 -0700544 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100545 pkts = []
546
547 for _ in range(count):
Neale Rannsefd7bc22019-11-11 08:32:34 +0000548 dst_addr = random.choice(routes).prefix.network_address
Klement Sekeradab231a2016-12-21 08:50:14 +0100549 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100550 payload = self.info_to_payload(info)
551 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
Neale Rannsefd7bc22019-11-11 08:32:34 +0000552 IP(src=src_if.remote_ip4, dst=str(dst_addr)) /
Matej Klotton16a14cd2016-12-07 15:09:13 +0100553 UDP(sport=1234, dport=1234) /
554 Raw(payload))
555 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100556 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
557 pkts.append(p)
558
559 return pkts
560
561 def _find_ip_match(self, find_in, pkt):
562 for p in find_in:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800563 if self.payload_to_info(p[Raw]) == \
564 self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100565 if p[IP].src != pkt[IP].src:
566 break
567 if p[IP].dst != pkt[IP].dst:
568 break
569 if p[UDP].sport != pkt[UDP].sport:
570 break
571 if p[UDP].dport != pkt[UDP].dport:
572 break
573 return p
574 return None
575
Matej Klotton16a14cd2016-12-07 15:09:13 +0100576 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
577 self.assertEqual(len(received_pkts), len(expected_pkts))
578 to_verify = list(expected_pkts)
579 for p in received_pkts:
580 self.assertEqual(p.src, dst_interface.local_mac)
581 self.assertEqual(p.dst, dst_interface.remote_mac)
582 x = self._find_ip_match(to_verify, p)
583 to_verify.remove(x)
584 self.assertListEqual(to_verify, [])
585
Neale Ranns097fa662018-05-01 05:17:55 -0700586 def verify_route_dump(self, routes):
587 for r in routes:
Neale Rannsefd7bc22019-11-11 08:32:34 +0000588 self.assertTrue(find_route(self,
589 r.prefix.network_address,
590 r.prefix.prefixlen))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100591
Neale Ranns097fa662018-05-01 05:17:55 -0700592 def verify_not_in_route_dump(self, routes):
593 for r in routes:
Neale Rannsefd7bc22019-11-11 08:32:34 +0000594 self.assertFalse(find_route(self,
595 r.prefix.network_address,
596 r.prefix.prefixlen))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100597
598 @classmethod
599 def setUpClass(cls):
600 """
601 #. Create and initialize 3 pg interfaces.
602 #. initialize class attributes configured_routes and deleted_routes
603 to store information between tests.
604 """
605 super(TestIPv4FibCrud, cls).setUpClass()
606
607 try:
608 # create 3 pg interfaces
609 cls.create_pg_interfaces(range(3))
610
611 cls.interfaces = list(cls.pg_interfaces)
612
613 # setup all interfaces
614 for i in cls.interfaces:
615 i.admin_up()
616 i.config_ip4()
617 i.resolve_arp()
618
619 cls.configured_routes = []
620 cls.deleted_routes = []
621 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
622
623 except Exception:
624 super(TestIPv4FibCrud, cls).tearDownClass()
625 raise
626
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700627 @classmethod
628 def tearDownClass(cls):
629 super(TestIPv4FibCrud, cls).tearDownClass()
630
Matej Klotton16a14cd2016-12-07 15:09:13 +0100631 def setUp(self):
632 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100633 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100634
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800635 self.configured_routes = []
636 self.deleted_routes = []
637
Matej Klotton16a14cd2016-12-07 15:09:13 +0100638 def test_1_add_routes(self):
Neale Ranns097fa662018-05-01 05:17:55 -0700639 """ Add 1k routes """
Matej Klotton16a14cd2016-12-07 15:09:13 +0100640
Neale Ranns097fa662018-05-01 05:17:55 -0700641 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100642 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700643 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100644
Neale Ranns097fa662018-05-01 05:17:55 -0700645 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100646
647 self.stream_1 = self.create_stream(
648 self.pg1, self.pg0, self.configured_routes, 100)
649 self.stream_2 = self.create_stream(
650 self.pg2, self.pg0, self.configured_routes, 100)
651 self.pg1.add_stream(self.stream_1)
652 self.pg2.add_stream(self.stream_2)
653
654 self.pg_enable_capture(self.pg_interfaces)
655 self.pg_start()
656
Klement Sekeradab231a2016-12-21 08:50:14 +0100657 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100658 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
659
Matej Klotton16a14cd2016-12-07 15:09:13 +0100660 def test_2_del_routes(self):
661 """ Delete 100 routes
662
663 - delete 10 routes check with traffic script.
664 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800665 # config 1M FIB entries
666 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700667 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100668 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700669 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100670 for x in self.deleted_routes:
671 self.configured_routes.remove(x)
672
Neale Ranns097fa662018-05-01 05:17:55 -0700673 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100674
675 self.stream_1 = self.create_stream(
676 self.pg1, self.pg0, self.configured_routes, 100)
677 self.stream_2 = self.create_stream(
678 self.pg2, self.pg0, self.configured_routes, 100)
679 self.stream_3 = self.create_stream(
680 self.pg1, self.pg0, self.deleted_routes, 100)
681 self.stream_4 = self.create_stream(
682 self.pg2, self.pg0, self.deleted_routes, 100)
683 self.pg1.add_stream(self.stream_1 + self.stream_3)
684 self.pg2.add_stream(self.stream_2 + self.stream_4)
685 self.pg_enable_capture(self.pg_interfaces)
686 self.pg_start()
687
Klement Sekeradab231a2016-12-21 08:50:14 +0100688 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100689 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
690
691 def test_3_add_new_routes(self):
692 """ Add 1k routes
693
694 - re-add 5 routes check with traffic script.
695 - add 100 routes check with traffic script.
696 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800697 # config 1M FIB entries
698 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700699 "10.0.0.%d", self.pg0.remote_ip4, 100))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800700 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700701 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800702 for x in self.deleted_routes:
703 self.configured_routes.remove(x)
704
Matej Klotton16a14cd2016-12-07 15:09:13 +0100705 tmp = self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700706 "10.0.0.%d", self.pg0.remote_ip4, 5, start=10)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100707 self.configured_routes.extend(tmp)
708 for x in tmp:
709 self.deleted_routes.remove(x)
710
711 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700712 "10.0.1.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100713
Neale Ranns097fa662018-05-01 05:17:55 -0700714 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100715
716 self.stream_1 = self.create_stream(
717 self.pg1, self.pg0, self.configured_routes, 300)
718 self.stream_2 = self.create_stream(
719 self.pg2, self.pg0, self.configured_routes, 300)
720 self.stream_3 = self.create_stream(
721 self.pg1, self.pg0, self.deleted_routes, 100)
722 self.stream_4 = self.create_stream(
723 self.pg2, self.pg0, self.deleted_routes, 100)
724
725 self.pg1.add_stream(self.stream_1 + self.stream_3)
726 self.pg2.add_stream(self.stream_2 + self.stream_4)
727 self.pg_enable_capture(self.pg_interfaces)
728 self.pg_start()
729
Klement Sekeradab231a2016-12-21 08:50:14 +0100730 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100731 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
732
Neale Ranns097fa662018-05-01 05:17:55 -0700733 # delete 5 routes check with traffic script.
734 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100735 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700736 "10.0.0.%d", self.pg0.remote_ip4, 15))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100737 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700738 "10.0.0.%d", self.pg0.remote_ip4, 85))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100739 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700740 "10.0.1.%d", self.pg0.remote_ip4, 100))
741 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100742
743
Neale Ranns37be7362017-02-21 17:30:26 -0800744class TestIPNull(VppTestCase):
745 """ IPv4 routes via NULL """
746
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700747 @classmethod
748 def setUpClass(cls):
749 super(TestIPNull, cls).setUpClass()
750
751 @classmethod
752 def tearDownClass(cls):
753 super(TestIPNull, cls).tearDownClass()
754
Neale Ranns37be7362017-02-21 17:30:26 -0800755 def setUp(self):
756 super(TestIPNull, self).setUp()
757
758 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700759 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800760
761 for i in self.pg_interfaces:
762 i.admin_up()
763 i.config_ip4()
764 i.resolve_arp()
765
766 def tearDown(self):
767 super(TestIPNull, self).tearDown()
768 for i in self.pg_interfaces:
769 i.unconfig_ip4()
770 i.admin_down()
771
772 def test_ip_null(self):
773 """ IP NULL route """
774
775 #
776 # A route via IP NULL that will reply with ICMP unreachables
777 #
Neale Ranns097fa662018-05-01 05:17:55 -0700778 ip_unreach = VppIpRoute(
779 self, "10.0.0.1", 32,
780 [VppRoutePath("0.0.0.0",
781 0xffffffff,
782 type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH)])
Neale Ranns37be7362017-02-21 17:30:26 -0800783 ip_unreach.add_vpp_config()
784
785 p_unreach = (Ether(src=self.pg0.remote_mac,
786 dst=self.pg0.local_mac) /
787 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
788 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200789 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800790 self.pg0.add_stream(p_unreach)
791 self.pg_enable_capture(self.pg_interfaces)
792 self.pg_start()
793
794 rx = self.pg0.get_capture(1)
795 rx = rx[0]
796 icmp = rx[ICMP]
797
798 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
799 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
800 self.assertEqual(icmp.src, self.pg0.remote_ip4)
801 self.assertEqual(icmp.dst, "10.0.0.1")
802
803 #
804 # ICMP replies are rate limited. so sit and spin.
805 #
806 self.sleep(1)
807
808 #
809 # A route via IP NULL that will reply with ICMP prohibited
810 #
Neale Ranns097fa662018-05-01 05:17:55 -0700811 ip_prohibit = VppIpRoute(
812 self, "10.0.0.2", 32,
813 [VppRoutePath("0.0.0.0",
814 0xffffffff,
815 type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT)])
Neale Ranns37be7362017-02-21 17:30:26 -0800816 ip_prohibit.add_vpp_config()
817
818 p_prohibit = (Ether(src=self.pg0.remote_mac,
819 dst=self.pg0.local_mac) /
820 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
821 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200822 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800823
824 self.pg0.add_stream(p_prohibit)
825 self.pg_enable_capture(self.pg_interfaces)
826 self.pg_start()
827
828 rx = self.pg0.get_capture(1)
829
830 rx = rx[0]
831 icmp = rx[ICMP]
832
833 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
834 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
835 self.assertEqual(icmp.src, self.pg0.remote_ip4)
836 self.assertEqual(icmp.dst, "10.0.0.2")
837
Neale Ranns3b93be52018-09-07 01:48:54 -0700838 def test_ip_drop(self):
839 """ IP Drop Routes """
840
841 p = (Ether(src=self.pg0.remote_mac,
842 dst=self.pg0.local_mac) /
843 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
844 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200845 Raw(b'\xa5' * 100))
Neale Ranns3b93be52018-09-07 01:48:54 -0700846
847 r1 = VppIpRoute(self, "1.1.1.0", 24,
848 [VppRoutePath(self.pg1.remote_ip4,
849 self.pg1.sw_if_index)])
850 r1.add_vpp_config()
851
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400852 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700853
854 #
855 # insert a more specific as a drop
856 #
Neale Ranns097fa662018-05-01 05:17:55 -0700857 r2 = VppIpRoute(self, "1.1.1.1", 32,
858 [VppRoutePath("0.0.0.0",
859 0xffffffff,
860 type=FibPathType.FIB_PATH_TYPE_DROP)])
Neale Ranns3b93be52018-09-07 01:48:54 -0700861 r2.add_vpp_config()
862
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400863 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700864 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400865 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700866
Neale Ranns37be7362017-02-21 17:30:26 -0800867
Neale Ranns180279b2017-03-16 15:49:09 -0400868class TestIPDisabled(VppTestCase):
869 """ IPv4 disabled """
870
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700871 @classmethod
872 def setUpClass(cls):
873 super(TestIPDisabled, cls).setUpClass()
874
875 @classmethod
876 def tearDownClass(cls):
877 super(TestIPDisabled, cls).tearDownClass()
878
Neale Ranns180279b2017-03-16 15:49:09 -0400879 def setUp(self):
880 super(TestIPDisabled, self).setUp()
881
882 # create 2 pg interfaces
883 self.create_pg_interfaces(range(2))
884
885 # PG0 is IP enalbed
886 self.pg0.admin_up()
887 self.pg0.config_ip4()
888 self.pg0.resolve_arp()
889
890 # PG 1 is not IP enabled
891 self.pg1.admin_up()
892
893 def tearDown(self):
894 super(TestIPDisabled, self).tearDown()
895 for i in self.pg_interfaces:
896 i.unconfig_ip4()
897 i.admin_down()
898
Neale Ranns180279b2017-03-16 15:49:09 -0400899 def test_ip_disabled(self):
900 """ IP Disabled """
901
Neale Ranns990f6942020-10-20 07:20:17 +0000902 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
903 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
904
Neale Ranns180279b2017-03-16 15:49:09 -0400905 #
906 # An (S,G).
907 # one accepting interface, pg0, 2 forwarding interfaces
908 #
909 route_232_1_1_1 = VppIpMRoute(
910 self,
911 "0.0.0.0",
912 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000913 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns180279b2017-03-16 15:49:09 -0400914 [VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000915 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns180279b2017-03-16 15:49:09 -0400916 VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000917 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns180279b2017-03-16 15:49:09 -0400918 route_232_1_1_1.add_vpp_config()
919
920 pu = (Ether(src=self.pg1.remote_mac,
921 dst=self.pg1.local_mac) /
922 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
923 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200924 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -0400925 pm = (Ether(src=self.pg1.remote_mac,
926 dst=self.pg1.local_mac) /
927 IP(src="10.10.10.10", dst="232.1.1.1") /
928 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200929 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -0400930
931 #
932 # PG1 does not forward IP traffic
933 #
934 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
935 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
936
937 #
938 # IP enable PG1
939 #
940 self.pg1.config_ip4()
941
942 #
943 # Now we get packets through
944 #
945 self.pg1.add_stream(pu)
946 self.pg_enable_capture(self.pg_interfaces)
947 self.pg_start()
948 rx = self.pg0.get_capture(1)
949
950 self.pg1.add_stream(pm)
951 self.pg_enable_capture(self.pg_interfaces)
952 self.pg_start()
953 rx = self.pg0.get_capture(1)
954
955 #
956 # Disable PG1
957 #
958 self.pg1.unconfig_ip4()
959
960 #
961 # PG1 does not forward IP traffic
962 #
963 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
964 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
965
966
Neale Ranns9a69a602017-03-26 10:56:33 -0700967class TestIPSubNets(VppTestCase):
968 """ IPv4 Subnets """
969
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700970 @classmethod
971 def setUpClass(cls):
972 super(TestIPSubNets, cls).setUpClass()
973
974 @classmethod
975 def tearDownClass(cls):
976 super(TestIPSubNets, cls).tearDownClass()
977
Neale Ranns9a69a602017-03-26 10:56:33 -0700978 def setUp(self):
979 super(TestIPSubNets, self).setUp()
980
981 # create a 2 pg interfaces
982 self.create_pg_interfaces(range(2))
983
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700984 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -0700985 self.pg0.admin_up()
986
987 # pg1 is setup normally
988 self.pg1.admin_up()
989 self.pg1.config_ip4()
990 self.pg1.resolve_arp()
991
992 def tearDown(self):
993 super(TestIPSubNets, self).tearDown()
994 for i in self.pg_interfaces:
995 i.admin_down()
996
Neale Ranns9a69a602017-03-26 10:56:33 -0700997 def test_ip_sub_nets(self):
998 """ IP Sub Nets """
999
1000 #
1001 # Configure a covering route to forward so we know
1002 # when we are dropping
1003 #
1004 cover_route = VppIpRoute(self, "10.0.0.0", 8,
1005 [VppRoutePath(self.pg1.remote_ip4,
1006 self.pg1.sw_if_index)])
1007 cover_route.add_vpp_config()
1008
1009 p = (Ether(src=self.pg1.remote_mac,
1010 dst=self.pg1.local_mac) /
1011 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
1012 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001013 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -07001014
1015 self.pg1.add_stream(p)
1016 self.pg_enable_capture(self.pg_interfaces)
1017 self.pg_start()
1018 rx = self.pg1.get_capture(1)
1019
1020 #
1021 # Configure some non-/24 subnets on an IP interface
1022 #
1023 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1024
Ole Troan9a475372019-03-05 16:58:24 +01001025 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +01001026 sw_if_index=self.pg0.sw_if_index,
Neale Rannsefd7bc22019-11-11 08:32:34 +00001027 prefix="10.10.10.10/16")
Neale Ranns9a69a602017-03-26 10:56:33 -07001028
1029 pn = (Ether(src=self.pg1.remote_mac,
1030 dst=self.pg1.local_mac) /
1031 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
1032 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001033 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -07001034 pb = (Ether(src=self.pg1.remote_mac,
1035 dst=self.pg1.local_mac) /
1036 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
1037 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001038 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -07001039
1040 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
1041 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
1042
1043 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001044 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +01001045 sw_if_index=self.pg0.sw_if_index,
Neale Rannsefd7bc22019-11-11 08:32:34 +00001046 prefix="10.10.10.10/16",
1047 is_add=0)
Jakub Grajciar053204a2019-03-18 13:17:53 +01001048
Neale Ranns9a69a602017-03-26 10:56:33 -07001049 self.pg1.add_stream(pn)
1050 self.pg_enable_capture(self.pg_interfaces)
1051 self.pg_start()
1052 rx = self.pg1.get_capture(1)
1053 self.pg1.add_stream(pb)
1054 self.pg_enable_capture(self.pg_interfaces)
1055 self.pg_start()
1056 rx = self.pg1.get_capture(1)
1057
1058 #
1059 # A /31 is a special case where the 'other-side' is an attached host
1060 # packets to that peer generate ARP requests
1061 #
1062 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
1063
Ole Troan9a475372019-03-05 16:58:24 +01001064 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +01001065 sw_if_index=self.pg0.sw_if_index,
Neale Rannsefd7bc22019-11-11 08:32:34 +00001066 prefix="10.10.10.10/31")
Neale Ranns9a69a602017-03-26 10:56:33 -07001067
1068 pn = (Ether(src=self.pg1.remote_mac,
1069 dst=self.pg1.local_mac) /
1070 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
1071 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001072 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -07001073
1074 self.pg1.add_stream(pn)
1075 self.pg_enable_capture(self.pg_interfaces)
1076 self.pg_start()
1077 rx = self.pg0.get_capture(1)
1078 rx[ARP]
1079
1080 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +01001081 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +01001082 sw_if_index=self.pg0.sw_if_index,
Neale Rannsefd7bc22019-11-11 08:32:34 +00001083 prefix="10.10.10.10/31", is_add=0)
Jakub Grajciar053204a2019-03-18 13:17:53 +01001084
Neale Ranns9a69a602017-03-26 10:56:33 -07001085 self.pg1.add_stream(pn)
1086 self.pg_enable_capture(self.pg_interfaces)
1087 self.pg_start()
1088 rx = self.pg1.get_capture(1)
1089
1090
Neale Ranns227038a2017-04-21 01:07:59 -07001091class TestIPLoadBalance(VppTestCase):
1092 """ IPv4 Load-Balancing """
1093
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001094 @classmethod
1095 def setUpClass(cls):
1096 super(TestIPLoadBalance, cls).setUpClass()
1097
1098 @classmethod
1099 def tearDownClass(cls):
1100 super(TestIPLoadBalance, cls).tearDownClass()
1101
Neale Ranns227038a2017-04-21 01:07:59 -07001102 def setUp(self):
1103 super(TestIPLoadBalance, self).setUp()
1104
1105 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -07001106 mpls_tbl = VppMplsTable(self, 0)
1107 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -07001108
1109 for i in self.pg_interfaces:
1110 i.admin_up()
1111 i.config_ip4()
1112 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -07001113 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001114
1115 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -07001116 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -07001117 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001118 i.unconfig_ip4()
1119 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001120 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -07001121
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001122 def total_len(self, rxs):
1123 n = 0
1124 for rx in rxs:
1125 n += len(rx)
1126 return n
1127
Neale Ranns227038a2017-04-21 01:07:59 -07001128 def test_ip_load_balance(self):
1129 """ IP Load-Balancing """
1130
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001131 fhc = VppEnum.vl_api_ip_flow_hash_config_t
1132 af = VppEnum.vl_api_address_family_t
1133
Neale Ranns227038a2017-04-21 01:07:59 -07001134 #
1135 # An array of packets that differ only in the destination port
1136 #
Neale Ranns71275e32017-05-25 12:38:58 -07001137 port_ip_pkts = []
1138 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001139
1140 #
1141 # An array of packets that differ only in the source address
1142 #
Neale Ranns71275e32017-05-25 12:38:58 -07001143 src_ip_pkts = []
1144 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001145
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001146 for ii in range(NUM_PKTS):
Neale Ranns71275e32017-05-25 12:38:58 -07001147 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
1148 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001149 Raw(b'\xa5' * 100))
Neale Ranns71275e32017-05-25 12:38:58 -07001150 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1151 dst=self.pg0.local_mac) /
1152 port_ip_hdr))
1153 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1154 dst=self.pg0.local_mac) /
1155 MPLS(label=66, ttl=2) /
1156 port_ip_hdr))
1157
1158 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
1159 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001160 Raw(b'\xa5' * 100))
Neale Ranns71275e32017-05-25 12:38:58 -07001161 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1162 dst=self.pg0.local_mac) /
1163 src_ip_hdr))
1164 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1165 dst=self.pg0.local_mac) /
1166 MPLS(label=66, ttl=2) /
1167 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -07001168
1169 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1170 [VppRoutePath(self.pg1.remote_ip4,
1171 self.pg1.sw_if_index),
1172 VppRoutePath(self.pg2.remote_ip4,
1173 self.pg2.sw_if_index)])
1174 route_10_0_0_1.add_vpp_config()
1175
Neale Ranns71275e32017-05-25 12:38:58 -07001176 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1177 binding.add_vpp_config()
1178
Neale Ranns227038a2017-04-21 01:07:59 -07001179 #
1180 # inject the packet on pg0 - expect load-balancing across the 2 paths
1181 # - since the default hash config is to use IP src,dst and port
1182 # src,dst
1183 # We are not going to ensure equal amounts of packets across each link,
1184 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001185 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001186 # balancing. So instead just ensure there is traffic on each link.
1187 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001188 rx = self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
1189 [self.pg1, self.pg2])
1190 n_ip_pg0 = len(rx[0])
Neale Ranns71275e32017-05-25 12:38:58 -07001191 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1192 [self.pg1, self.pg2])
1193 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
1194 [self.pg1, self.pg2])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001195 rx = self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1196 [self.pg1, self.pg2])
1197 n_mpls_pg0 = len(rx[0])
1198
1199 #
1200 # change the router ID and expect the distribution changes
1201 #
1202 self.vapi.set_ip_flow_hash_router_id(router_id=0x11111111)
1203
1204 rx = self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
1205 [self.pg1, self.pg2])
1206 self.assertNotEqual(n_ip_pg0, len(rx[0]))
1207
1208 rx = self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1209 [self.pg1, self.pg2])
1210 self.assertNotEqual(n_mpls_pg0, len(rx[0]))
Neale Ranns227038a2017-04-21 01:07:59 -07001211
1212 #
1213 # change the flow hash config so it's only IP src,dst
1214 # - now only the stream with differing source address will
1215 # load-balance
1216 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001217 self.vapi.set_ip_flow_hash_v2(
1218 af=af.ADDRESS_IP4,
1219 table_id=0,
1220 flow_hash_config=(fhc.IP_API_FLOW_HASH_SRC_IP |
1221 fhc.IP_API_FLOW_HASH_DST_IP |
1222 fhc.IP_API_FLOW_HASH_PROTO))
Neale Ranns227038a2017-04-21 01:07:59 -07001223
Neale Ranns71275e32017-05-25 12:38:58 -07001224 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1225 [self.pg1, self.pg2])
1226 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001227 [self.pg1, self.pg2])
1228
Neale Ranns699bea22022-02-17 09:22:16 +00001229 self.send_and_expect_only(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001230
1231 #
1232 # change the flow hash config back to defaults
1233 #
Ahmed Abdelsalamf2984bb2020-11-20 18:56:09 +00001234 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1,
1235 proto=1, sport=1, dport=1)
Neale Ranns227038a2017-04-21 01:07:59 -07001236
1237 #
1238 # Recursive prefixes
1239 # - testing that 2 stages of load-balancing occurs and there is no
1240 # polarisation (i.e. only 2 of 4 paths are used)
1241 #
1242 port_pkts = []
1243 src_pkts = []
1244
1245 for ii in range(257):
1246 port_pkts.append((Ether(src=self.pg0.remote_mac,
1247 dst=self.pg0.local_mac) /
1248 IP(dst="1.1.1.1", src="20.0.0.1") /
1249 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001250 Raw(b'\xa5' * 100)))
Neale Ranns227038a2017-04-21 01:07:59 -07001251 src_pkts.append((Ether(src=self.pg0.remote_mac,
1252 dst=self.pg0.local_mac) /
1253 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1254 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001255 Raw(b'\xa5' * 100)))
Neale Ranns227038a2017-04-21 01:07:59 -07001256
1257 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1258 [VppRoutePath(self.pg3.remote_ip4,
1259 self.pg3.sw_if_index),
1260 VppRoutePath(self.pg4.remote_ip4,
1261 self.pg4.sw_if_index)])
1262 route_10_0_0_2.add_vpp_config()
1263
1264 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1265 [VppRoutePath("10.0.0.2", 0xffffffff),
1266 VppRoutePath("10.0.0.1", 0xffffffff)])
1267 route_1_1_1_1.add_vpp_config()
1268
1269 #
1270 # inject the packet on pg0 - expect load-balancing across all 4 paths
1271 #
1272 self.vapi.cli("clear trace")
1273 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1274 [self.pg1, self.pg2,
1275 self.pg3, self.pg4])
1276 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1277 [self.pg1, self.pg2,
1278 self.pg3, self.pg4])
1279
Neale Ranns42e6b092017-07-31 02:56:03 -07001280 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001281 # bring down pg1 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001282 #
1283 self.pg1.link_down()
1284
1285 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1286 [self.pg2, self.pg3,
1287 self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001288 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001289
1290 #
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001291 # bring down pg2 expect LB to adjust to use only those that are up
Neale Ranns63480742019-03-13 06:41:52 -07001292 #
1293 self.pg2.link_down()
1294
1295 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1296 [self.pg3, self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001297 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001298
1299 #
1300 # bring the links back up - expect LB over all again
1301 #
1302 self.pg1.link_up()
1303 self.pg2.link_up()
1304
1305 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1306 [self.pg1, self.pg2,
1307 self.pg3, self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001308 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001309
1310 #
1311 # The same link-up/down but this time admin state
1312 #
1313 self.pg1.admin_down()
1314 self.pg2.admin_down()
1315 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1316 [self.pg3, self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001317 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001318 self.pg1.admin_up()
1319 self.pg2.admin_up()
1320 self.pg1.resolve_arp()
1321 self.pg2.resolve_arp()
1322 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1323 [self.pg1, self.pg2,
1324 self.pg3, self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001325 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001326
1327 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001328 # Recursive prefixes
1329 # - testing that 2 stages of load-balancing, no choices
1330 #
1331 port_pkts = []
1332
1333 for ii in range(257):
1334 port_pkts.append((Ether(src=self.pg0.remote_mac,
1335 dst=self.pg0.local_mac) /
1336 IP(dst="1.1.1.2", src="20.0.0.2") /
1337 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001338 Raw(b'\xa5' * 100)))
Neale Ranns42e6b092017-07-31 02:56:03 -07001339
1340 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1341 [VppRoutePath(self.pg3.remote_ip4,
1342 self.pg3.sw_if_index)])
1343 route_10_0_0_3.add_vpp_config()
1344
1345 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1346 [VppRoutePath("10.0.0.3", 0xffffffff)])
1347 route_1_1_1_2.add_vpp_config()
1348
1349 #
Neale Ranns63480742019-03-13 06:41:52 -07001350 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001351 #
1352 self.vapi.cli("clear trace")
Neale Ranns699bea22022-02-17 09:22:16 +00001353 self.send_and_expect_only(self.pg0, port_pkts, self.pg3)
Neale Ranns42e6b092017-07-31 02:56:03 -07001354
Neale Ranns63480742019-03-13 06:41:52 -07001355 #
1356 # Add a LB route in the presence of a down link - expect no
1357 # packets over the down link
1358 #
1359 self.pg3.link_down()
1360
1361 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1362 [VppRoutePath(self.pg3.remote_ip4,
1363 self.pg3.sw_if_index),
1364 VppRoutePath(self.pg4.remote_ip4,
1365 self.pg4.sw_if_index)])
1366 route_10_0_0_3.add_vpp_config()
1367
1368 port_pkts = []
1369 for ii in range(257):
1370 port_pkts.append(Ether(src=self.pg0.remote_mac,
1371 dst=self.pg0.local_mac) /
1372 IP(dst="10.0.0.3", src="20.0.0.2") /
1373 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001374 Raw(b'\xa5' * 100))
Neale Ranns63480742019-03-13 06:41:52 -07001375
Neale Ranns699bea22022-02-17 09:22:16 +00001376 self.send_and_expect_only(self.pg0, port_pkts, self.pg4)
Neale Ranns63480742019-03-13 06:41:52 -07001377
1378 # bring the link back up
1379 self.pg3.link_up()
1380
1381 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1382 [self.pg3, self.pg4])
Neale Ranns3d5f08a2021-01-22 16:12:38 +00001383 self.assertEqual(len(src_pkts), self.total_len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001384
Neale Ranns30d0fd42017-05-30 07:30:04 -07001385
1386class TestIPVlan0(VppTestCase):
1387 """ IPv4 VLAN-0 """
1388
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001389 @classmethod
1390 def setUpClass(cls):
1391 super(TestIPVlan0, cls).setUpClass()
1392
1393 @classmethod
1394 def tearDownClass(cls):
1395 super(TestIPVlan0, cls).tearDownClass()
1396
Neale Ranns30d0fd42017-05-30 07:30:04 -07001397 def setUp(self):
1398 super(TestIPVlan0, self).setUp()
1399
1400 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001401 mpls_tbl = VppMplsTable(self, 0)
1402 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001403
1404 for i in self.pg_interfaces:
1405 i.admin_up()
1406 i.config_ip4()
1407 i.resolve_arp()
1408 i.enable_mpls()
1409
1410 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001411 for i in self.pg_interfaces:
1412 i.disable_mpls()
1413 i.unconfig_ip4()
1414 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001415 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001416
Neale Ranns30d0fd42017-05-30 07:30:04 -07001417 def test_ip_vlan_0(self):
1418 """ IP VLAN-0 """
1419
1420 pkts = (Ether(src=self.pg0.remote_mac,
1421 dst=self.pg0.local_mac) /
1422 Dot1Q(vlan=0) /
1423 IP(dst=self.pg1.remote_ip4,
1424 src=self.pg0.remote_ip4) /
1425 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001426 Raw(b'\xa5' * 100)) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001427
1428 #
1429 # Expect that packets sent on VLAN-0 are forwarded on the
1430 # main interface.
1431 #
1432 self.send_and_expect(self.pg0, pkts, self.pg1)
1433
1434
Brian Russell318fdb82021-01-19 16:56:32 +00001435class IPPuntSetup(object):
1436 """ Setup for IPv4 Punt Police/Redirect """
Neale Rannsd91c1db2017-07-31 02:30:50 -07001437
Brian Russell318fdb82021-01-19 16:56:32 +00001438 def punt_setup(self):
Pavel Kotucek609e1212018-11-27 09:59:44 +01001439 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001440
1441 for i in self.pg_interfaces:
1442 i.admin_up()
1443 i.config_ip4()
1444 i.resolve_arp()
1445
Neale Ranns68577d22019-06-04 13:31:23 +00001446 # use UDP packet that have a port we need to explicitly
1447 # register to get punted.
1448 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1449 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1450 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1451 punt_udp = {
1452 'type': pt_l4,
1453 'punt': {
1454 'l4': {
1455 'af': af_ip4,
1456 'protocol': udp_proto,
1457 'port': 1234,
1458 }
1459 }
1460 }
1461
1462 self.vapi.set_punt(is_add=1, punt=punt_udp)
1463
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001464 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
1465 punt_udp = {
1466 'type': pt_l4,
1467 'punt': {
1468 'l4': {
1469 'af': af_ip6,
1470 'protocol': udp_proto,
1471 'port': 1236,
1472 }
1473 }
1474 }
1475
1476 self.vapi.set_punt(is_add=1, punt=punt_udp)
1477
Brian Russell318fdb82021-01-19 16:56:32 +00001478 self.pkt = (Ether(src=self.pg0.remote_mac,
1479 dst=self.pg0.local_mac) /
1480 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1481 UDP(sport=1234, dport=1234) /
1482 Raw(b'\xa5' * 100))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001483
Brian Russell318fdb82021-01-19 16:56:32 +00001484 def punt_teardown(self):
1485 for i in self.pg_interfaces:
1486 i.unconfig_ip4()
1487 i.admin_down()
1488
1489
1490class TestIPPunt(IPPuntSetup, VppTestCase):
1491 """ IPv4 Punt Police/Redirect """
1492
1493 def setUp(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001494 super().setUp()
1495 super().punt_setup()
Brian Russell318fdb82021-01-19 16:56:32 +00001496
1497 def tearDown(self):
Klement Sekerafd1f56a2021-11-22 21:25:57 +01001498 super().punt_teardown()
1499 super().tearDown()
1500
1501 def test_ip_punt_api_validation(self):
1502 """ IP punt API parameter validation """
1503
1504 nh_addr = self.pg1.remote_ip4
1505 punt = {"rx_sw_if_index": self.pg0.sw_if_index,
1506 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1507 "n_paths": 1000000,
1508 "paths": []}
1509
1510 with self.assertRaises(vpp_papi.VPPIOError):
1511 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
1512
1513 punt = {"rx_sw_if_index": self.pg0.sw_if_index,
1514 "af": VppEnum.vl_api_address_family_t.ADDRESS_IP4,
1515 "n_paths": 0,
1516 "paths": []}
1517
1518 self.vapi.add_del_ip_punt_redirect_v2(punt=punt, is_add=True)
Brian Russell318fdb82021-01-19 16:56:32 +00001519
1520 def test_ip_punt(self):
1521 """ IP punt police and redirect """
1522
1523 pkts = self.pkt * 1025
Neale Rannsd91c1db2017-07-31 02:30:50 -07001524
1525 #
1526 # Configure a punt redirect via pg1.
1527 #
Ole Troan0bcad322018-12-11 13:04:01 +01001528 nh_addr = self.pg1.remote_ip4
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001529 ip_punt_redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
1530 self.pg1.sw_if_index, nh_addr)
1531 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001532
1533 self.send_and_expect(self.pg0, pkts, self.pg1)
1534
1535 #
1536 # add a policer
1537 #
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001538 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1)
1539 policer.add_vpp_config()
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001540 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1541 ip_punt_policer.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001542
1543 self.vapi.cli("clear trace")
1544 self.pg0.add_stream(pkts)
1545 self.pg_enable_capture(self.pg_interfaces)
1546 self.pg_start()
1547
1548 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001549 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001550 # but not equal to the number sent, since some were policed
1551 #
1552 rx = self.pg1._get_capture(1)
Brian Russelle9887262021-01-27 14:45:22 +00001553
1554 stats = policer.get_stats()
1555
1556 # Single rate policer - expect conform, violate but no exceed
1557 self.assertGreater(stats['conform_packets'], 0)
1558 self.assertEqual(stats['exceed_packets'], 0)
1559 self.assertGreater(stats['violate_packets'], 0)
1560
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001561 self.assertGreater(len(rx), 0)
1562 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001563
1564 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001565 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001566 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001567 ip_punt_policer.remove_vpp_config()
Jakub Grajciarcd01fb42020-03-02 13:16:53 +01001568 policer.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001569 self.send_and_expect(self.pg0, pkts, self.pg1)
1570
1571 #
1572 # remove the redirect. expect full drop.
1573 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001574 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001575 self.send_and_assert_no_replies(self.pg0, pkts,
1576 "IP no punt config")
1577
1578 #
1579 # Add a redirect that is not input port selective
1580 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001581 ip_punt_redirect = VppIpPuntRedirect(self, 0xffffffff,
1582 self.pg1.sw_if_index, nh_addr)
1583 ip_punt_redirect.add_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001584 self.send_and_expect(self.pg0, pkts, self.pg1)
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001585 ip_punt_redirect.remove_vpp_config()
Neale Rannsd91c1db2017-07-31 02:30:50 -07001586
Neale Rannsaa7cfd02022-03-24 12:28:42 +00001587 def test_ip_punt_vrf(self):
1588 """ IP punt/local with VRFs """
1589
1590 # use a punt redirect to test if for-us packets are accepted
1591 pkts = self.pkt * 1025
1592
1593 vlans_pg0 = [VppDot1QSubint(self, self.pg0, v)
1594 for v in range(100, 104)]
1595 vlans_pg1 = [VppDot1QSubint(self, self.pg1, v)
1596 for v in range(100, 104)]
1597 tbl4 = [VppIpTable(self, v).add_vpp_config()
1598 for v in range(100, 104)]
1599 tbl6 = [VppIpTable(self, v, True).add_vpp_config()
1600 for v in range(100, 104)]
1601
1602 for v in vlans_pg0 + vlans_pg1:
1603 v.admin_up()
1604 v.set_table_ip4(v.vlan)
1605 v.set_table_ip6(v.vlan)
1606 v.config_ip4()
1607 v.config_ip6()
1608 v.resolve_arp()
1609 v.resolve_ndp()
1610
1611 [VppIpPuntRedirect
1612 (self,
1613 vlans_pg0[i].sw_if_index,
1614 vlans_pg1[i].sw_if_index,
1615 vlans_pg1[i].remote_ip4).add_vpp_config()
1616 for i in range(4)]
1617 [VppIpPuntRedirect
1618 (self,
1619 vlans_pg0[i].sw_if_index,
1620 vlans_pg1[i].sw_if_index,
1621 vlans_pg1[i].remote_ip6).add_vpp_config()
1622 for i in range(4)]
1623
1624 pkts = [(Ether(src=self.pg0.remote_mac,
1625 dst=self.pg0.local_mac) /
1626 Dot1Q(vlan=i.vlan) /
1627 IP(src=i.remote_ip4,
1628 dst=i.local_ip4) /
1629 UDP(sport=1234, dport=1234) /
1630 Raw(b'\xa5' * 100))
1631 for i in vlans_pg0]
1632
1633 self.send_and_expect(self.pg0, pkts, self.pg1)
1634
1635 #
1636 # IPv4
1637 #
1638
1639 # we reject packets for source addresses in the wrong vlan/VRF
1640 pkts = [(Ether(src=self.pg0.remote_mac,
1641 dst=self.pg0.local_mac) /
1642 Dot1Q(vlan=i.vlan) /
1643 IP(src="1.1.1.1",
1644 dst=i.local_ip4) /
1645 UDP(sport=1234, dport=1234) /
1646 Raw(b'\xa5' * 100))
1647 for i in vlans_pg0]
1648 # single and dual loop
1649 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1650 self.send_and_assert_no_replies(self.pg0, pkts)
1651
1652 self.assert_error_counter_equal(
1653 "/err/ip4-local/ip4 source lookup miss",
1654 len(pkts) + 1)
1655
1656 # using the same source in different tables, should reject
1657 # for the table that the source is not present in
1658 # the first packet in the stream is drop
1659 pkts = [(Ether(src=self.pg0.remote_mac,
1660 dst=self.pg0.local_mac) /
1661 Dot1Q(vlan=i.vlan) /
1662 IP(src=vlans_pg0[0].remote_ip4,
1663 dst=i.local_ip4) /
1664 UDP(sport=1234, dport=1234) /
1665 Raw(b'\xa5' * 100))
1666 for i in vlans_pg0]
1667 # single loop accept and drop
1668 # followed by both in the same frame/loop
1669 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1670 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1671 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1672
1673 # using the same source in different tables, should reject
1674 # for the table that the source is not present in
1675 # the first packet in the stream is accept
1676 pkts = [(Ether(src=self.pg0.remote_mac,
1677 dst=self.pg0.local_mac) /
1678 Dot1Q(vlan=i.vlan) /
1679 IP(src=vlans_pg0[3].remote_ip4,
1680 dst=i.local_ip4) /
1681 UDP(sport=1234, dport=1234) /
1682 Raw(b'\xa5' * 100))
1683 for i in vlans_pg0]
1684
1685 # single loop accept and drop
1686 # followed by both in the same frame/loop
1687 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1688 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1689 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1690
1691 #
1692 # IPv6
1693 #
1694
1695 # we reject packets for source addresses in the wrong vlan/VRF
1696 pkts = [(Ether(src=self.pg0.remote_mac,
1697 dst=self.pg0.local_mac) /
1698 Dot1Q(vlan=i.vlan) /
1699 IPv6(src="1::1",
1700 dst=i.local_ip6) /
1701 UDP(sport=1236, dport=1236) /
1702 Raw(b'\xa5' * 100))
1703 for i in vlans_pg0]
1704 # single and dual loop
1705 self.send_and_assert_no_replies(self.pg0, [pkts[0]])
1706 self.send_and_assert_no_replies(self.pg0, pkts)
1707
1708 self.assert_error_counter_equal(
1709 "/err/ip6-input/ip6 source lookup miss",
1710 len(pkts) + 1)
1711
1712 # using the same source in different tables, should reject
1713 # for the table that the source is not present in
1714 # the first packet in the stream is drop
1715 pkts = [(Ether(src=self.pg0.remote_mac,
1716 dst=self.pg0.local_mac) /
1717 Dot1Q(vlan=i.vlan) /
1718 IPv6(src=vlans_pg0[0].remote_ip6,
1719 dst=i.local_ip6) /
1720 UDP(sport=1236, dport=1236) /
1721 Raw(b'\xa5' * 100))
1722 for i in vlans_pg0]
1723 # single loop accept and drop
1724 # followed by both in the same frame/loop
1725 self.send_and_expect(self.pg0, [pkts[0]], self.pg1)
1726 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1727 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1728
1729 # using the same source in different tables, should reject
1730 # for the table that the source is not present in
1731 # the first packet in the stream is accept
1732 pkts = [(Ether(src=self.pg0.remote_mac,
1733 dst=self.pg0.local_mac) /
1734 Dot1Q(vlan=i.vlan) /
1735 IPv6(src=vlans_pg0[3].remote_ip6,
1736 dst=i.local_ip6) /
1737 UDP(sport=1236, dport=1236) /
1738 Raw(b'\xa5' * 100))
1739 for i in vlans_pg0]
1740
1741 # single loop accept and drop
1742 # followed by both in the same frame/loop
1743 self.send_and_expect(self.pg0, [pkts[3]], self.pg1)
1744 self.send_and_assert_no_replies(self.pg0, [pkts[1]])
1745 self.send_and_expect(self.pg0, pkts * 4, self.pg1, n_rx=4)
1746
1747 for v in vlans_pg0 + vlans_pg1:
1748 v.unconfig_ip4()
1749 v.unconfig_ip6()
1750 v.set_table_ip4(0)
1751 v.set_table_ip6(0)
1752
Pavel Kotucek609e1212018-11-27 09:59:44 +01001753 def test_ip_punt_dump(self):
1754 """ IP4 punt redirect dump"""
1755
1756 #
1757 # Configure a punt redirects
1758 #
Ole Troan0bcad322018-12-11 13:04:01 +01001759 nh_address = self.pg3.remote_ip4
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001760 ipr_03 = VppIpPuntRedirect(self, self.pg0.sw_if_index,
1761 self.pg3.sw_if_index, nh_address)
1762 ipr_13 = VppIpPuntRedirect(self, self.pg1.sw_if_index,
1763 self.pg3.sw_if_index, nh_address)
1764 ipr_23 = VppIpPuntRedirect(self, self.pg2.sw_if_index,
1765 self.pg3.sw_if_index, "0.0.0.0")
1766 ipr_03.add_vpp_config()
1767 ipr_13.add_vpp_config()
1768 ipr_23.add_vpp_config()
Pavel Kotucek609e1212018-11-27 09:59:44 +01001769
1770 #
1771 # Dump pg0 punt redirects
1772 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +01001773 self.assertTrue(ipr_03.query_vpp_config())
1774 self.assertTrue(ipr_13.query_vpp_config())
1775 self.assertTrue(ipr_23.query_vpp_config())
Pavel Kotucek609e1212018-11-27 09:59:44 +01001776
1777 #
1778 # Dump punt redirects for all interfaces
1779 #
1780 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1781 self.assertEqual(len(punts), 3)
1782 for p in punts:
1783 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001784 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1785 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001786
Neale Rannsd91c1db2017-07-31 02:30:50 -07001787
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001788class TestIPPuntHandoff(IPPuntSetup, VppTestCase):
1789 """ IPv4 Punt Policer thread handoff """
Klement Sekera8d815022021-03-15 16:58:10 +01001790 vpp_worker_count = 2
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001791
1792 def setUp(self):
1793 super(TestIPPuntHandoff, self).setUp()
1794 super(TestIPPuntHandoff, self).punt_setup()
1795
1796 def tearDown(self):
1797 super(TestIPPuntHandoff, self).punt_teardown()
1798 super(TestIPPuntHandoff, self).tearDown()
1799
1800 def test_ip_punt_policer_handoff(self):
1801 """ IP4 punt policer thread handoff """
1802 pkts = self.pkt * NUM_PKTS
1803
1804 #
1805 # Configure a punt redirect via pg1.
1806 #
1807 nh_addr = self.pg1.remote_ip4
1808 ip_punt_redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
1809 self.pg1.sw_if_index, nh_addr)
1810 ip_punt_redirect.add_vpp_config()
1811
1812 action_tx = PolicerAction(
1813 VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT,
1814 0)
1815 #
1816 # This policer drops no packets, we are just
1817 # testing that they get to the right thread.
1818 #
1819 policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, 1,
1820 0, 0, False, action_tx, action_tx, action_tx)
1821 policer.add_vpp_config()
1822 ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index)
1823 ip_punt_policer.add_vpp_config()
1824
1825 for worker in [0, 1]:
1826 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
Brian Russellbb983142021-02-10 13:56:06 +00001827 self.logger.debug(self.vapi.cli("show trace max 100"))
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001828
Brian Russelle9887262021-01-27 14:45:22 +00001829 # Combined stats, all threads
1830 stats = policer.get_stats()
1831
1832 # Single rate policer - expect conform, violate but no exceed
1833 self.assertGreater(stats['conform_packets'], 0)
1834 self.assertEqual(stats['exceed_packets'], 0)
1835 self.assertGreater(stats['violate_packets'], 0)
1836
1837 # Worker 0, should have done all the policing
1838 stats0 = policer.get_stats(worker=0)
1839 self.assertEqual(stats, stats0)
1840
1841 # Worker 1, should have handed everything off
1842 stats1 = policer.get_stats(worker=1)
1843 self.assertEqual(stats1['conform_packets'], 0)
1844 self.assertEqual(stats1['exceed_packets'], 0)
1845 self.assertEqual(stats1['violate_packets'], 0)
1846
Brian Russellbb983142021-02-10 13:56:06 +00001847 # Bind the policer to worker 1 and repeat
1848 policer.bind_vpp_config(1, True)
1849 for worker in [0, 1]:
1850 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
1851 self.logger.debug(self.vapi.cli("show trace max 100"))
1852
1853 # The 2 workers should now have policed the same amount
1854 stats = policer.get_stats()
1855 stats0 = policer.get_stats(worker=0)
1856 stats1 = policer.get_stats(worker=1)
1857
1858 self.assertGreater(stats0['conform_packets'], 0)
1859 self.assertEqual(stats0['exceed_packets'], 0)
1860 self.assertGreater(stats0['violate_packets'], 0)
1861
1862 self.assertGreater(stats1['conform_packets'], 0)
1863 self.assertEqual(stats1['exceed_packets'], 0)
1864 self.assertGreater(stats1['violate_packets'], 0)
1865
1866 self.assertEqual(stats0['conform_packets'] + stats1['conform_packets'],
1867 stats['conform_packets'])
1868
1869 self.assertEqual(stats0['violate_packets'] + stats1['violate_packets'],
1870 stats['violate_packets'])
1871
1872 # Unbind the policer and repeat
1873 policer.bind_vpp_config(1, False)
1874 for worker in [0, 1]:
1875 self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker)
1876 self.logger.debug(self.vapi.cli("show trace max 100"))
1877
1878 # The policer should auto-bind to worker 0 when packets arrive
1879 stats = policer.get_stats()
1880 stats0new = policer.get_stats(worker=0)
1881 stats1new = policer.get_stats(worker=1)
1882
1883 self.assertGreater(stats0new['conform_packets'],
1884 stats0['conform_packets'])
1885 self.assertEqual(stats0new['exceed_packets'], 0)
1886 self.assertGreater(stats0new['violate_packets'],
1887 stats0['violate_packets'])
1888
1889 self.assertEqual(stats1, stats1new)
1890
Brian Russellc8f3cdf2021-01-19 16:57:42 +00001891 #
1892 # Clean up
1893 #
1894 ip_punt_policer.remove_vpp_config()
1895 policer.remove_vpp_config()
1896 ip_punt_redirect.remove_vpp_config()
1897
1898
Neale Ranns054c03a2017-10-13 05:15:07 -07001899class TestIPDeag(VppTestCase):
1900 """ IPv4 Deaggregate Routes """
1901
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001902 @classmethod
1903 def setUpClass(cls):
1904 super(TestIPDeag, cls).setUpClass()
1905
1906 @classmethod
1907 def tearDownClass(cls):
1908 super(TestIPDeag, cls).tearDownClass()
1909
Neale Ranns054c03a2017-10-13 05:15:07 -07001910 def setUp(self):
1911 super(TestIPDeag, self).setUp()
1912
1913 self.create_pg_interfaces(range(3))
1914
1915 for i in self.pg_interfaces:
1916 i.admin_up()
1917 i.config_ip4()
1918 i.resolve_arp()
1919
1920 def tearDown(self):
1921 super(TestIPDeag, self).tearDown()
1922 for i in self.pg_interfaces:
1923 i.unconfig_ip4()
1924 i.admin_down()
1925
Neale Ranns054c03a2017-10-13 05:15:07 -07001926 def test_ip_deag(self):
1927 """ IP Deag Routes """
1928
1929 #
1930 # Create a table to be used for:
1931 # 1 - another destination address lookup
1932 # 2 - a source address lookup
1933 #
1934 table_dst = VppIpTable(self, 1)
1935 table_src = VppIpTable(self, 2)
1936 table_dst.add_vpp_config()
1937 table_src.add_vpp_config()
1938
1939 #
1940 # Add a route in the default table to point to a deag/
1941 # second lookup in each of these tables
1942 #
1943 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1944 [VppRoutePath("0.0.0.0",
1945 0xffffffff,
1946 nh_table_id=1)])
Neale Ranns097fa662018-05-01 05:17:55 -07001947 route_to_src = VppIpRoute(
1948 self, "1.1.1.2", 32,
1949 [VppRoutePath("0.0.0.0",
1950 0xffffffff,
1951 nh_table_id=2,
1952 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP)])
Neale Ranns054c03a2017-10-13 05:15:07 -07001953 route_to_dst.add_vpp_config()
1954 route_to_src.add_vpp_config()
1955
1956 #
1957 # packets to these destination are dropped, since they'll
1958 # hit the respective default routes in the second table
1959 #
1960 p_dst = (Ether(src=self.pg0.remote_mac,
1961 dst=self.pg0.local_mac) /
1962 IP(src="5.5.5.5", dst="1.1.1.1") /
1963 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001964 Raw(b'\xa5' * 100))
Neale Ranns054c03a2017-10-13 05:15:07 -07001965 p_src = (Ether(src=self.pg0.remote_mac,
1966 dst=self.pg0.local_mac) /
1967 IP(src="2.2.2.2", dst="1.1.1.2") /
1968 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001969 Raw(b'\xa5' * 100))
Neale Ranns054c03a2017-10-13 05:15:07 -07001970 pkts_dst = p_dst * 257
1971 pkts_src = p_src * 257
1972
1973 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1974 "IP in dst table")
1975 self.send_and_assert_no_replies(self.pg0, pkts_src,
1976 "IP in src table")
1977
1978 #
1979 # add a route in the dst table to forward via pg1
1980 #
1981 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1982 [VppRoutePath(self.pg1.remote_ip4,
1983 self.pg1.sw_if_index)],
1984 table_id=1)
1985 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001986
Neale Ranns054c03a2017-10-13 05:15:07 -07001987 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1988
1989 #
1990 # add a route in the src table to forward via pg2
1991 #
1992 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1993 [VppRoutePath(self.pg2.remote_ip4,
1994 self.pg2.sw_if_index)],
1995 table_id=2)
1996 route_in_src.add_vpp_config()
1997 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1998
Neale Rannsce9e0b42018-08-01 12:53:17 -07001999 #
2000 # loop in the lookup DP
2001 #
2002 route_loop = VppIpRoute(self, "2.2.2.3", 32,
2003 [VppRoutePath("0.0.0.0",
2004 0xffffffff,
2005 nh_table_id=0)])
2006 route_loop.add_vpp_config()
2007
2008 p_l = (Ether(src=self.pg0.remote_mac,
2009 dst=self.pg0.local_mac) /
2010 IP(src="2.2.2.4", dst="2.2.2.3") /
2011 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002012 Raw(b'\xa5' * 100))
Neale Rannsce9e0b42018-08-01 12:53:17 -07002013
2014 self.send_and_assert_no_replies(self.pg0, p_l * 257,
2015 "IP lookup loop")
2016
Neale Ranns054c03a2017-10-13 05:15:07 -07002017
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002018class TestIPInput(VppTestCase):
2019 """ IPv4 Input Exceptions """
2020
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002021 @classmethod
2022 def setUpClass(cls):
2023 super(TestIPInput, cls).setUpClass()
2024
2025 @classmethod
2026 def tearDownClass(cls):
2027 super(TestIPInput, cls).tearDownClass()
2028
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002029 def setUp(self):
2030 super(TestIPInput, self).setUp()
2031
2032 self.create_pg_interfaces(range(2))
2033
2034 for i in self.pg_interfaces:
2035 i.admin_up()
2036 i.config_ip4()
2037 i.resolve_arp()
2038
2039 def tearDown(self):
2040 super(TestIPInput, self).tearDown()
2041 for i in self.pg_interfaces:
2042 i.unconfig_ip4()
2043 i.admin_down()
2044
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002045 def test_ip_input(self):
2046 """ IP Input Exceptions """
2047
2048 # i can't find a way in scapy to construct an IP packet
2049 # with a length less than the IP header length
2050
2051 #
2052 # Packet too short - this is forwarded
2053 #
2054 p_short = (Ether(src=self.pg0.remote_mac,
2055 dst=self.pg0.local_mac) /
2056 IP(src=self.pg0.remote_ip4,
2057 dst=self.pg1.remote_ip4,
2058 len=40) /
2059 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002060 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002061
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002062 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002063
2064 #
2065 # Packet too long - this is dropped
2066 #
2067 p_long = (Ether(src=self.pg0.remote_mac,
2068 dst=self.pg0.local_mac) /
2069 IP(src=self.pg0.remote_ip4,
2070 dst=self.pg1.remote_ip4,
2071 len=400) /
2072 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002073 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002074
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002075 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002076 "too long")
2077
2078 #
2079 # bad chksum - this is dropped
2080 #
2081 p_chksum = (Ether(src=self.pg0.remote_mac,
2082 dst=self.pg0.local_mac) /
2083 IP(src=self.pg0.remote_ip4,
2084 dst=self.pg1.remote_ip4,
2085 chksum=400) /
2086 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002087 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002088
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002089 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002090 "bad checksum")
2091
2092 #
2093 # bad version - this is dropped
2094 #
2095 p_ver = (Ether(src=self.pg0.remote_mac,
2096 dst=self.pg0.local_mac) /
2097 IP(src=self.pg0.remote_ip4,
2098 dst=self.pg1.remote_ip4,
2099 version=3) /
2100 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002101 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002102
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002103 rx = self.send_and_assert_no_replies(self.pg0, p_ver * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002104 "funky version")
2105
2106 #
2107 # fragment offset 1 - this is dropped
2108 #
2109 p_frag = (Ether(src=self.pg0.remote_mac,
2110 dst=self.pg0.local_mac) /
2111 IP(src=self.pg0.remote_ip4,
2112 dst=self.pg1.remote_ip4,
2113 frag=1) /
2114 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002115 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002116
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002117 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002118 "frag offset")
2119
2120 #
2121 # TTL expired packet
2122 #
2123 p_ttl = (Ether(src=self.pg0.remote_mac,
2124 dst=self.pg0.local_mac) /
2125 IP(src=self.pg0.remote_ip4,
2126 dst=self.pg1.remote_ip4,
2127 ttl=1) /
2128 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002129 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002130
Neale Ranns5c6dd172022-02-17 09:08:47 +00002131 rxs = self.send_and_expect_some(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002132
Neale Ranns5c6dd172022-02-17 09:08:47 +00002133 for rx in rxs:
2134 icmp = rx[ICMP]
2135 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
2136 self.assertEqual(icmpcodes[icmp.type][icmp.code],
2137 "ttl-zero-during-transit")
2138 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2139 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002140
Neale Rannsffd78d12018-02-09 06:05:16 -08002141 #
2142 # MTU exceeded
2143 #
2144 p_mtu = (Ether(src=self.pg0.remote_mac,
2145 dst=self.pg0.local_mac) /
2146 IP(src=self.pg0.remote_ip4,
2147 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02002148 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08002149 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002150 Raw(b'\xa5' * 2000))
Neale Rannsffd78d12018-02-09 06:05:16 -08002151
Ole Troand7231612018-06-07 10:17:57 +02002152 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08002153
Neale Ranns5c6dd172022-02-17 09:08:47 +00002154 rxs = self.send_and_expect_some(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08002155
Neale Ranns5c6dd172022-02-17 09:08:47 +00002156 for rx in rxs:
2157 icmp = rx[ICMP]
2158 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
2159 self.assertEqual(icmpcodes[icmp.type][icmp.code],
2160 "fragmentation-needed")
Neale Rannsfbc633f2022-03-18 13:05:09 +00002161 self.assertEqual(icmp.nexthopmtu, 1500)
Neale Ranns5c6dd172022-02-17 09:08:47 +00002162 self.assertEqual(icmp.src, self.pg0.remote_ip4)
2163 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
Neale Rannsffd78d12018-02-09 06:05:16 -08002164
Ole Troand7231612018-06-07 10:17:57 +02002165 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002166 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08002167
Ole Troand7231612018-06-07 10:17:57 +02002168 # Reset MTU for subsequent tests
2169 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07002170
Neale Rannsbe2286b2018-12-09 12:54:51 -08002171 #
2172 # source address 0.0.0.0 and 25.255.255.255 and for-us
2173 #
2174 p_s0 = (Ether(src=self.pg0.remote_mac,
2175 dst=self.pg0.local_mac) /
2176 IP(src="0.0.0.0",
2177 dst=self.pg0.local_ip4) /
2178 ICMP(id=4, seq=4) /
Ole Troan5e56f752019-10-21 21:06:52 +02002179 Raw(load=b'\x0a' * 18))
Neale Rannsbe2286b2018-12-09 12:54:51 -08002180 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2181
2182 p_s0 = (Ether(src=self.pg0.remote_mac,
2183 dst=self.pg0.local_mac) /
2184 IP(src="255.255.255.255",
2185 dst=self.pg0.local_ip4) /
2186 ICMP(id=4, seq=4) /
Ole Troan5e56f752019-10-21 21:06:52 +02002187 Raw(load=b'\x0a' * 18))
Neale Rannsbe2286b2018-12-09 12:54:51 -08002188 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
2189
Neale Ranns1855b8e2018-07-11 10:31:26 -07002190
2191class TestIPDirectedBroadcast(VppTestCase):
2192 """ IPv4 Directed Broadcast """
2193
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002194 @classmethod
2195 def setUpClass(cls):
2196 super(TestIPDirectedBroadcast, cls).setUpClass()
2197
2198 @classmethod
2199 def tearDownClass(cls):
2200 super(TestIPDirectedBroadcast, cls).tearDownClass()
2201
Neale Ranns1855b8e2018-07-11 10:31:26 -07002202 def setUp(self):
2203 super(TestIPDirectedBroadcast, self).setUp()
2204
2205 self.create_pg_interfaces(range(2))
2206
2207 for i in self.pg_interfaces:
2208 i.admin_up()
2209
2210 def tearDown(self):
2211 super(TestIPDirectedBroadcast, self).tearDown()
2212 for i in self.pg_interfaces:
2213 i.admin_down()
2214
2215 def test_ip_input(self):
2216 """ IP Directed Broadcast """
2217
2218 #
2219 # set the directed broadcast on pg0 first, then config IP4 addresses
2220 # for pg1 directed broadcast is always disabled
2221 self.vapi.sw_interface_set_ip_directed_broadcast(
2222 self.pg0.sw_if_index, 1)
2223
2224 p0 = (Ether(src=self.pg1.remote_mac,
2225 dst=self.pg1.local_mac) /
2226 IP(src="1.1.1.1",
2227 dst=self.pg0._local_ip4_bcast) /
2228 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002229 Raw(b'\xa5' * 2000))
Neale Ranns1855b8e2018-07-11 10:31:26 -07002230 p1 = (Ether(src=self.pg0.remote_mac,
2231 dst=self.pg0.local_mac) /
2232 IP(src="1.1.1.1",
2233 dst=self.pg1._local_ip4_bcast) /
2234 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002235 Raw(b'\xa5' * 2000))
Neale Ranns1855b8e2018-07-11 10:31:26 -07002236
2237 self.pg0.config_ip4()
2238 self.pg0.resolve_arp()
2239 self.pg1.config_ip4()
2240 self.pg1.resolve_arp()
2241
2242 #
2243 # test packet is L2 broadcast
2244 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002245 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002246 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
2247
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002248 self.send_and_assert_no_replies(self.pg0, p1 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07002249 "directed broadcast disabled")
2250
2251 #
2252 # toggle directed broadcast on pg0
2253 #
2254 self.vapi.sw_interface_set_ip_directed_broadcast(
2255 self.pg0.sw_if_index, 0)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002256 self.send_and_assert_no_replies(self.pg1, p0 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07002257 "directed broadcast disabled")
2258
2259 self.vapi.sw_interface_set_ip_directed_broadcast(
2260 self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002261 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07002262
2263 self.pg0.unconfig_ip4()
2264 self.pg1.unconfig_ip4()
2265
2266
mu.duojiao59a82952018-10-11 14:27:30 +08002267class TestIPLPM(VppTestCase):
2268 """ IPv4 longest Prefix Match """
2269
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002270 @classmethod
2271 def setUpClass(cls):
2272 super(TestIPLPM, cls).setUpClass()
2273
2274 @classmethod
2275 def tearDownClass(cls):
2276 super(TestIPLPM, cls).tearDownClass()
2277
mu.duojiao59a82952018-10-11 14:27:30 +08002278 def setUp(self):
2279 super(TestIPLPM, self).setUp()
2280
2281 self.create_pg_interfaces(range(4))
2282
2283 for i in self.pg_interfaces:
2284 i.admin_up()
2285 i.config_ip4()
2286 i.resolve_arp()
2287
2288 def tearDown(self):
2289 super(TestIPLPM, self).tearDown()
2290 for i in self.pg_interfaces:
2291 i.admin_down()
2292 i.unconfig_ip4()
2293
2294 def test_ip_lpm(self):
2295 """ IP longest Prefix Match """
2296
2297 s_24 = VppIpRoute(self, "10.1.2.0", 24,
2298 [VppRoutePath(self.pg1.remote_ip4,
2299 self.pg1.sw_if_index)])
2300 s_24.add_vpp_config()
2301 s_8 = VppIpRoute(self, "10.0.0.0", 8,
2302 [VppRoutePath(self.pg2.remote_ip4,
2303 self.pg2.sw_if_index)])
2304 s_8.add_vpp_config()
2305
2306 p_8 = (Ether(src=self.pg0.remote_mac,
2307 dst=self.pg0.local_mac) /
2308 IP(src="1.1.1.1",
2309 dst="10.1.1.1") /
2310 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002311 Raw(b'\xa5' * 2000))
mu.duojiao59a82952018-10-11 14:27:30 +08002312 p_24 = (Ether(src=self.pg0.remote_mac,
2313 dst=self.pg0.local_mac) /
2314 IP(src="1.1.1.1",
2315 dst="10.1.2.1") /
2316 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02002317 Raw(b'\xa5' * 2000))
mu.duojiao59a82952018-10-11 14:27:30 +08002318
2319 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04002320 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
2321 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08002322
2323
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002324@tag_fixme_vpp_workers
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002325class TestIPv4Frag(VppTestCase):
2326 """ IPv4 fragmentation """
2327
2328 @classmethod
2329 def setUpClass(cls):
2330 super(TestIPv4Frag, cls).setUpClass()
2331
2332 cls.create_pg_interfaces([0, 1])
2333 cls.src_if = cls.pg0
2334 cls.dst_if = cls.pg1
2335
2336 # setup all interfaces
2337 for i in cls.pg_interfaces:
2338 i.admin_up()
2339 i.config_ip4()
2340 i.resolve_arp()
2341
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07002342 @classmethod
2343 def tearDownClass(cls):
2344 super(TestIPv4Frag, cls).tearDownClass()
2345
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002346 def test_frag_large_packets(self):
2347 """ Fragmentation of large packets """
2348
Neale Ranns0b6a8572019-10-30 17:34:14 +00002349 self.vapi.cli("adjacency counters enable")
2350
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002351 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
2352 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
2353 UDP(sport=1234, dport=5678) / Raw())
2354 self.extend_packet(p, 6000, "abcde")
2355 saved_payload = p[Raw].load
2356
Neale Ranns0b6a8572019-10-30 17:34:14 +00002357 nbr = VppNeighbor(self,
2358 self.dst_if.sw_if_index,
2359 self.dst_if.remote_mac,
2360 self.dst_if.remote_ip4).add_vpp_config()
2361
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002362 # Force fragmentation by setting MTU of output interface
2363 # lower than packet size
2364 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
2365 [5000, 0, 0, 0])
2366
2367 self.pg_enable_capture()
2368 self.src_if.add_stream(p)
2369 self.pg_start()
2370
2371 # Expecting 3 fragments because size of created fragments currently
2372 # cannot be larger then VPP buffer size (which is 2048)
2373 packets = self.dst_if.get_capture(3)
2374
Neale Ranns0b6a8572019-10-30 17:34:14 +00002375 # we should show 3 packets thru the neighbor
2376 self.assertEqual(3, nbr.get_stats()['packets'])
2377
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002378 # Assume VPP sends the fragments in order
Ole Troan6ed154f2019-10-15 19:31:55 +02002379 payload = b''
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02002380 for p in packets:
2381 payload_offset = p.frag * 8
2382 if payload_offset > 0:
2383 payload_offset -= 8 # UDP header is not in payload
2384 self.assert_equal(payload_offset, len(payload))
2385 payload += p[Raw].load
2386 self.assert_equal(payload, saved_payload, "payload")
2387
2388
Neale Ranns9db6ada2019-11-08 12:42:31 +00002389class TestIPReplace(VppTestCase):
2390 """ IPv4 Table Replace """
2391
2392 @classmethod
2393 def setUpClass(cls):
2394 super(TestIPReplace, cls).setUpClass()
2395
2396 @classmethod
2397 def tearDownClass(cls):
2398 super(TestIPReplace, cls).tearDownClass()
2399
2400 def setUp(self):
2401 super(TestIPReplace, self).setUp()
2402
2403 self.create_pg_interfaces(range(4))
2404
2405 table_id = 1
2406 self.tables = []
2407
2408 for i in self.pg_interfaces:
2409 i.admin_up()
2410 i.config_ip4()
2411 i.resolve_arp()
2412 i.generate_remote_hosts(2)
2413 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2414 table_id += 1
2415
2416 def tearDown(self):
2417 super(TestIPReplace, self).tearDown()
2418 for i in self.pg_interfaces:
2419 i.admin_down()
2420 i.unconfig_ip4()
2421
2422 def test_replace(self):
2423 """ IP Table Replace """
2424
Neale Ranns990f6942020-10-20 07:20:17 +00002425 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
2426 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
Neale Ranns9db6ada2019-11-08 12:42:31 +00002427 N_ROUTES = 20
2428 links = [self.pg0, self.pg1, self.pg2, self.pg3]
2429 routes = [[], [], [], []]
2430
2431 # load up the tables with some routes
2432 for ii, t in enumerate(self.tables):
2433 for jj in range(N_ROUTES):
2434 uni = VppIpRoute(
2435 self, "10.0.0.%d" % jj, 32,
2436 [VppRoutePath(links[ii].remote_hosts[0].ip4,
2437 links[ii].sw_if_index),
2438 VppRoutePath(links[ii].remote_hosts[1].ip4,
2439 links[ii].sw_if_index)],
2440 table_id=t.table_id).add_vpp_config()
2441 multi = VppIpMRoute(
2442 self, "0.0.0.0",
2443 "239.0.0.%d" % jj, 32,
Neale Ranns990f6942020-10-20 07:20:17 +00002444 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns9db6ada2019-11-08 12:42:31 +00002445 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00002446 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns9db6ada2019-11-08 12:42:31 +00002447 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00002448 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns9db6ada2019-11-08 12:42:31 +00002449 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00002450 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns9db6ada2019-11-08 12:42:31 +00002451 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00002452 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)],
Neale Ranns9db6ada2019-11-08 12:42:31 +00002453 table_id=t.table_id).add_vpp_config()
2454 routes[ii].append({'uni': uni,
2455 'multi': multi})
2456
2457 #
2458 # replace the tables a few times
2459 #
2460 for kk in range(3):
2461 # replace_begin each table
2462 for t in self.tables:
2463 t.replace_begin()
2464
2465 # all the routes are still there
2466 for ii, t in enumerate(self.tables):
2467 dump = t.dump()
2468 mdump = t.mdump()
2469 for r in routes[ii]:
2470 self.assertTrue(find_route_in_dump(dump, r['uni'], t))
2471 self.assertTrue(find_mroute_in_dump(mdump, r['multi'], t))
2472
2473 # redownload the even numbered routes
2474 for ii, t in enumerate(self.tables):
2475 for jj in range(0, N_ROUTES, 2):
2476 routes[ii][jj]['uni'].add_vpp_config()
2477 routes[ii][jj]['multi'].add_vpp_config()
2478
2479 # signal each table replace_end
2480 for t in self.tables:
2481 t.replace_end()
2482
2483 # we should find the even routes, but not the odd
2484 for ii, t in enumerate(self.tables):
2485 dump = t.dump()
2486 mdump = t.mdump()
2487 for jj in range(0, N_ROUTES, 2):
2488 self.assertTrue(find_route_in_dump(
2489 dump, routes[ii][jj]['uni'], t))
2490 self.assertTrue(find_mroute_in_dump(
2491 mdump, routes[ii][jj]['multi'], t))
2492 for jj in range(1, N_ROUTES - 1, 2):
2493 self.assertFalse(find_route_in_dump(
2494 dump, routes[ii][jj]['uni'], t))
2495 self.assertFalse(find_mroute_in_dump(
2496 mdump, routes[ii][jj]['multi'], t))
2497
2498 # reload all the routes
2499 for ii, t in enumerate(self.tables):
2500 for r in routes[ii]:
2501 r['uni'].add_vpp_config()
2502 r['multi'].add_vpp_config()
2503
2504 # all the routes are still there
2505 for ii, t in enumerate(self.tables):
2506 dump = t.dump()
2507 mdump = t.mdump()
2508 for r in routes[ii]:
2509 self.assertTrue(find_route_in_dump(dump, r['uni'], t))
2510 self.assertTrue(find_mroute_in_dump(mdump, r['multi'], t))
2511
2512 #
2513 # finally flush the tables for good measure
2514 #
2515 for t in self.tables:
2516 t.flush()
2517 self.assertEqual(len(t.dump()), 5)
Neale Ranns03c254e2020-03-17 14:25:10 +00002518 self.assertEqual(len(t.mdump()), 3)
Neale Ranns9db6ada2019-11-08 12:42:31 +00002519
2520
Neale Ranns9efcee62019-11-26 19:30:08 +00002521class TestIPCover(VppTestCase):
2522 """ IPv4 Table Cover """
2523
2524 @classmethod
2525 def setUpClass(cls):
2526 super(TestIPCover, cls).setUpClass()
2527
2528 @classmethod
2529 def tearDownClass(cls):
2530 super(TestIPCover, cls).tearDownClass()
2531
2532 def setUp(self):
2533 super(TestIPCover, self).setUp()
2534
2535 self.create_pg_interfaces(range(4))
2536
2537 table_id = 1
2538 self.tables = []
2539
2540 for i in self.pg_interfaces:
2541 i.admin_up()
2542 i.config_ip4()
2543 i.resolve_arp()
2544 i.generate_remote_hosts(2)
2545 self.tables.append(VppIpTable(self, table_id).add_vpp_config())
2546 table_id += 1
2547
2548 def tearDown(self):
2549 super(TestIPCover, self).tearDown()
2550 for i in self.pg_interfaces:
2551 i.admin_down()
2552 i.unconfig_ip4()
2553
2554 def test_cover(self):
2555 """ IP Table Cover """
2556
2557 # add a loop back with a /32 prefix
2558 lo = VppLoInterface(self)
2559 lo.admin_up()
2560 a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
2561
2562 # add a neighbour that matches the loopback's /32
2563 nbr = VppNeighbor(self,
2564 lo.sw_if_index,
2565 lo.remote_mac,
2566 "127.0.0.1").add_vpp_config()
2567
2568 # add the default route which will be the cover for /32
2569 r = VppIpRoute(self, "0.0.0.0", 0,
2570 [VppRoutePath("127.0.0.1",
2571 lo.sw_if_index)],
2572 register=False).add_vpp_config()
2573
2574 # add/remove/add a longer mask cover
Neale Ranns87866032020-11-25 09:14:22 +00002575 r8 = VppIpRoute(self, "127.0.0.0", 8,
2576 [VppRoutePath("127.0.0.1",
2577 lo.sw_if_index)]).add_vpp_config()
2578 r8.remove_vpp_config()
2579 r8.add_vpp_config()
2580 r8.remove_vpp_config()
Neale Ranns9efcee62019-11-26 19:30:08 +00002581
2582 # remove the default route
2583 r.remove_vpp_config()
2584
Neale Ranns87866032020-11-25 09:14:22 +00002585 # remove the interface prefix
2586 a.remove_vpp_config()
2587
Neale Ranns59f71132020-04-08 12:19:38 +00002588
2589class TestIP4Replace(VppTestCase):
2590 """ IPv4 Interface Address Replace """
2591
2592 @classmethod
2593 def setUpClass(cls):
2594 super(TestIP4Replace, cls).setUpClass()
2595
2596 @classmethod
2597 def tearDownClass(cls):
2598 super(TestIP4Replace, cls).tearDownClass()
2599
2600 def setUp(self):
2601 super(TestIP4Replace, self).setUp()
2602
2603 self.create_pg_interfaces(range(4))
2604
2605 for i in self.pg_interfaces:
2606 i.admin_up()
2607
2608 def tearDown(self):
2609 super(TestIP4Replace, self).tearDown()
2610 for i in self.pg_interfaces:
2611 i.admin_down()
2612
2613 def get_n_pfxs(self, intf):
2614 return len(self.vapi.ip_address_dump(intf.sw_if_index))
2615
2616 def test_replace(self):
2617 """ IP interface address replace """
2618
2619 intf_pfxs = [[], [], [], []]
2620
2621 # add prefixes to each of the interfaces
2622 for i in range(len(self.pg_interfaces)):
2623 intf = self.pg_interfaces[i]
2624
2625 # 172.16.x.1/24
2626 addr = "172.16.%d.1" % intf.sw_if_index
2627 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2628 intf_pfxs[i].append(a)
2629
2630 # 172.16.x.2/24 - a different address in the same subnet as above
2631 addr = "172.16.%d.2" % intf.sw_if_index
2632 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2633 intf_pfxs[i].append(a)
2634
2635 # 172.15.x.2/24 - a different address and subnet
2636 addr = "172.15.%d.2" % intf.sw_if_index
2637 a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2638 intf_pfxs[i].append(a)
2639
2640 # a dump should n_address in it
2641 for intf in self.pg_interfaces:
2642 self.assertEqual(self.get_n_pfxs(intf), 3)
2643
2644 #
2645 # remove all the address thru a replace
2646 #
2647 self.vapi.sw_interface_address_replace_begin()
2648 self.vapi.sw_interface_address_replace_end()
2649 for intf in self.pg_interfaces:
2650 self.assertEqual(self.get_n_pfxs(intf), 0)
2651
2652 #
2653 # add all the interface addresses back
2654 #
2655 for p in intf_pfxs:
2656 for v in p:
2657 v.add_vpp_config()
2658 for intf in self.pg_interfaces:
2659 self.assertEqual(self.get_n_pfxs(intf), 3)
2660
2661 #
2662 # replace again, but this time update/re-add the address on the first
2663 # two interfaces
2664 #
2665 self.vapi.sw_interface_address_replace_begin()
2666
2667 for p in intf_pfxs[:2]:
2668 for v in p:
2669 v.add_vpp_config()
2670
2671 self.vapi.sw_interface_address_replace_end()
2672
2673 # on the first two the address still exist,
2674 # on the other two they do not
2675 for intf in self.pg_interfaces[:2]:
2676 self.assertEqual(self.get_n_pfxs(intf), 3)
2677 for p in intf_pfxs[:2]:
2678 for v in p:
2679 self.assertTrue(v.query_vpp_config())
2680 for intf in self.pg_interfaces[2:]:
2681 self.assertEqual(self.get_n_pfxs(intf), 0)
2682
2683 #
2684 # add all the interface addresses back on the last two
2685 #
2686 for p in intf_pfxs[2:]:
2687 for v in p:
2688 v.add_vpp_config()
2689 for intf in self.pg_interfaces:
2690 self.assertEqual(self.get_n_pfxs(intf), 3)
2691
2692 #
2693 # replace again, this time add different prefixes on all the interfaces
2694 #
2695 self.vapi.sw_interface_address_replace_begin()
2696
2697 pfxs = []
2698 for intf in self.pg_interfaces:
2699 # 172.18.x.1/24
2700 addr = "172.18.%d.1" % intf.sw_if_index
2701 pfxs.append(VppIpInterfaceAddress(self, intf, addr,
2702 24).add_vpp_config())
2703
2704 self.vapi.sw_interface_address_replace_end()
2705
2706 # only .18 should exist on each interface
2707 for intf in self.pg_interfaces:
2708 self.assertEqual(self.get_n_pfxs(intf), 1)
2709 for pfx in pfxs:
2710 self.assertTrue(pfx.query_vpp_config())
2711
2712 #
2713 # remove everything
2714 #
2715 self.vapi.sw_interface_address_replace_begin()
2716 self.vapi.sw_interface_address_replace_end()
2717 for intf in self.pg_interfaces:
2718 self.assertEqual(self.get_n_pfxs(intf), 0)
2719
2720 #
2721 # add prefixes to each interface. post-begin add the prefix from
2722 # interface X onto interface Y. this would normally be an error
2723 # since it would generate a 'duplicate address' warning. but in
2724 # this case, since what is newly downloaded is sane, it's ok
2725 #
2726 for intf in self.pg_interfaces:
2727 # 172.18.x.1/24
2728 addr = "172.18.%d.1" % intf.sw_if_index
2729 VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config()
2730
2731 self.vapi.sw_interface_address_replace_begin()
2732
2733 pfxs = []
2734 for intf in self.pg_interfaces:
2735 # 172.18.x.1/24
2736 addr = "172.18.%d.1" % (intf.sw_if_index + 1)
2737 pfxs.append(VppIpInterfaceAddress(self, intf,
2738 addr, 24).add_vpp_config())
2739
2740 self.vapi.sw_interface_address_replace_end()
2741
2742 self.logger.info(self.vapi.cli("sh int addr"))
2743
2744 for intf in self.pg_interfaces:
2745 self.assertEqual(self.get_n_pfxs(intf), 1)
2746 for pfx in pfxs:
2747 self.assertTrue(pfx.query_vpp_config())
2748
2749
Neale Ranns8f5fef22020-12-21 08:29:34 +00002750class TestIPv4PathMTU(VppTestCase):
2751 """ IPv4 Path MTU """
2752
2753 @classmethod
2754 def setUpClass(cls):
2755 super(TestIPv4PathMTU, cls).setUpClass()
2756
2757 cls.create_pg_interfaces(range(2))
2758
2759 # setup all interfaces
2760 for i in cls.pg_interfaces:
2761 i.admin_up()
2762 i.config_ip4()
2763 i.resolve_arp()
2764
2765 @classmethod
2766 def tearDownClass(cls):
2767 super(TestIPv4PathMTU, cls).tearDownClass()
2768
2769 def test_path_mtu(self):
2770 """ Path MTU """
2771
2772 #
2773 # The goal here is not to test that fragmentation works correctly,
2774 # that's done elsewhere, the intent is to ensure that the Path MTU
2775 # settings are honoured.
2776 #
2777 self.vapi.cli("adjacency counters enable")
2778
2779 # set the interface MTU to a reasonable value
2780 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
2781 [1800, 0, 0, 0])
2782
2783 self.pg1.generate_remote_hosts(4)
2784
2785 p_2k = (Ether(dst=self.pg0.local_mac,
2786 src=self.pg0.remote_mac) /
2787 IP(src=self.pg0.remote_ip4,
2788 dst=self.pg1.remote_ip4) /
2789 UDP(sport=1234, dport=5678) /
2790 Raw(b'0xa' * 640))
2791 p_1k = (Ether(dst=self.pg0.local_mac,
2792 src=self.pg0.remote_mac) /
2793 IP(src=self.pg0.remote_ip4,
2794 dst=self.pg1.remote_ip4) /
2795 UDP(sport=1234, dport=5678) /
2796 Raw(b'0xa' * 320))
2797
2798 nbr = VppNeighbor(self,
2799 self.pg1.sw_if_index,
2800 self.pg1.remote_mac,
2801 self.pg1.remote_ip4).add_vpp_config()
2802
2803 # this is now the interface MTU frags
2804 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
2805 self.send_and_expect(self.pg0, [p_1k], self.pg1)
2806
2807 # drop the path MTU for this neighbour to below the interface MTU
2808 # expect more frags
2809 pmtu = VppIpPathMtu(self, self.pg1.remote_ip4, 900).add_vpp_config()
2810
2811 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2812 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2813
2814 # print/format the adj delegate
2815 self.logger.info(self.vapi.cli("sh adj 5"))
2816
2817 # increase the path MTU to more than the interface
2818 # expect to use the interface MTU
2819 pmtu.modify(8192)
2820
2821 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
2822 self.send_and_expect(self.pg0, [p_1k], self.pg1)
2823
2824 # go back to an MTU from the path
2825 # wrap the call around mark-n-sweep to enusre updates clear stale
2826 self.vapi.ip_path_mtu_replace_begin()
2827 pmtu.modify(900)
2828 self.vapi.ip_path_mtu_replace_end()
2829
2830 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2831 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2832
2833 # raise the interface's MTU
2834 # should still use that of the path
2835 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
2836 [2000, 0, 0, 0])
2837 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2838 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2839
2840 # set path high and interface low
2841 pmtu.modify(2000)
2842 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
2843 [900, 0, 0, 0])
2844 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2845 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2846
2847 # remove the path MTU using the mark-n-sweep semantics
2848 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
2849 [1800, 0, 0, 0])
2850 self.vapi.ip_path_mtu_replace_begin()
2851 self.vapi.ip_path_mtu_replace_end()
2852
2853 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
2854 self.send_and_expect(self.pg0, [p_1k], self.pg1)
2855
2856 #
2857 # set path MTU for a neighbour that doesn't exist, yet
2858 #
2859 pmtu2 = VppIpPathMtu(self,
2860 self.pg1.remote_hosts[2].ip4,
2861 900).add_vpp_config()
2862
2863 p_2k = (Ether(dst=self.pg0.local_mac,
2864 src=self.pg0.remote_mac) /
2865 IP(src=self.pg0.remote_ip4,
2866 dst=self.pg1.remote_hosts[2].ip4) /
2867 UDP(sport=1234, dport=5678) /
2868 Raw(b'0xa' * 640))
2869 p_1k = (Ether(dst=self.pg0.local_mac,
2870 src=self.pg0.remote_mac) /
2871 IP(src=self.pg0.remote_ip4,
2872 dst=self.pg1.remote_hosts[2].ip4) /
2873 UDP(sport=1234, dport=5678) /
2874 Raw(b'0xa' * 320))
2875
2876 nbr2 = VppNeighbor(self,
2877 self.pg1.sw_if_index,
2878 self.pg1.remote_hosts[2].mac,
2879 self.pg1.remote_hosts[2].ip4).add_vpp_config()
2880
2881 # should frag to the path MTU
2882 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2883 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2884
2885 # remove and re-add the neighbour
2886 nbr2.remove_vpp_config()
2887 nbr2.add_vpp_config()
2888
2889 # should frag to the path MTU
2890 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2891 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2892
2893 #
2894 # set PMTUs for many peers
2895 #
2896 N_HOSTS = 16
2897 self.pg1.generate_remote_hosts(16)
2898 self.pg1.configure_ipv4_neighbors()
2899
2900 for h in range(N_HOSTS):
2901 pmtu = VppIpPathMtu(self, self.pg1.remote_hosts[h].ip4, 900)
2902 pmtu.add_vpp_config()
2903 self.assertTrue(pmtu.query_vpp_config())
2904
2905 self.logger.info(self.vapi.cli("sh ip pmtu"))
2906 dump = list(self.vapi.vpp.details_iter(self.vapi.ip_path_mtu_get))
2907 self.assertEqual(N_HOSTS, len(dump))
2908
2909 for h in range(N_HOSTS):
2910 p_2k[IP].dst = self.pg1.remote_hosts[h].ip4
2911 p_1k[IP].dst = self.pg1.remote_hosts[h].ip4
2912
2913 # should frag to the path MTU
2914 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=3)
2915 self.send_and_expect(self.pg0, [p_1k], self.pg1, n_rx=2)
2916
2917
Neale Ranns50bd1d32021-10-08 07:16:12 +00002918class TestIPv4ItfRebind(VppTestCase):
2919 """ IPv4 Interface Bind w/ attached routes """
2920
2921 def setUp(self):
2922 super(TestIPv4ItfRebind, self).setUp()
2923
2924 self.create_pg_interfaces(range(3))
2925
2926 def tearDown(self):
2927 super(TestIPv4ItfRebind, self).tearDown()
2928
2929 def test_rebind(self):
2930 """ Import to no import """
2931
2932 TABLE_ID = 1
2933 tbl = VppIpTable(self, TABLE_ID).add_vpp_config()
2934 self.pg1.set_table_ip4(TABLE_ID)
2935
2936 for i in self.pg_interfaces:
2937 i.admin_up()
2938 i.config_ip4()
2939 i.resolve_arp()
2940
2941 # add an attached route via an pg0
2942 # in a different table. this prefix should import
2943 rt = VppIpRoute(self, self.pg0.local_ip4, 24,
2944 [VppRoutePath("0.0.0.0",
2945 self.pg0.sw_if_index)],
2946 table_id=TABLE_ID).add_vpp_config()
2947
2948 p = (Ether(dst=self.pg1.local_mac,
2949 src=self.pg1.remote_mac) /
2950 IP(src=self.pg1.remote_ip4,
2951 dst=self.pg0.remote_ip4) /
2952 UDP(sport=1234, dport=5678) /
2953 Raw(b'0xa' * 640))
2954
2955 rx = self.send_and_expect(self.pg1, [p], self.pg0)
2956 self.assertFalse(rx[0].haslayer(ARP))
2957
2958 # then bind pg0 to a new table
2959 # so the prefix no longer imports
2960 self.pg0.unconfig_ip4()
2961 self.pg0.set_table_ip4(TABLE_ID)
2962 self.pg0.config_ip4()
2963 self.pg0.resolve_arp()
2964
2965 rx = self.send_and_expect(self.pg1, [p], self.pg0)
2966 self.assertFalse(rx[0].haslayer(ARP))
2967
2968 # revert back to imported
2969 self.pg0.unconfig_ip4()
2970 self.pg0.set_table_ip4(0)
2971 self.pg0.config_ip4()
2972 self.pg0.resolve_arp()
2973
2974 rx = self.send_and_expect(self.pg1, [p], self.pg0)
2975 self.assertFalse(rx[0].haslayer(ARP))
2976
2977 # cleanup
2978 for i in self.pg_interfaces:
2979 i.unconfig_ip4()
2980 i.set_table_ip4(0)
2981 i.admin_down()
2982
2983 rt.remove_vpp_config()
2984 tbl.remove_vpp_config()
2985
2986 def test_delete(self):
2987 """ Swap import tables """
2988
2989 TABLE_ID1 = 1
2990 tbl1_4 = VppIpTable(self, TABLE_ID1).add_vpp_config()
2991 tbl1_6 = VppIpTable(self, TABLE_ID1, True).add_vpp_config()
2992 TABLE_ID2 = 2
2993 tbl2_4 = VppIpTable(self, TABLE_ID2).add_vpp_config()
2994 tbl2_6 = VppIpTable(self, TABLE_ID2, True).add_vpp_config()
2995
2996 # table mappings
2997 self.pg1.set_table_ip4(TABLE_ID1)
2998 self.pg1.set_table_ip6(TABLE_ID1)
2999 self.pg2.set_table_ip4(TABLE_ID2)
3000 self.pg2.set_table_ip6(TABLE_ID2)
3001
3002 for i in self.pg_interfaces:
3003 i.admin_up()
3004 i.config_ip4()
3005 i.resolve_arp()
3006
3007 # add an attached route in the default table via pg0
3008 # this should import to table 1
3009 rt4 = VppIpRoute(self, self.pg1.local_ip4, 24,
3010 [VppRoutePath("0.0.0.0",
3011 self.pg1.sw_if_index)]).add_vpp_config()
3012 rt6 = VppIpRoute(self, self.pg1.local_ip6, 64,
3013 [VppRoutePath("0.0.0.0",
3014 self.pg1.sw_if_index)]).add_vpp_config()
3015
3016 p1 = (Ether(dst=self.pg0.local_mac,
3017 src=self.pg0.remote_mac) /
3018 IP(src=self.pg1.remote_ip4,
3019 dst=self.pg1.remote_ip4) /
3020 UDP(sport=1234, dport=5678) /
3021 Raw(b'0xa' * 640))
3022
3023 # inject into table 0
3024 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3025 self.assertFalse(rx[0].haslayer(ARP))
3026
3027 # swap the attached interface to table 2
3028 self.pg1.unconfig_ip4()
3029 self.pg1.unconfig_ip6()
3030 self.pg1.set_table_ip4(TABLE_ID2)
3031 self.pg1.set_table_ip6(TABLE_ID2)
3032 self.pg1.config_ip4()
3033 self.pg1.config_ip6()
3034 self.pg1.resolve_arp()
3035
3036 # delete table 1
3037 tbl1_4.flush()
3038 tbl1_6.flush()
3039 tbl1_4.remove_vpp_config()
3040 tbl1_6.remove_vpp_config()
3041
3042 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
3043 self.assertFalse(rx[0].haslayer(ARP))
3044
3045 for i in self.pg_interfaces:
3046 i.unconfig_ip4()
3047 i.unconfig_ip6()
3048 i.set_table_ip4(0)
3049 i.set_table_ip6(0)
3050 i.admin_down()
3051
3052
Damjan Marionf56b77a2016-10-03 19:44:57 +02003053if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02003054 unittest.main(testRunner=VppTestRunner)