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_res_group_add_test
15	nexthop_res_group_add_err_test
16	nexthop_group_replace_test
17	nexthop_group_replace_err_test
18	nexthop_res_group_replace_test
19	nexthop_res_group_replace_err_test
20	nexthop_res_group_idle_timer_test
21	nexthop_res_group_idle_timer_del_test
22	nexthop_res_group_increase_idle_timer_test
23	nexthop_res_group_decrease_idle_timer_test
24	nexthop_res_group_unbalanced_timer_test
25	nexthop_res_group_unbalanced_timer_del_test
26	nexthop_res_group_no_unbalanced_timer_test
27	nexthop_res_group_short_unbalanced_timer_test
28	nexthop_res_group_increase_unbalanced_timer_test
29	nexthop_res_group_decrease_unbalanced_timer_test
30	nexthop_res_group_force_migrate_busy_test
31	nexthop_single_replace_test
32	nexthop_single_replace_err_test
33	nexthop_single_in_group_replace_test
34	nexthop_single_in_group_replace_err_test
35	nexthop_single_in_res_group_replace_test
36	nexthop_single_in_res_group_replace_err_test
37	nexthop_single_in_group_delete_test
38	nexthop_single_in_group_delete_err_test
39	nexthop_single_in_res_group_delete_test
40	nexthop_single_in_res_group_delete_err_test
41	nexthop_replay_test
42	nexthop_replay_err_test
43"
44NETDEVSIM_PATH=/sys/bus/netdevsim/
45DEV_ADDR=1337
46DEV=netdevsim${DEV_ADDR}
47SYSFS_NET_DIR=/sys/bus/netdevsim/devices/$DEV/net/
48DEBUGFS_NET_DIR=/sys/kernel/debug/netdevsim/$DEV/
49NUM_NETIFS=0
50source $lib_dir/lib.sh
51
52DEVLINK_DEV=
53source $lib_dir/devlink_lib.sh
54DEVLINK_DEV=netdevsim/${DEV}
55
56nexthop_check()
57{
58	local nharg="$1"; shift
59	local expected="$1"; shift
60
61	out=$($IP nexthop show ${nharg} | sed -e 's/ *$//')
62	if [[ "$out" != "$expected" ]]; then
63		return 1
64	fi
65
66	return 0
67}
68
69nexthop_bucket_nhid_count_check()
70{
71	local group_id=$1; shift
72	local expected
73	local count
74	local nhid
75	local ret
76
77	while (($# > 0)); do
78		nhid=$1; shift
79		expected=$1; shift
80
81		count=$($IP nexthop bucket show id $group_id nhid $nhid |
82			grep "trap" | wc -l)
83		if ((expected != count)); then
84			return 1
85		fi
86	done
87
88	return 0
89}
90
91nexthop_resource_check()
92{
93	local expected_occ=$1; shift
94
95	occ=$($DEVLINK -jp resource show $DEVLINK_DEV \
96		| jq '.[][][] | select(.name=="nexthops") | .["occ"]')
97
98	if [ $expected_occ -ne $occ ]; then
99		return 1
100	fi
101
102	return 0
103}
104
105nexthop_resource_set()
106{
107	local size=$1; shift
108
109	$DEVLINK resource set $DEVLINK_DEV path nexthops size $size
110	$DEVLINK dev reload $DEVLINK_DEV
111}
112
113nexthop_single_add_test()
114{
115	RET=0
116
117	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
118	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
119	check_err $? "Unexpected nexthop entry"
120
121	nexthop_resource_check 1
122	check_err $? "Wrong nexthop occupancy"
123
124	$IP nexthop del id 1
125	nexthop_resource_check 0
126	check_err $? "Wrong nexthop occupancy after delete"
127
128	log_test "Single nexthop add and delete"
129}
130
131nexthop_single_add_err_test()
132{
133	RET=0
134
135	nexthop_resource_set 1
136
137	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
138
139	$IP nexthop add id 2 via 192.0.2.3 dev dummy1 &> /dev/null
140	check_fail $? "Nexthop addition succeeded when should fail"
141
142	nexthop_resource_check 1
143	check_err $? "Wrong nexthop occupancy"
144
145	log_test "Single nexthop add failure"
146
147	$IP nexthop flush &> /dev/null
148	nexthop_resource_set 9999
149}
150
151nexthop_group_add_test()
152{
153	RET=0
154
155	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
156	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
157
158	$IP nexthop add id 10 group 1/2
159	nexthop_check "id 10" "id 10 group 1/2 trap"
160	check_err $? "Unexpected nexthop group entry"
161
162	nexthop_resource_check 4
163	check_err $? "Wrong nexthop occupancy"
164
165	$IP nexthop del id 10
166	nexthop_resource_check 2
167	check_err $? "Wrong nexthop occupancy after delete"
168
169	$IP nexthop add id 10 group 1,20/2,39
170	nexthop_check "id 10" "id 10 group 1,20/2,39 trap"
171	check_err $? "Unexpected weighted nexthop group entry"
172
173	nexthop_resource_check 61
174	check_err $? "Wrong weighted nexthop occupancy"
175
176	$IP nexthop del id 10
177	nexthop_resource_check 2
178	check_err $? "Wrong nexthop occupancy after delete"
179
180	log_test "Nexthop group add and delete"
181
182	$IP nexthop flush &> /dev/null
183}
184
185nexthop_group_add_err_test()
186{
187	RET=0
188
189	nexthop_resource_set 2
190
191	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
192	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
193
194	$IP nexthop add id 10 group 1/2 &> /dev/null
195	check_fail $? "Nexthop group addition succeeded when should fail"
196
197	nexthop_resource_check 2
198	check_err $? "Wrong nexthop occupancy"
199
200	log_test "Nexthop group add failure"
201
202	$IP nexthop flush &> /dev/null
203	nexthop_resource_set 9999
204}
205
206nexthop_res_group_add_test()
207{
208	RET=0
209
210	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
211	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
212
213	$IP nexthop add id 10 group 1/2 type resilient buckets 4
214	nexthop_check "id 10" "id 10 group 1/2 type resilient buckets 4 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
215	check_err $? "Unexpected nexthop group entry"
216
217	nexthop_bucket_nhid_count_check 10 1 2
218	check_err $? "Wrong nexthop buckets count"
219	nexthop_bucket_nhid_count_check 10 2 2
220	check_err $? "Wrong nexthop buckets count"
221
222	nexthop_resource_check 6
223	check_err $? "Wrong nexthop occupancy"
224
225	$IP nexthop del id 10
226	nexthop_resource_check 2
227	check_err $? "Wrong nexthop occupancy after delete"
228
229	$IP nexthop add id 10 group 1,3/2,2 type resilient buckets 5
230	nexthop_check "id 10" "id 10 group 1,3/2,2 type resilient buckets 5 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
231	check_err $? "Unexpected weighted nexthop group entry"
232
233	nexthop_bucket_nhid_count_check 10 1 3
234	check_err $? "Wrong nexthop buckets count"
235	nexthop_bucket_nhid_count_check 10 2 2
236	check_err $? "Wrong nexthop buckets count"
237
238	nexthop_resource_check 7
239	check_err $? "Wrong weighted nexthop occupancy"
240
241	$IP nexthop del id 10
242	nexthop_resource_check 2
243	check_err $? "Wrong nexthop occupancy after delete"
244
245	log_test "Resilient nexthop group add and delete"
246
247	$IP nexthop flush &> /dev/null
248}
249
250nexthop_res_group_add_err_test()
251{
252	RET=0
253
254	nexthop_resource_set 2
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
259	$IP nexthop add id 10 group 1/2 type resilient buckets 4 &> /dev/null
260	check_fail $? "Nexthop group addition succeeded when should fail"
261
262	nexthop_resource_check 2
263	check_err $? "Wrong nexthop occupancy"
264
265	log_test "Resilient nexthop group add failure"
266
267	$IP nexthop flush &> /dev/null
268	nexthop_resource_set 9999
269}
270
271nexthop_group_replace_test()
272{
273	RET=0
274
275	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
276	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
277	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
278	$IP nexthop add id 10 group 1/2
279
280	$IP nexthop replace id 10 group 1/2/3
281	nexthop_check "id 10" "id 10 group 1/2/3 trap"
282	check_err $? "Unexpected nexthop group entry"
283
284	nexthop_resource_check 6
285	check_err $? "Wrong nexthop occupancy"
286
287	log_test "Nexthop group replace"
288
289	$IP nexthop flush &> /dev/null
290}
291
292nexthop_group_replace_err_test()
293{
294	RET=0
295
296	nexthop_resource_set 5
297
298	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
299	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
300	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
301	$IP nexthop add id 10 group 1/2
302
303	$IP nexthop replace id 10 group 1/2/3 &> /dev/null
304	check_fail $? "Nexthop group replacement succeeded when should fail"
305
306	nexthop_check "id 10" "id 10 group 1/2 trap"
307	check_err $? "Unexpected nexthop group entry after failure"
308
309	nexthop_resource_check 5
310	check_err $? "Wrong nexthop occupancy after failure"
311
312	log_test "Nexthop group replace failure"
313
314	$IP nexthop flush &> /dev/null
315	nexthop_resource_set 9999
316}
317
318nexthop_res_group_replace_test()
319{
320	RET=0
321
322	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
323	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
324	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
325	$IP nexthop add id 10 group 1/2 type resilient buckets 6
326
327	$IP nexthop replace id 10 group 1/2/3 type resilient
328	nexthop_check "id 10" "id 10 group 1/2/3 type resilient buckets 6 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
329	check_err $? "Unexpected nexthop group entry"
330
331	nexthop_bucket_nhid_count_check 10 1 2
332	check_err $? "Wrong nexthop buckets count"
333	nexthop_bucket_nhid_count_check 10 2 2
334	check_err $? "Wrong nexthop buckets count"
335	nexthop_bucket_nhid_count_check 10 3 2
336	check_err $? "Wrong nexthop buckets count"
337
338	nexthop_resource_check 9
339	check_err $? "Wrong nexthop occupancy"
340
341	log_test "Resilient nexthop group replace"
342
343	$IP nexthop flush &> /dev/null
344}
345
346nexthop_res_group_replace_err_test()
347{
348	RET=0
349
350	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
351	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
352	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
353	$IP nexthop add id 10 group 1/2 type resilient buckets 6
354
355	ip netns exec testns1 \
356		echo 1 > $DEBUGFS_NET_DIR/fib/fail_res_nexthop_group_replace
357	$IP nexthop replace id 10 group 1/2/3 type resilient &> /dev/null
358	check_fail $? "Nexthop group replacement succeeded when should fail"
359
360	nexthop_check "id 10" "id 10 group 1/2 type resilient buckets 6 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
361	check_err $? "Unexpected nexthop group entry after failure"
362
363	nexthop_bucket_nhid_count_check 10 1 3
364	check_err $? "Wrong nexthop buckets count"
365	nexthop_bucket_nhid_count_check 10 2 3
366	check_err $? "Wrong nexthop buckets count"
367
368	nexthop_resource_check 9
369	check_err $? "Wrong nexthop occupancy after failure"
370
371	log_test "Resilient nexthop group replace failure"
372
373	$IP nexthop flush &> /dev/null
374	ip netns exec testns1 \
375		echo 0 > $DEBUGFS_NET_DIR/fib/fail_res_nexthop_group_replace
376}
377
378nexthop_res_mark_buckets_busy()
379{
380	local group_id=$1; shift
381	local nhid=$1; shift
382	local count=$1; shift
383	local index
384
385	for index in $($IP -j nexthop bucket show id $group_id nhid $nhid |
386		       jq '.[].bucket.index' | head -n ${count:--0})
387	do
388		echo $group_id $index \
389			> $DEBUGFS_NET_DIR/fib/nexthop_bucket_activity
390	done
391}
392
393nexthop_res_num_nhid_buckets()
394{
395	local group_id=$1; shift
396	local nhid=$1; shift
397
398	$IP -j nexthop bucket show id $group_id nhid $nhid | jq length
399}
400
401nexthop_res_group_idle_timer_test()
402{
403	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
404	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
405
406	RET=0
407
408	$IP nexthop add id 10 group 1/2 type resilient buckets 8 idle_timer 4
409	nexthop_res_mark_buckets_busy 10 1
410	$IP nexthop replace id 10 group 1/2,3 type resilient
411
412	nexthop_bucket_nhid_count_check 10  1 4  2 4
413	check_err $? "Group expected to be unbalanced"
414
415	sleep 6
416
417	nexthop_bucket_nhid_count_check 10  1 2  2 6
418	check_err $? "Group expected to be balanced"
419
420	log_test "Bucket migration after idle timer"
421
422	$IP nexthop flush &> /dev/null
423}
424
425nexthop_res_group_idle_timer_del_test()
426{
427	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
428	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
429	$IP nexthop add id 3 via 192.0.2.3 dev dummy1
430
431	RET=0
432
433	$IP nexthop add id 10 group 1,50/2,50/3,1 \
434	    type resilient buckets 8 idle_timer 6
435	nexthop_res_mark_buckets_busy 10 1
436	$IP nexthop replace id 10 group 1,50/2,150/3,1 type resilient
437
438	nexthop_bucket_nhid_count_check 10  1 4  2 4  3 0
439	check_err $? "Group expected to be unbalanced"
440
441	sleep 4
442
443	# Deletion prompts group replacement. Check that the bucket timers
444	# are kept.
445	$IP nexthop delete id 3
446
447	nexthop_bucket_nhid_count_check 10  1 4  2 4
448	check_err $? "Group expected to still be unbalanced"
449
450	sleep 4
451
452	nexthop_bucket_nhid_count_check 10  1 2  2 6
453	check_err $? "Group expected to be balanced"
454
455	log_test "Bucket migration after idle timer (with delete)"
456
457	$IP nexthop flush &> /dev/null
458}
459
460__nexthop_res_group_increase_timer_test()
461{
462	local timer=$1; shift
463
464	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
465	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
466
467	RET=0
468
469	$IP nexthop add id 10 group 1/2 type resilient buckets 8 $timer 4
470	nexthop_res_mark_buckets_busy 10 1
471	$IP nexthop replace id 10 group 1/2,3 type resilient
472
473	nexthop_bucket_nhid_count_check 10 2 6
474	check_fail $? "Group expected to be unbalanced"
475
476	sleep 2
477	$IP nexthop replace id 10 group 1/2,3 type resilient $timer 8
478	sleep 4
479
480	# 6 seconds, past the original timer.
481	nexthop_bucket_nhid_count_check 10 2 6
482	check_fail $? "Group still expected to be unbalanced"
483
484	sleep 4
485
486	# 10 seconds, past the new timer.
487	nexthop_bucket_nhid_count_check 10 2 6
488	check_err $? "Group expected to be balanced"
489
490	log_test "Bucket migration after $timer increase"
491
492	$IP nexthop flush &> /dev/null
493}
494
495__nexthop_res_group_decrease_timer_test()
496{
497	local timer=$1; shift
498
499	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
500	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
501
502	RET=0
503
504	$IP nexthop add id 10 group 1/2 type resilient buckets 8 $timer 8
505	nexthop_res_mark_buckets_busy 10 1
506	$IP nexthop replace id 10 group 1/2,3 type resilient
507
508	nexthop_bucket_nhid_count_check 10 2 6
509	check_fail $? "Group expected to be unbalanced"
510
511	sleep 2
512	$IP nexthop replace id 10 group 1/2,3 type resilient $timer 4
513	sleep 4
514
515	# 6 seconds, past the new timer, before the old timer.
516	nexthop_bucket_nhid_count_check 10 2 6
517	check_err $? "Group expected to be balanced"
518
519	log_test "Bucket migration after $timer decrease"
520
521	$IP nexthop flush &> /dev/null
522}
523
524__nexthop_res_group_increase_timer_del_test()
525{
526	local timer=$1; shift
527
528	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
529	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
530	$IP nexthop add id 3 via 192.0.2.3 dev dummy1
531
532	RET=0
533
534	$IP nexthop add id 10 group 1,100/2,100/3,1 \
535	    type resilient buckets 8 $timer 4
536	nexthop_res_mark_buckets_busy 10 1
537	$IP nexthop replace id 10 group 1,100/2,300/3,1 type resilient
538
539	nexthop_bucket_nhid_count_check 10 2 6
540	check_fail $? "Group expected to be unbalanced"
541
542	sleep 2
543	$IP nexthop replace id 10 group 1/2,3 type resilient $timer 8
544	sleep 4
545
546	# 6 seconds, past the original timer.
547	nexthop_bucket_nhid_count_check 10 2 6
548	check_fail $? "Group still expected to be unbalanced"
549
550	sleep 4
551
552	# 10 seconds, past the new timer.
553	nexthop_bucket_nhid_count_check 10 2 6
554	check_err $? "Group expected to be balanced"
555
556	log_test "Bucket migration after $timer increase"
557
558	$IP nexthop flush &> /dev/null
559}
560
561nexthop_res_group_increase_idle_timer_test()
562{
563	__nexthop_res_group_increase_timer_test idle_timer
564}
565
566nexthop_res_group_decrease_idle_timer_test()
567{
568	__nexthop_res_group_decrease_timer_test idle_timer
569}
570
571nexthop_res_group_unbalanced_timer_test()
572{
573	local i
574
575	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
576	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
577
578	RET=0
579
580	$IP nexthop add id 10 group 1/2 type resilient \
581	    buckets 8 idle_timer 6 unbalanced_timer 10
582	nexthop_res_mark_buckets_busy 10 1
583	$IP nexthop replace id 10 group 1/2,3 type resilient
584
585	for i in 1 2; do
586		sleep 4
587		nexthop_bucket_nhid_count_check 10  1 4  2 4
588		check_err $? "$i: Group expected to be unbalanced"
589		nexthop_res_mark_buckets_busy 10 1
590	done
591
592	# 3 x sleep 4 > unbalanced timer 10
593	sleep 4
594	nexthop_bucket_nhid_count_check 10  1 2  2 6
595	check_err $? "Group expected to be balanced"
596
597	log_test "Bucket migration after unbalanced timer"
598
599	$IP nexthop flush &> /dev/null
600}
601
602nexthop_res_group_unbalanced_timer_del_test()
603{
604	local i
605
606	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
607	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
608	$IP nexthop add id 3 via 192.0.2.3 dev dummy1
609
610	RET=0
611
612	$IP nexthop add id 10 group 1,50/2,50/3,1 type resilient \
613	    buckets 8 idle_timer 6 unbalanced_timer 10
614	nexthop_res_mark_buckets_busy 10 1
615	$IP nexthop replace id 10 group 1,50/2,150/3,1 type resilient
616
617	# Check that NH delete does not reset unbalanced time.
618	sleep 4
619	$IP nexthop delete id 3
620	nexthop_bucket_nhid_count_check 10  1 4  2 4
621	check_err $? "1: Group expected to be unbalanced"
622	nexthop_res_mark_buckets_busy 10 1
623
624	sleep 4
625	nexthop_bucket_nhid_count_check 10  1 4  2 4
626	check_err $? "2: Group expected to be unbalanced"
627	nexthop_res_mark_buckets_busy 10 1
628
629	# 3 x sleep 4 > unbalanced timer 10
630	sleep 4
631	nexthop_bucket_nhid_count_check 10  1 2  2 6
632	check_err $? "Group expected to be balanced"
633
634	log_test "Bucket migration after unbalanced timer (with delete)"
635
636	$IP nexthop flush &> /dev/null
637}
638
639nexthop_res_group_no_unbalanced_timer_test()
640{
641	local i
642
643	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
644	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
645
646	RET=0
647
648	$IP nexthop add id 10 group 1/2 type resilient buckets 8
649	nexthop_res_mark_buckets_busy 10 1
650	$IP nexthop replace id 10 group 1/2,3 type resilient
651
652	for i in $(seq 3); do
653		sleep 60
654		nexthop_bucket_nhid_count_check 10 2 6
655		check_fail $? "$i: Group expected to be unbalanced"
656		nexthop_res_mark_buckets_busy 10 1
657	done
658
659	log_test "Buckets never force-migrated without unbalanced timer"
660
661	$IP nexthop flush &> /dev/null
662}
663
664nexthop_res_group_short_unbalanced_timer_test()
665{
666	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
667	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
668
669	RET=0
670
671	$IP nexthop add id 10 group 1/2 type resilient \
672	    buckets 8 idle_timer 120 unbalanced_timer 4
673	nexthop_res_mark_buckets_busy 10 1
674	$IP nexthop replace id 10 group 1/2,3 type resilient
675
676	nexthop_bucket_nhid_count_check 10 2 6
677	check_fail $? "Group expected to be unbalanced"
678
679	sleep 5
680
681	nexthop_bucket_nhid_count_check 10 2 6
682	check_err $? "Group expected to be balanced"
683
684	log_test "Bucket migration after unbalanced < idle timer"
685
686	$IP nexthop flush &> /dev/null
687}
688
689nexthop_res_group_increase_unbalanced_timer_test()
690{
691	__nexthop_res_group_increase_timer_test unbalanced_timer
692}
693
694nexthop_res_group_decrease_unbalanced_timer_test()
695{
696	__nexthop_res_group_decrease_timer_test unbalanced_timer
697}
698
699nexthop_res_group_force_migrate_busy_test()
700{
701	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
702	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
703
704	RET=0
705
706	$IP nexthop add id 10 group 1/2 type resilient \
707	    buckets 8 idle_timer 120
708	nexthop_res_mark_buckets_busy 10 1
709	$IP nexthop replace id 10 group 1/2,3 type resilient
710
711	nexthop_bucket_nhid_count_check 10 2 6
712	check_fail $? "Group expected to be unbalanced"
713
714	$IP nexthop replace id 10 group 2 type resilient
715	nexthop_bucket_nhid_count_check 10 2 8
716	check_err $? "All buckets expected to have migrated"
717
718	log_test "Busy buckets force-migrated when NH removed"
719
720	$IP nexthop flush &> /dev/null
721}
722
723nexthop_single_replace_test()
724{
725	RET=0
726
727	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
728
729	$IP nexthop replace id 1 via 192.0.2.3 dev dummy1
730	nexthop_check "id 1" "id 1 via 192.0.2.3 dev dummy1 scope link trap"
731	check_err $? "Unexpected nexthop entry"
732
733	nexthop_resource_check 1
734	check_err $? "Wrong nexthop occupancy"
735
736	log_test "Single nexthop replace"
737
738	$IP nexthop flush &> /dev/null
739}
740
741nexthop_single_replace_err_test()
742{
743	RET=0
744
745	# This is supposed to cause the replace to fail because the new nexthop
746	# is programmed before deleting the replaced one.
747	nexthop_resource_set 1
748
749	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
750
751	$IP nexthop replace id 1 via 192.0.2.3 dev dummy1 &> /dev/null
752	check_fail $? "Nexthop replace succeeded when should fail"
753
754	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
755	check_err $? "Unexpected nexthop entry after failure"
756
757	nexthop_resource_check 1
758	check_err $? "Wrong nexthop occupancy after failure"
759
760	log_test "Single nexthop replace failure"
761
762	$IP nexthop flush &> /dev/null
763	nexthop_resource_set 9999
764}
765
766nexthop_single_in_group_replace_test()
767{
768	RET=0
769
770	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
771	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
772	$IP nexthop add id 10 group 1/2
773
774	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1
775	check_err $? "Failed to replace nexthop when should not"
776
777	nexthop_check "id 10" "id 10 group 1/2 trap"
778	check_err $? "Unexpected nexthop group entry"
779
780	nexthop_resource_check 4
781	check_err $? "Wrong nexthop occupancy"
782
783	log_test "Single nexthop replace while in group"
784
785	$IP nexthop flush &> /dev/null
786}
787
788nexthop_single_in_group_replace_err_test()
789{
790	RET=0
791
792	nexthop_resource_set 5
793
794	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
795	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
796	$IP nexthop add id 10 group 1/2
797
798	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1 &> /dev/null
799	check_fail $? "Nexthop replacement succeeded when should fail"
800
801	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
802	check_err $? "Unexpected nexthop entry after failure"
803
804	nexthop_check "id 10" "id 10 group 1/2 trap"
805	check_err $? "Unexpected nexthop group entry after failure"
806
807	nexthop_resource_check 4
808	check_err $? "Wrong nexthop occupancy"
809
810	log_test "Single nexthop replace while in group failure"
811
812	$IP nexthop flush &> /dev/null
813	nexthop_resource_set 9999
814}
815
816nexthop_single_in_res_group_replace_test()
817{
818	RET=0
819
820	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
821	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
822	$IP nexthop add id 10 group 1/2 type resilient buckets 4
823
824	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1
825	check_err $? "Failed to replace nexthop when should not"
826
827	nexthop_check "id 10" "id 10 group 1/2 type resilient buckets 4 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
828	check_err $? "Unexpected nexthop group entry"
829
830	nexthop_bucket_nhid_count_check 10  1 2  2 2
831	check_err $? "Wrong nexthop buckets count"
832
833	nexthop_resource_check 6
834	check_err $? "Wrong nexthop occupancy"
835
836	log_test "Single nexthop replace while in resilient group"
837
838	$IP nexthop flush &> /dev/null
839}
840
841nexthop_single_in_res_group_replace_err_test()
842{
843	RET=0
844
845	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
846	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
847	$IP nexthop add id 10 group 1/2 type resilient buckets 4
848
849	ip netns exec testns1 \
850		echo 1 > $DEBUGFS_NET_DIR/fib/fail_nexthop_bucket_replace
851	$IP nexthop replace id 1 via 192.0.2.4 dev dummy1 &> /dev/null
852	check_fail $? "Nexthop replacement succeeded when should fail"
853
854	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
855	check_err $? "Unexpected nexthop entry after failure"
856
857	nexthop_check "id 10" "id 10 group 1/2 type resilient buckets 4 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
858	check_err $? "Unexpected nexthop group entry after failure"
859
860	nexthop_bucket_nhid_count_check 10  1 2  2 2
861	check_err $? "Wrong nexthop buckets count"
862
863	nexthop_resource_check 6
864	check_err $? "Wrong nexthop occupancy"
865
866	log_test "Single nexthop replace while in resilient group failure"
867
868	$IP nexthop flush &> /dev/null
869	ip netns exec testns1 \
870		echo 0 > $DEBUGFS_NET_DIR/fib/fail_nexthop_bucket_replace
871}
872
873nexthop_single_in_group_delete_test()
874{
875	RET=0
876
877	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
878	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
879	$IP nexthop add id 10 group 1/2
880
881	$IP nexthop del id 1
882	nexthop_check "id 10" "id 10 group 2 trap"
883	check_err $? "Unexpected nexthop group entry"
884
885	nexthop_resource_check 2
886	check_err $? "Wrong nexthop occupancy"
887
888	log_test "Single nexthop delete while in group"
889
890	$IP nexthop flush &> /dev/null
891}
892
893nexthop_single_in_group_delete_err_test()
894{
895	RET=0
896
897	# First, nexthop 1 will be deleted, which will reduce the occupancy to
898	# 5. Afterwards, a replace notification will be sent for nexthop group
899	# 10 with only two nexthops. Since the new group is allocated before
900	# the old is deleted, the replacement will fail as it will result in an
901	# occupancy of 7.
902	nexthop_resource_set 6
903
904	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
905	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
906	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
907	$IP nexthop add id 10 group 1/2/3
908
909	$IP nexthop del id 1
910
911	nexthop_resource_check 5
912	check_err $? "Wrong nexthop occupancy"
913
914	log_test "Single nexthop delete while in group failure"
915
916	$IP nexthop flush &> /dev/null
917	nexthop_resource_set 9999
918}
919
920nexthop_single_in_res_group_delete_test()
921{
922	RET=0
923
924	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
925	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
926	$IP nexthop add id 10 group 1/2 type resilient buckets 4
927
928	$IP nexthop del id 1
929	nexthop_check "id 10" "id 10 group 2 type resilient buckets 4 idle_timer 120 unbalanced_timer 0 unbalanced_time 0 trap"
930	check_err $? "Unexpected nexthop group entry"
931
932	nexthop_bucket_nhid_count_check 10 2 4
933	check_err $? "Wrong nexthop buckets count"
934
935	nexthop_resource_check 5
936	check_err $? "Wrong nexthop occupancy"
937
938	log_test "Single nexthop delete while in resilient group"
939
940	$IP nexthop flush &> /dev/null
941}
942
943nexthop_single_in_res_group_delete_err_test()
944{
945	RET=0
946
947	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
948	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
949	$IP nexthop add id 3 via 192.0.2.4 dev dummy1
950	$IP nexthop add id 10 group 1/2/3 type resilient buckets 6
951
952	ip netns exec testns1 \
953		echo 1 > $DEBUGFS_NET_DIR/fib/fail_nexthop_bucket_replace
954	$IP nexthop del id 1
955
956	# We failed to replace the two nexthop buckets that were originally
957	# assigned to nhid 1.
958	nexthop_bucket_nhid_count_check 10  2 2  3 2
959	check_err $? "Wrong nexthop buckets count"
960
961	nexthop_resource_check 8
962	check_err $? "Wrong nexthop occupancy"
963
964	log_test "Single nexthop delete while in resilient group failure"
965
966	$IP nexthop flush &> /dev/null
967	ip netns exec testns1 \
968		echo 0 > $DEBUGFS_NET_DIR/fib/fail_nexthop_bucket_replace
969}
970
971nexthop_replay_test()
972{
973	RET=0
974
975	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
976	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
977	$IP nexthop add id 10 group 1/2
978
979	$DEVLINK dev reload $DEVLINK_DEV
980	check_err $? "Failed to reload when should not"
981
982	nexthop_check "id 1" "id 1 via 192.0.2.2 dev dummy1 scope link trap"
983	check_err $? "Unexpected nexthop entry after reload"
984
985	nexthop_check "id 2" "id 2 via 192.0.2.3 dev dummy1 scope link trap"
986	check_err $? "Unexpected nexthop entry after reload"
987
988	nexthop_check "id 10" "id 10 group 1/2 trap"
989	check_err $? "Unexpected nexthop group entry after reload"
990
991	nexthop_resource_check 4
992	check_err $? "Wrong nexthop occupancy"
993
994	log_test "Nexthop replay"
995
996	$IP nexthop flush &> /dev/null
997}
998
999nexthop_replay_err_test()
1000{
1001	RET=0
1002
1003	$IP nexthop add id 1 via 192.0.2.2 dev dummy1
1004	$IP nexthop add id 2 via 192.0.2.3 dev dummy1
1005	$IP nexthop add id 10 group 1/2
1006
1007	# Reduce size of nexthop resource so that reload will fail.
1008	$DEVLINK resource set $DEVLINK_DEV path nexthops size 3
1009	$DEVLINK dev reload $DEVLINK_DEV &> /dev/null
1010	check_fail $? "Reload succeeded when should fail"
1011
1012	$DEVLINK resource set $DEVLINK_DEV path nexthops size 9999
1013	$DEVLINK dev reload $DEVLINK_DEV
1014	check_err $? "Failed to reload when should not"
1015
1016	log_test "Nexthop replay failure"
1017
1018	$IP nexthop flush &> /dev/null
1019}
1020
1021setup_prepare()
1022{
1023	local netdev
1024
1025	modprobe netdevsim &> /dev/null
1026
1027	echo "$DEV_ADDR 1" > ${NETDEVSIM_PATH}/new_device
1028	while [ ! -d $SYSFS_NET_DIR ] ; do :; done
1029
1030	set -e
1031
1032	ip netns add testns1
1033	devlink dev reload $DEVLINK_DEV netns testns1
1034
1035	IP="ip -netns testns1"
1036	DEVLINK="devlink -N testns1"
1037
1038	$IP link add name dummy1 up type dummy
1039	$IP address add 192.0.2.1/24 dev dummy1
1040
1041	set +e
1042}
1043
1044cleanup()
1045{
1046	pre_cleanup
1047	ip netns del testns1
1048	echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device
1049	modprobe -r netdevsim &> /dev/null
1050}
1051
1052trap cleanup EXIT
1053
1054setup_prepare
1055
1056tests_run
1057
1058exit $EXIT_STATUS
1059