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