1# SPDX-License-Identifier: GPL-2.0
2#
3# Various helpers and tests to verify FIB offload.
4
5__fib_trap_check()
6{
7	local ns=$1; shift
8	local family=$1; shift
9	local route=$1; shift
10	local should_fail=$1; shift
11	local ret
12
13	ip -n $ns -j -p -$family route show $route \
14		| jq -e '.[]["flags"] | contains(["trap"])' &> /dev/null
15	ret=$?
16	if [[ $should_fail == "true" ]]; then
17		if [[ $ret -ne 0 ]]; then
18			return 0
19		else
20			return 1
21		fi
22	fi
23
24	return $ret
25}
26
27fib_trap_check()
28{
29	local ns=$1; shift
30	local family=$1; shift
31	local route=$1; shift
32	local should_fail=$1; shift
33
34	busywait 5000 __fib_trap_check $ns $family "$route" $should_fail
35}
36
37fib4_trap_check()
38{
39	local ns=$1; shift
40	local route=$1; shift
41	local should_fail=$1; shift
42
43	fib_trap_check $ns 4 "$route" $should_fail
44}
45
46fib6_trap_check()
47{
48	local ns=$1; shift
49	local route=$1; shift
50	local should_fail=$1; shift
51
52	fib_trap_check $ns 6 "$route" $should_fail
53}
54
55fib_ipv4_identical_routes_test()
56{
57	local ns=$1; shift
58	local i
59
60	RET=0
61
62	for i in $(seq 1 3); do
63		ip -n $ns link add name dummy$i type dummy
64		ip -n $ns link set dev dummy$i up
65	done
66
67	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 0 metric 1024
68	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 0 metric 1024" false
69	check_err $? "Route not in hardware when should"
70
71	ip -n $ns route append 192.0.2.0/24 dev dummy2 tos 0 metric 1024
72	fib4_trap_check $ns "192.0.2.0/24 dev dummy2 tos 0 metric 1024" true
73	check_err $? "Appended route in hardware when should not"
74
75	ip -n $ns route prepend 192.0.2.0/24 dev dummy3 tos 0 metric 1024
76	fib4_trap_check $ns "192.0.2.0/24 dev dummy3 tos 0 metric 1024" false
77	check_err $? "Prepended route not in hardware when should"
78
79	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 0 metric 1024" true
80	check_err $? "Route was not replaced in hardware by prepended one"
81
82	log_test "IPv4 identical routes"
83
84	for i in $(seq 1 3); do
85		ip -n $ns link del dev dummy$i
86	done
87}
88
89fib_ipv4_tos_test()
90{
91	local ns=$1; shift
92
93	RET=0
94
95	ip -n $ns link add name dummy1 type dummy
96	ip -n $ns link set dev dummy1 up
97
98	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 0 metric 1024
99	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 0 metric 1024" false
100	check_err $? "Route not in hardware when should"
101
102	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 2 metric 1024
103	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 2 metric 1024" false
104	check_err $? "Highest TOS route not in hardware when should"
105
106	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 0 metric 1024" true
107	check_err $? "Lowest TOS route still in hardware when should not"
108
109	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 1 metric 1024
110	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 1 metric 1024" true
111	check_err $? "Middle TOS route in hardware when should not"
112
113	log_test "IPv4 routes with TOS"
114
115	ip -n $ns link del dev dummy1
116}
117
118fib_ipv4_metric_test()
119{
120	local ns=$1; shift
121
122	RET=0
123
124	ip -n $ns link add name dummy1 type dummy
125	ip -n $ns link set dev dummy1 up
126
127	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1024
128	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1024" false
129	check_err $? "Route not in hardware when should"
130
131	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1022
132	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1022" false
133	check_err $? "Lowest metric route not in hardware when should"
134
135	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1024" true
136	check_err $? "Highest metric route still in hardware when should not"
137
138	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1023
139	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1023" true
140	check_err $? "Middle metric route in hardware when should not"
141
142	log_test "IPv4 routes with metric"
143
144	ip -n $ns link del dev dummy1
145}
146
147fib_ipv4_replace_test()
148{
149	local ns=$1; shift
150	local i
151
152	RET=0
153
154	for i in $(seq 1 2); do
155		ip -n $ns link add name dummy$i type dummy
156		ip -n $ns link set dev dummy$i up
157	done
158
159	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1024
160	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1024" false
161	check_err $? "Route not in hardware when should"
162
163	ip -n $ns route replace 192.0.2.0/24 dev dummy2 metric 1024
164	fib4_trap_check $ns "192.0.2.0/24 dev dummy2 metric 1024" false
165	check_err $? "Replacement route not in hardware when should"
166
167	# Add a route with an higher metric and make sure that replacing it
168	# does not affect the lower metric one.
169	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1025
170	ip -n $ns route replace 192.0.2.0/24 dev dummy2 metric 1025
171
172	fib4_trap_check $ns "192.0.2.0/24 dev dummy2 metric 1024" false
173	check_err $? "Lowest metric route not in hardware when should"
174	fib4_trap_check $ns "192.0.2.0/24 dev dummy2 metric 1025" true
175	check_err $? "Highest metric route in hardware when should not"
176
177	log_test "IPv4 route replace"
178
179	for i in $(seq 1 2); do
180		ip -n $ns link del dev dummy$i
181	done
182}
183
184fib_ipv4_delete_test()
185{
186	local ns=$1; shift
187	local metric
188
189	RET=0
190
191	ip -n $ns link add name dummy1 type dummy
192	ip -n $ns link set dev dummy1 up
193
194	# Insert multiple routes with the same prefix and length and varying
195	# metrics. Make sure that throughout delete operations the lowest
196	# metric route is the one in hardware.
197	for metric in $(seq 1024 1026); do
198		ip -n $ns route add 192.0.2.0/24 dev dummy1 metric $metric
199	done
200
201	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1024" false
202	check_err $? "Route not in hardware when should"
203
204	ip -n $ns route del 192.0.2.0/24 dev dummy1 metric 1024
205	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1025" false
206	check_err $? "Lowest metric route not in hardware when should"
207
208	ip -n $ns route del 192.0.2.0/24 dev dummy1 metric 1026
209	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1025" false
210	check_err $? "Sole route not in hardware when should"
211
212	log_test "IPv4 route delete"
213
214	ip -n $ns link del dev dummy1
215}
216
217fib_ipv4_plen_test()
218{
219	local ns=$1; shift
220
221	RET=0
222
223	ip -n $ns link add name dummy1 type dummy
224	ip -n $ns link set dev dummy1 up
225
226	# Add two routes with the same key and different prefix length and
227	# make sure both are in hardware. It can be verfied that both are
228	# sharing the same leaf by checking the /proc/net/fib_trie
229	ip -n $ns route add 192.0.2.0/24 dev dummy1
230	ip -n $ns route add 192.0.2.0/25 dev dummy1
231
232	fib4_trap_check $ns "192.0.2.0/24 dev dummy1" false
233	check_err $? "/24 not in hardware when should"
234
235	fib4_trap_check $ns "192.0.2.0/25 dev dummy1" false
236	check_err $? "/25 not in hardware when should"
237
238	log_test "IPv4 routes with different prefix length"
239
240	ip -n $ns link del dev dummy1
241}
242
243fib_ipv4_replay_metric_test()
244{
245	local ns=$1; shift
246	local devlink_dev=$1; shift
247
248	RET=0
249
250	ip -n $ns link add name dummy1 type dummy
251	ip -n $ns link set dev dummy1 up
252
253	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1024
254	ip -n $ns route add 192.0.2.0/24 dev dummy1 metric 1025
255
256	devlink -N $ns dev reload $devlink_dev
257
258	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1024" false
259	check_err $? "Lowest metric route not in hardware when should"
260
261	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 metric 1025" true
262	check_err $? "Highest metric route in hardware when should not"
263
264	log_test "IPv4 routes replay - metric"
265
266	ip -n $ns link del dev dummy1
267}
268
269fib_ipv4_replay_tos_test()
270{
271	local ns=$1; shift
272	local devlink_dev=$1; shift
273
274	RET=0
275
276	ip -n $ns link add name dummy1 type dummy
277	ip -n $ns link set dev dummy1 up
278
279	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 0
280	ip -n $ns route add 192.0.2.0/24 dev dummy1 tos 1
281
282	devlink -N $ns dev reload $devlink_dev
283
284	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 1" false
285	check_err $? "Highest TOS route not in hardware when should"
286
287	fib4_trap_check $ns "192.0.2.0/24 dev dummy1 tos 0" true
288	check_err $? "Lowest TOS route in hardware when should not"
289
290	log_test "IPv4 routes replay - TOS"
291
292	ip -n $ns link del dev dummy1
293}
294
295fib_ipv4_replay_plen_test()
296{
297	local ns=$1; shift
298	local devlink_dev=$1; shift
299
300	RET=0
301
302	ip -n $ns link add name dummy1 type dummy
303	ip -n $ns link set dev dummy1 up
304
305	ip -n $ns route add 192.0.2.0/24 dev dummy1
306	ip -n $ns route add 192.0.2.0/25 dev dummy1
307
308	devlink -N $ns dev reload $devlink_dev
309
310	fib4_trap_check $ns "192.0.2.0/24 dev dummy1" false
311	check_err $? "/24 not in hardware when should"
312
313	fib4_trap_check $ns "192.0.2.0/25 dev dummy1" false
314	check_err $? "/25 not in hardware when should"
315
316	log_test "IPv4 routes replay - prefix length"
317
318	ip -n $ns link del dev dummy1
319}
320
321fib_ipv4_flush_test()
322{
323	local ns=$1; shift
324	local metric
325
326	RET=0
327
328	ip -n $ns link add name dummy1 type dummy
329	ip -n $ns link set dev dummy1 up
330
331	# Exercise the routes flushing code paths by inserting various
332	# prefix routes on a netdev and then deleting it.
333	for metric in $(seq 1 20); do
334		ip -n $ns route add 192.0.2.0/24 dev dummy1 metric $metric
335	done
336
337	ip -n $ns link del dev dummy1
338
339	log_test "IPv4 routes flushing"
340}
341
342fib_ipv6_add_test()
343{
344	local ns=$1; shift
345
346	RET=0
347
348	for i in $(seq 1 2); do
349		ip -n $ns link add name dummy$i type dummy
350		ip -n $ns link set dev dummy$i up
351	done
352
353	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1024
354	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1024" false
355	check_err $? "Route not in hardware when should"
356
357	ip -n $ns route append 2001:db8:1::/64 dev dummy2 metric 1024
358	fib6_trap_check $ns "2001:db8:1::/64 dev dummy2 metric 1024" true
359	check_err $? "Route in hardware when should not"
360
361	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1024" false
362	check_err $? "Route not in hardware after appending route"
363
364	log_test "IPv6 single route add"
365
366	for i in $(seq 1 2); do
367		ip -n $ns link del dev dummy$i
368	done
369}
370
371fib_ipv6_metric_test()
372{
373	local ns=$1; shift
374
375	RET=0
376
377	ip -n $ns link add name dummy1 type dummy
378	ip -n $ns link set dev dummy1 up
379
380	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1024
381	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1024" false
382	check_err $? "Route not in hardware when should"
383
384	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1022
385	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1022" false
386	check_err $? "Lowest metric route not in hardware when should"
387
388	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1024" true
389	check_err $? "Highest metric route still in hardware when should not"
390
391	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1023
392	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1023" true
393	check_err $? "Middle metric route in hardware when should not"
394
395	log_test "IPv6 routes with metric"
396
397	ip -n $ns link del dev dummy1
398}
399
400fib_ipv6_append_single_test()
401{
402	local ns=$1; shift
403
404	# When an IPv6 multipath route is added without the 'nexthop' keyword,
405	# different code paths are taken compared to when the keyword is used.
406	# This test tries to verify the former.
407	RET=0
408
409	for i in $(seq 1 2); do
410		ip -n $ns link add name dummy$i type dummy
411		ip -n $ns link set dev dummy$i up
412		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
413	done
414
415	ip -n $ns route add 2001:db8:10::/64 via 2001:db8:1::2 metric 1024
416	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
417	check_err $? "Route not in hardware when should"
418
419	ip -n $ns route append 2001:db8:10::/64 via 2001:db8:2::2 metric 1024
420	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
421	check_err $? "Route not in hardware after appending"
422
423	ip -n $ns route add 2001:db8:10::/64 via 2001:db8:1::2 metric 1025
424	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
425	check_err $? "Route in hardware when should not"
426
427	ip -n $ns route append 2001:db8:10::/64 via 2001:db8:2::2 metric 1025
428	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
429	check_err $? "Route in hardware when should not after appending"
430
431	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
432	check_err $? "Lowest metric route not in hardware when should"
433
434	log_test "IPv6 append single route without 'nexthop' keyword"
435
436	for i in $(seq 1 2); do
437		ip -n $ns link del dev dummy$i
438	done
439}
440
441fib_ipv6_replace_single_test()
442{
443	local ns=$1; shift
444	local i
445
446	RET=0
447
448	for i in $(seq 1 2); do
449		ip -n $ns link add name dummy$i type dummy
450		ip -n $ns link set dev dummy$i up
451	done
452
453	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1024
454	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1 metric 1024" false
455	check_err $? "Route not in hardware when should"
456
457	ip -n $ns route replace 2001:db8:1::/64 dev dummy2 metric 1024
458	fib6_trap_check $ns "2001:db8:1::/64 dev dummy2 metric 1024" false
459	check_err $? "Replacement route not in hardware when should"
460
461	# Add a route with an higher metric and make sure that replacing it
462	# does not affect the lower metric one.
463	ip -n $ns route add 2001:db8:1::/64 dev dummy1 metric 1025
464	ip -n $ns route replace 2001:db8:1::/64 dev dummy2 metric 1025
465
466	fib6_trap_check $ns "2001:db8:1::/64 dev dummy2 metric 1024" false
467	check_err $? "Lowest metric route not in hardware when should"
468	fib6_trap_check $ns "2001:db8:1::/64 dev dummy2 metric 1025" true
469	check_err $? "Highest metric route in hardware when should not"
470
471	log_test "IPv6 single route replace"
472
473	for i in $(seq 1 2); do
474		ip -n $ns link del dev dummy$i
475	done
476}
477
478fib_ipv6_metric_multipath_test()
479{
480	local ns=$1; shift
481
482	RET=0
483
484	for i in $(seq 1 2); do
485		ip -n $ns link add name dummy$i type dummy
486		ip -n $ns link set dev dummy$i up
487		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
488	done
489
490	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
491		nexthop via 2001:db8:1::2 dev dummy1 \
492		nexthop via 2001:db8:2::2 dev dummy2
493	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
494	check_err $? "Route not in hardware when should"
495
496	ip -n $ns route add 2001:db8:10::/64 metric 1022 \
497		nexthop via 2001:db8:1::2 dev dummy1 \
498		nexthop via 2001:db8:2::2 dev dummy2
499	fib6_trap_check $ns "2001:db8:10::/64 metric 1022" false
500	check_err $? "Lowest metric route not in hardware when should"
501
502	ip -n $ns route add 2001:db8:10::/64 metric 1023 \
503		nexthop via 2001:db8:1::2 dev dummy1 \
504		nexthop via 2001:db8:2::2 dev dummy2
505	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" true
506	check_err $? "Highest metric route still in hardware when should not"
507
508	fib6_trap_check $ns "2001:db8:10::/64 metric 1023" true
509	check_err $? "Middle metric route in hardware when should not"
510
511	log_test "IPv6 multipath routes with metric"
512
513	for i in $(seq 1 2); do
514		ip -n $ns link del dev dummy$i
515	done
516}
517
518fib_ipv6_append_multipath_test()
519{
520	local ns=$1; shift
521
522	RET=0
523
524	for i in $(seq 1 3); do
525		ip -n $ns link add name dummy$i type dummy
526		ip -n $ns link set dev dummy$i up
527		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
528	done
529
530	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
531		nexthop via 2001:db8:1::2 dev dummy1
532	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
533	check_err $? "Route not in hardware when should"
534
535	ip -n $ns route append 2001:db8:10::/64 metric 1024 \
536		nexthop via 2001:db8:2::2 dev dummy2 \
537		nexthop via 2001:db8:3::2 dev dummy3
538	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
539	check_err $? "Route not in hardware after appending"
540
541	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
542		nexthop via 2001:db8:1::2 dev dummy1
543	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
544	check_err $? "Route in hardware when should not"
545
546	ip -n $ns route append 2001:db8:10::/64 metric 1025 \
547		nexthop via 2001:db8:2::2 dev dummy2 \
548		nexthop via 2001:db8:3::2 dev dummy3
549	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
550	check_err $? "Route in hardware when should not after appending"
551
552	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
553	check_err $? "Lowest metric route not in hardware when should"
554
555	log_test "IPv6 append multipath route with 'nexthop' keyword"
556
557	for i in $(seq 1 3); do
558		ip -n $ns link del dev dummy$i
559	done
560}
561
562fib_ipv6_replace_multipath_test()
563{
564	local ns=$1; shift
565	local i
566
567	RET=0
568
569	for i in $(seq 1 3); do
570		ip -n $ns link add name dummy$i type dummy
571		ip -n $ns link set dev dummy$i up
572		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
573	done
574
575	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
576		nexthop via 2001:db8:1::2 dev dummy1 \
577		nexthop via 2001:db8:2::2 dev dummy2
578	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
579	check_err $? "Route not in hardware when should"
580
581	ip -n $ns route replace 2001:db8:10::/64 metric 1024 \
582		nexthop via 2001:db8:1::2 dev dummy1 \
583		nexthop via 2001:db8:3::2 dev dummy3
584	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
585	check_err $? "Replacement route not in hardware when should"
586
587	# Add a route with an higher metric and make sure that replacing it
588	# does not affect the lower metric one.
589	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
590		nexthop via 2001:db8:1::2 dev dummy1 \
591		nexthop via 2001:db8:2::2 dev dummy2
592	ip -n $ns route replace 2001:db8:10::/64 metric 1025 \
593		nexthop via 2001:db8:1::2 dev dummy1 \
594		nexthop via 2001:db8:3::2 dev dummy3
595
596	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
597	check_err $? "Lowest metric route not in hardware when should"
598	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
599	check_err $? "Highest metric route in hardware when should not"
600
601	log_test "IPv6 multipath route replace"
602
603	for i in $(seq 1 3); do
604		ip -n $ns link del dev dummy$i
605	done
606}
607
608fib_ipv6_append_multipath_to_single_test()
609{
610	local ns=$1; shift
611
612	# Test that when the first route in the leaf is not a multipath route
613	# and we try to append a multipath route with the same metric to it, it
614	# is not notified.
615	RET=0
616
617	for i in $(seq 1 2); do
618		ip -n $ns link add name dummy$i type dummy
619		ip -n $ns link set dev dummy$i up
620		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
621	done
622
623	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1024
624	fib6_trap_check $ns "2001:db8:10::/64 dev dummy1 metric 1024" false
625	check_err $? "Route not in hardware when should"
626
627	ip -n $ns route append 2001:db8:10::/64 metric 1024 \
628		nexthop via 2001:db8:2::2 dev dummy2
629	fib6_trap_check $ns "2001:db8:10::/64 dev dummy2 metric 1024" true
630	check_err $? "Route in hardware when should not"
631
632	fib6_trap_check $ns "2001:db8:10::/64 dev dummy1 metric 1024" false
633	check_err $? "Route not in hardware after append"
634
635	log_test "IPv6 append multipath route to non-multipath route"
636
637	for i in $(seq 1 2); do
638		ip -n $ns link del dev dummy$i
639	done
640}
641
642fib_ipv6_delete_single_test()
643{
644	local ns=$1; shift
645
646	# Test various deletion scenarios, where only a single route is
647	# deleted from the FIB node.
648	for i in $(seq 1 2); do
649		ip -n $ns link add name dummy$i type dummy
650		ip -n $ns link set dev dummy$i up
651		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
652	done
653
654	# Test deletion of a single route when it is the only route in the FIB
655	# node.
656	RET=0
657
658	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1024
659	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1024
660
661	log_test "IPv6 delete sole single route"
662
663	# Test that deletion of last route does not affect the first one.
664	RET=0
665
666	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1024
667	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1025
668	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1025
669
670	fib6_trap_check $ns "2001:db8:10::/64 dev dummy1 metric 1024" false
671	check_err $? "Route not in hardware after deleting higher metric route"
672
673	log_test "IPv6 delete single route not in hardware"
674
675	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1024
676
677	# Test that first route is replaced by next single route in the FIB
678	# node.
679	RET=0
680
681	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1024
682	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1025
683	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1024
684
685	fib6_trap_check $ns "2001:db8:10::/64 dev dummy1 metric 1025" false
686	check_err $? "Route not in hardware after deleting lowest metric route"
687
688	log_test "IPv6 delete single route - replaced by single"
689
690	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1025
691
692	# Test that first route is replaced by next multipath route in the FIB
693	# node.
694	RET=0
695
696	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1024
697	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
698		nexthop via 2001:db8:1::2 dev dummy1 \
699		nexthop via 2001:db8:2::2 dev dummy2
700	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1024
701
702	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" false
703	check_err $? "Route not in hardware after deleting lowest metric route"
704
705	log_test "IPv6 delete single route - replaced by multipath"
706
707	ip -n $ns route del 2001:db8:10::/64 metric 1025
708
709	# Test deletion of a single nexthop from a multipath route.
710	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
711		nexthop via 2001:db8:1::2 dev dummy1 \
712		nexthop via 2001:db8:2::2 dev dummy2
713	ip -n $ns route del 2001:db8:10::/64 metric 1024 \
714		nexthop via 2001:db8:1::2 dev dummy1
715
716	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
717	check_err $? "Route not in hardware after deleting a single nexthop"
718
719	log_test "IPv6 delete single nexthop"
720
721	ip -n $ns route del 2001:db8:10::/64 metric 1024
722
723	for i in $(seq 1 2); do
724		ip -n $ns link del dev dummy$i
725	done
726}
727
728fib_ipv6_delete_multipath_test()
729{
730	local ns=$1; shift
731
732	# Test various deletion scenarios, where an entire multipath route is
733	# deleted from the FIB node.
734	for i in $(seq 1 2); do
735		ip -n $ns link add name dummy$i type dummy
736		ip -n $ns link set dev dummy$i up
737		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
738	done
739
740	# Test deletion of a multipath route when it is the only route in the
741	# FIB node.
742	RET=0
743
744	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
745		nexthop via 2001:db8:1::2 dev dummy1 \
746		nexthop via 2001:db8:2::2 dev dummy2
747	ip -n $ns route del 2001:db8:10::/64 metric 1024
748
749	log_test "IPv6 delete sole multipath route"
750
751	# Test that deletion of last route does not affect the first one.
752	RET=0
753
754	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
755		nexthop via 2001:db8:1::2 dev dummy1 \
756		nexthop via 2001:db8:2::2 dev dummy2
757	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
758		nexthop via 2001:db8:1::2 dev dummy1 \
759		nexthop via 2001:db8:2::2 dev dummy2
760	ip -n $ns route del 2001:db8:10::/64 metric 1025
761
762	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
763	check_err $? "Route not in hardware after deleting higher metric route"
764
765	log_test "IPv6 delete multipath route not in hardware"
766
767	ip -n $ns route del 2001:db8:10::/64 metric 1024
768
769	# Test that first route is replaced by next single route in the FIB
770	# node.
771	RET=0
772
773	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
774		nexthop via 2001:db8:1::2 dev dummy1 \
775		nexthop via 2001:db8:2::2 dev dummy2
776	ip -n $ns route add 2001:db8:10::/64 dev dummy1 metric 1025
777	ip -n $ns route del 2001:db8:10::/64 metric 1024
778
779	fib6_trap_check $ns "2001:db8:10::/64 dev dummy1 metric 1025" false
780	check_err $? "Route not in hardware after deleting lowest metric route"
781
782	log_test "IPv6 delete multipath route - replaced by single"
783
784	ip -n $ns route del 2001:db8:10::/64 dev dummy1 metric 1025
785
786	# Test that first route is replaced by next multipath route in the FIB
787	# node.
788	RET=0
789
790	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
791		nexthop via 2001:db8:1::2 dev dummy1 \
792		nexthop via 2001:db8:2::2 dev dummy2
793	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
794		nexthop via 2001:db8:1::2 dev dummy1 \
795		nexthop via 2001:db8:2::2 dev dummy2
796	ip -n $ns route del 2001:db8:10::/64 metric 1024
797
798	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" false
799	check_err $? "Route not in hardware after deleting lowest metric route"
800
801	log_test "IPv6 delete multipath route - replaced by multipath"
802
803	ip -n $ns route del 2001:db8:10::/64 metric 1025
804
805	for i in $(seq 1 2); do
806		ip -n $ns link del dev dummy$i
807	done
808}
809
810fib_ipv6_replay_single_test()
811{
812	local ns=$1; shift
813	local devlink_dev=$1; shift
814
815	RET=0
816
817	for i in $(seq 1 2); do
818		ip -n $ns link add name dummy$i type dummy
819		ip -n $ns link set dev dummy$i up
820	done
821
822	ip -n $ns route add 2001:db8:1::/64 dev dummy1
823	ip -n $ns route append 2001:db8:1::/64 dev dummy2
824
825	devlink -N $ns dev reload $devlink_dev
826
827	fib6_trap_check $ns "2001:db8:1::/64 dev dummy1" false
828	check_err $? "First route not in hardware when should"
829
830	fib6_trap_check $ns "2001:db8:1::/64 dev dummy2" true
831	check_err $? "Second route in hardware when should not"
832
833	log_test "IPv6 routes replay - single route"
834
835	for i in $(seq 1 2); do
836		ip -n $ns link del dev dummy$i
837	done
838}
839
840fib_ipv6_replay_multipath_test()
841{
842	local ns=$1; shift
843	local devlink_dev=$1; shift
844
845	RET=0
846
847	for i in $(seq 1 2); do
848		ip -n $ns link add name dummy$i type dummy
849		ip -n $ns link set dev dummy$i up
850		ip -n $ns address add 2001:db8:$i::1/64 dev dummy$i
851	done
852
853	ip -n $ns route add 2001:db8:10::/64 metric 1024 \
854		nexthop via 2001:db8:1::2 dev dummy1 \
855		nexthop via 2001:db8:2::2 dev dummy2
856	ip -n $ns route add 2001:db8:10::/64 metric 1025 \
857		nexthop via 2001:db8:1::2 dev dummy1 \
858		nexthop via 2001:db8:2::2 dev dummy2
859
860	devlink -N $ns dev reload $devlink_dev
861
862	fib6_trap_check $ns "2001:db8:10::/64 metric 1024" false
863	check_err $? "First route not in hardware when should"
864
865	fib6_trap_check $ns "2001:db8:10::/64 metric 1025" true
866	check_err $? "Second route in hardware when should not"
867
868	log_test "IPv6 routes replay - multipath route"
869
870	for i in $(seq 1 2); do
871		ip -n $ns link del dev dummy$i
872	done
873}
874