1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# This test is for checking the nexthop offload API. It makes use of netdevsim
5# which registers a listener to the nexthop notification chain.
6
7lib_dir=$(dirname $0)/../../../net/forwarding
8
9ALL_TESTS="
10	nexthop_single_add_test
11	nexthop_single_add_err_test
12	nexthop_group_add_test
13	nexthop_group_add_err_test
14	nexthop_group_replace_test
15	nexthop_group_replace_err_test
16	nexthop_single_replace_test
17	nexthop_single_replace_err_test
18	nexthop_single_in_group_replace_test
19	nexthop_single_in_group_replace_err_test
20	nexthop_single_in_group_delete_test
21	nexthop_single_in_group_delete_err_test
22	nexthop_replay_test
23	nexthop_replay_err_test
24"
25NETDEVSIM_PATH=/sys/bus/netdevsim/
26DEV_ADDR=1337
27DEV=netdevsim${DEV_ADDR}
28DEVLINK_DEV=netdevsim/${DEV}
29SYSFS_NET_DIR=/sys/bus/netdevsim/devices/$DEV/net/
30NUM_NETIFS=0
31source $lib_dir/lib.sh
32source $lib_dir/devlink_lib.sh
33
34nexthop_check()
35{
36	local nharg="$1"; shift
37	local expected="$1"; shift
38
39	out=$($IP nexthop show ${nharg} | sed -e 's/ *$//')
40	if [[ "$out" != "$expected" ]]; then
41		return 1
42	fi
43
44	return 0
45}
46
47nexthop_resource_check()
48{
49	local expected_occ=$1; shift
50
51	occ=$($DEVLINK -jp resource show $DEVLINK_DEV \
52		| jq '.[][][] | select(.name=="nexthops") | .["occ"]')
53
54	if [ $expected_occ -ne $occ ]; then
55		return 1
56	fi
57
58	return 0
59}
60
61nexthop_resource_set()
62{
63	local size=$1; shift
64
65	$DEVLINK resource set $DEVLINK_DEV path nexthops size $size
66	$DEVLINK dev reload $DEVLINK_DEV
67}
68
69nexthop_single_add_test()
70{
71	RET=0
72
73	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
74	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
75	check_err $? "Unexpected nexthop entry"
76
77	nexthop_resource_check 1
78	check_err $? "Wrong nexthop occupancy"
79
80	$IP nexthop del id 1
81	nexthop_resource_check 0
82	check_err $? "Wrong nexthop occupancy after delete"
83
84	log_test "Single nexthop add and delete"
85}
86
87nexthop_single_add_err_test()
88{
89	RET=0
90
91	nexthop_resource_set 1
92
93	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
94
95	$IP nexthop add id 2 via 192.0.2.3 dev dummy1 &> /dev/null
96	check_fail $? "Nexthop addition succeeded when should fail"
97
98	nexthop_resource_check 1
99	check_err $? "Wrong nexthop occupancy"
100
101	log_test "Single nexthop add failure"
102
103	$IP nexthop flush &> /dev/null
104	nexthop_resource_set 9999
105}
106
107nexthop_group_add_test()
108{
109	RET=0
110
111	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
112	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
113
114	$IP nexthop add id 10 group 1/2
115	nexthop_check "id 10" "id 10 group 1/2 trap"
116	check_err $? "Unexpected nexthop group entry"
117
118	nexthop_resource_check 4
119	check_err $? "Wrong nexthop occupancy"
120
121	$IP nexthop del id 10
122	nexthop_resource_check 2
123	check_err $? "Wrong nexthop occupancy after delete"
124
125	$IP nexthop add id 10 group 1,20/2,39
126	nexthop_check "id 10" "id 10 group 1,20/2,39 trap"
127	check_err $? "Unexpected weighted nexthop group entry"
128
129	nexthop_resource_check 61
130	check_err $? "Wrong weighted nexthop occupancy"
131
132	$IP nexthop del id 10
133	nexthop_resource_check 2
134	check_err $? "Wrong nexthop occupancy after delete"
135
136	log_test "Nexthop group add and delete"
137
138	$IP nexthop flush &> /dev/null
139}
140
141nexthop_group_add_err_test()
142{
143	RET=0
144
145	nexthop_resource_set 2
146
147	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
148	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
149
150	$IP nexthop add id 10 group 1/2 &> /dev/null
151	check_fail $? "Nexthop group addition succeeded when should fail"
152
153	nexthop_resource_check 2
154	check_err $? "Wrong nexthop occupancy"
155
156	log_test "Nexthop group add failure"
157
158	$IP nexthop flush &> /dev/null
159	nexthop_resource_set 9999
160}
161
162nexthop_group_replace_test()
163{
164	RET=0
165
166	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
167	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
168	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
169	$IP nexthop add id 10 group 1/2
170
171	$IP nexthop replace id 10 group 1/2/3
172	nexthop_check "id 10" "id 10 group 1/2/3 trap"
173	check_err $? "Unexpected nexthop group entry"
174
175	nexthop_resource_check 6
176	check_err $? "Wrong nexthop occupancy"
177
178	log_test "Nexthop group replace"
179
180	$IP nexthop flush &> /dev/null
181}
182
183nexthop_group_replace_err_test()
184{
185	RET=0
186
187	nexthop_resource_set 5
188
189	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
190	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
191	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
192	$IP nexthop add id 10 group 1/2
193
194	$IP nexthop replace id 10 group 1/2/3 &> /dev/null
195	check_fail $? "Nexthop group replacement succeeded when should fail"
196
197	nexthop_check "id 10" "id 10 group 1/2 trap"
198	check_err $? "Unexpected nexthop group entry after failure"
199
200	nexthop_resource_check 5
201	check_err $? "Wrong nexthop occupancy after failure"
202
203	log_test "Nexthop group replace failure"
204
205	$IP nexthop flush &> /dev/null
206	nexthop_resource_set 9999
207}
208
209nexthop_single_replace_test()
210{
211	RET=0
212
213	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
214
215	$IP nexthop replace id 1 via 192.0.2.3 dev dummy1
216	nexthop_check "id 1" "id 1 via 192.0.2.3 dev dummy1 scope link trap"
217	check_err $? "Unexpected nexthop entry"
218
219	nexthop_resource_check 1
220	check_err $? "Wrong nexthop occupancy"
221
222	log_test "Single nexthop replace"
223
224	$IP nexthop flush &> /dev/null
225}
226
227nexthop_single_replace_err_test()
228{
229	RET=0
230
231	# This is supposed to cause the replace to fail because the new nexthop
232	# is programmed before deleting the replaced one.
233	nexthop_resource_set 1
234
235	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
236
237	$IP nexthop replace id 1 via 192.0.2.3 dev dummy1 &> /dev/null
238	check_fail $? "Nexthop replace succeeded when should fail"
239
240	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
241	check_err $? "Unexpected nexthop entry after failure"
242
243	nexthop_resource_check 1
244	check_err $? "Wrong nexthop occupancy after failure"
245
246	log_test "Single nexthop replace failure"
247
248	$IP nexthop flush &> /dev/null
249	nexthop_resource_set 9999
250}
251
252nexthop_single_in_group_replace_test()
253{
254	RET=0
255
256	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
257	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
258	$IP nexthop add id 10 group 1/2
259
260	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1
261	check_err $? "Failed to replace nexthop when should not"
262
263	nexthop_check "id 10" "id 10 group 1/2 trap"
264	check_err $? "Unexpected nexthop group entry"
265
266	nexthop_resource_check 4
267	check_err $? "Wrong nexthop occupancy"
268
269	log_test "Single nexthop replace while in group"
270
271	$IP nexthop flush &> /dev/null
272}
273
274nexthop_single_in_group_replace_err_test()
275{
276	RET=0
277
278	nexthop_resource_set 5
279
280	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
281	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
282	$IP nexthop add id 10 group 1/2
283
284	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1 &> /dev/null
285	check_fail $? "Nexthop replacement succeeded when should fail"
286
287	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
288	check_err $? "Unexpected nexthop entry after failure"
289
290	nexthop_check "id 10" "id 10 group 1/2 trap"
291	check_err $? "Unexpected nexthop group entry after failure"
292
293	nexthop_resource_check 4
294	check_err $? "Wrong nexthop occupancy"
295
296	log_test "Single nexthop replace while in group failure"
297
298	$IP nexthop flush &> /dev/null
299	nexthop_resource_set 9999
300}
301
302nexthop_single_in_group_delete_test()
303{
304	RET=0
305
306	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
307	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
308	$IP nexthop add id 10 group 1/2
309
310	$IP nexthop del id 1
311	nexthop_check "id 10" "id 10 group 2 trap"
312	check_err $? "Unexpected nexthop group entry"
313
314	nexthop_resource_check 2
315	check_err $? "Wrong nexthop occupancy"
316
317	log_test "Single nexthop delete while in group"
318
319	$IP nexthop flush &> /dev/null
320}
321
322nexthop_single_in_group_delete_err_test()
323{
324	RET=0
325
326	# First, nexthop 1 will be deleted, which will reduce the occupancy to
327	# 5. Afterwards, a replace notification will be sent for nexthop group
328	# 10 with only two nexthops. Since the new group is allocated before
329	# the old is deleted, the replacement will fail as it will result in an
330	# occupancy of 7.
331	nexthop_resource_set 6
332
333	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
334	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
335	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
336	$IP nexthop add id 10 group 1/2/3
337
338	$IP nexthop del id 1
339
340	nexthop_resource_check 5
341	check_err $? "Wrong nexthop occupancy"
342
343	log_test "Single nexthop delete while in group failure"
344
345	$IP nexthop flush &> /dev/null
346	nexthop_resource_set 9999
347}
348
349nexthop_replay_test()
350{
351	RET=0
352
353	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
354	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
355	$IP nexthop add id 10 group 1/2
356
357	$DEVLINK dev reload $DEVLINK_DEV
358	check_err $? "Failed to reload when should not"
359
360	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
361	check_err $? "Unexpected nexthop entry after reload"
362
363	nexthop_check "id 2" "id 2 via 192.0.2.3 dev dummy1 scope link trap"
364	check_err $? "Unexpected nexthop entry after reload"
365
366	nexthop_check "id 10" "id 10 group 1/2 trap"
367	check_err $? "Unexpected nexthop group entry after reload"
368
369	nexthop_resource_check 4
370	check_err $? "Wrong nexthop occupancy"
371
372	log_test "Nexthop replay"
373
374	$IP nexthop flush &> /dev/null
375}
376
377nexthop_replay_err_test()
378{
379	RET=0
380
381	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
382	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
383	$IP nexthop add id 10 group 1/2
384
385	# Reduce size of nexthop resource so that reload will fail.
386	$DEVLINK resource set $DEVLINK_DEV path nexthops size 3
387	$DEVLINK dev reload $DEVLINK_DEV &> /dev/null
388	check_fail $? "Reload succeeded when should fail"
389
390	$DEVLINK resource set $DEVLINK_DEV path nexthops size 9999
391	$DEVLINK dev reload $DEVLINK_DEV
392	check_err $? "Failed to reload when should not"
393
394	log_test "Nexthop replay failure"
395
396	$IP nexthop flush &> /dev/null
397}
398
399setup_prepare()
400{
401	local netdev
402
403	modprobe netdevsim &> /dev/null
404
405	echo "$DEV_ADDR 1" > ${NETDEVSIM_PATH}/new_device
406	while [ ! -d $SYSFS_NET_DIR ] ; do :; done
407
408	set -e
409
410	ip netns add testns1
411	devlink dev reload $DEVLINK_DEV netns testns1
412
413	IP="ip -netns testns1"
414	DEVLINK="devlink -N testns1"
415
416	$IP link add name dummy1 up type dummy
417	$IP address add 192.0.2.1/24 dev dummy1
418
419	set +e
420}
421
422cleanup()
423{
424	pre_cleanup
425	ip netns del testns1
426	echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device
427	modprobe -r netdevsim &> /dev/null
428}
429
430trap cleanup EXIT
431
432setup_prepare
433
434tests_run
435
436exit $EXIT_STATUS
437