ACPI: APEI: Fix integer overflow in ghes_estatus_pool_init()
[sfrench/cifs-2.6.git] / tools / testing / selftests / net / fib_nexthops.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # ns: me               | ns: peer              | ns: remote
5 #   2001:db8:91::1     |       2001:db8:91::2  |
6 #   172.16.1.1         |       172.16.1.2      |
7 #            veth1 <---|---> veth2             |
8 #                      |              veth5 <--|--> veth6  172.16.101.1
9 #            veth3 <---|---> veth4             |           2001:db8:101::1
10 #   172.16.2.1         |       172.16.2.2      |
11 #   2001:db8:92::1     |       2001:db8:92::2  |
12 #
13 # This test is for checking IPv4 and IPv6 FIB behavior with nexthop
14 # objects. Device reference counts and network namespace cleanup tested
15 # by use of network namespace for peer.
16
17 ret=0
18 # Kselftest framework requirement - SKIP code is 4.
19 ksft_skip=4
20
21 # all tests in this script. Can be overridden with -t option
22 IPV4_TESTS="
23         ipv4_fcnal
24         ipv4_grp_fcnal
25         ipv4_res_grp_fcnal
26         ipv4_withv6_fcnal
27         ipv4_fcnal_runtime
28         ipv4_large_grp
29         ipv4_large_res_grp
30         ipv4_compat_mode
31         ipv4_fdb_grp_fcnal
32         ipv4_torture
33         ipv4_res_torture
34 "
35
36 IPV6_TESTS="
37         ipv6_fcnal
38         ipv6_grp_fcnal
39         ipv6_res_grp_fcnal
40         ipv6_fcnal_runtime
41         ipv6_large_grp
42         ipv6_large_res_grp
43         ipv6_compat_mode
44         ipv6_fdb_grp_fcnal
45         ipv6_torture
46         ipv6_res_torture
47 "
48
49 ALL_TESTS="
50         basic
51         basic_res
52         ${IPV4_TESTS}
53         ${IPV6_TESTS}
54 "
55 TESTS="${ALL_TESTS}"
56 VERBOSE=0
57 PAUSE_ON_FAIL=no
58 PAUSE=no
59 PING_TIMEOUT=5
60
61 nsid=100
62
63 ################################################################################
64 # utilities
65
66 log_test()
67 {
68         local rc=$1
69         local expected=$2
70         local msg="$3"
71
72         if [ ${rc} -eq ${expected} ]; then
73                 printf "TEST: %-60s  [ OK ]\n" "${msg}"
74                 nsuccess=$((nsuccess+1))
75         else
76                 ret=1
77                 nfail=$((nfail+1))
78                 printf "TEST: %-60s  [FAIL]\n" "${msg}"
79                 if [ "$VERBOSE" = "1" ]; then
80                         echo "    rc=$rc, expected $expected"
81                 fi
82
83                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
84                 echo
85                         echo "hit enter to continue, 'q' to quit"
86                         read a
87                         [ "$a" = "q" ] && exit 1
88                 fi
89         fi
90
91         if [ "${PAUSE}" = "yes" ]; then
92                 echo
93                 echo "hit enter to continue, 'q' to quit"
94                 read a
95                 [ "$a" = "q" ] && exit 1
96         fi
97
98         [ "$VERBOSE" = "1" ] && echo
99 }
100
101 run_cmd()
102 {
103         local cmd="$1"
104         local out
105         local stderr="2>/dev/null"
106
107         if [ "$VERBOSE" = "1" ]; then
108                 printf "COMMAND: $cmd\n"
109                 stderr=
110         fi
111
112         out=$(eval $cmd $stderr)
113         rc=$?
114         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
115                 echo "    $out"
116         fi
117
118         return $rc
119 }
120
121 get_linklocal()
122 {
123         local dev=$1
124         local ns
125         local addr
126
127         [ -n "$2" ] && ns="-netns $2"
128         addr=$(ip $ns -6 -br addr show dev ${dev} | \
129         awk '{
130                 for (i = 3; i <= NF; ++i) {
131                         if ($i ~ /^fe80/)
132                                 print $i
133                 }
134         }'
135         )
136         addr=${addr/\/*}
137
138         [ -z "$addr" ] && return 1
139
140         echo $addr
141
142         return 0
143 }
144
145 create_ns()
146 {
147         local n=${1}
148
149         ip netns del ${n} 2>/dev/null
150
151         set -e
152         ip netns add ${n}
153         ip netns set ${n} $((nsid++))
154         ip -netns ${n} addr add 127.0.0.1/8 dev lo
155         ip -netns ${n} link set lo up
156
157         ip netns exec ${n} sysctl -qw net.ipv4.ip_forward=1
158         ip netns exec ${n} sysctl -qw net.ipv4.fib_multipath_use_neigh=1
159         ip netns exec ${n} sysctl -qw net.ipv4.conf.default.ignore_routes_with_linkdown=1
160         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
161         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.forwarding=1
162         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.forwarding=1
163         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
164         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.accept_dad=0
165         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.accept_dad=0
166
167         set +e
168 }
169
170 setup()
171 {
172         cleanup
173
174         create_ns me
175         create_ns peer
176         create_ns remote
177
178         IP="ip -netns me"
179         BRIDGE="bridge -netns me"
180         set -e
181         $IP li add veth1 type veth peer name veth2
182         $IP li set veth1 up
183         $IP addr add 172.16.1.1/24 dev veth1
184         $IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
185
186         $IP li add veth3 type veth peer name veth4
187         $IP li set veth3 up
188         $IP addr add 172.16.2.1/24 dev veth3
189         $IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
190
191         $IP li set veth2 netns peer up
192         ip -netns peer addr add 172.16.1.2/24 dev veth2
193         ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
194
195         $IP li set veth4 netns peer up
196         ip -netns peer addr add 172.16.2.2/24 dev veth4
197         ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
198
199         ip -netns remote li add veth5 type veth peer name veth6
200         ip -netns remote li set veth5 up
201         ip -netns remote addr add dev veth5 172.16.101.1/24
202         ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
203         ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
204         ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
205
206         ip -netns remote li set veth6 netns peer up
207         ip -netns peer addr add dev veth6 172.16.101.2/24
208         ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
209         set +e
210 }
211
212 cleanup()
213 {
214         local ns
215
216         for ns in me peer remote; do
217                 ip netns del ${ns} 2>/dev/null
218         done
219 }
220
221 check_output()
222 {
223         local out="$1"
224         local expected="$2"
225         local rc=0
226
227         [ "${out}" = "${expected}" ] && return 0
228
229         if [ -z "${out}" ]; then
230                 if [ "$VERBOSE" = "1" ]; then
231                         printf "\nNo entry found\n"
232                         printf "Expected:\n"
233                         printf "    ${expected}\n"
234                 fi
235                 return 1
236         fi
237
238         out=$(echo ${out})
239         if [ "${out}" != "${expected}" ]; then
240                 rc=1
241                 if [ "${VERBOSE}" = "1" ]; then
242                         printf "    Unexpected entry. Have:\n"
243                         printf "        ${out}\n"
244                         printf "    Expected:\n"
245                         printf "        ${expected}\n\n"
246                 else
247                         echo "      WARNING: Unexpected route entry"
248                 fi
249         fi
250
251         return $rc
252 }
253
254 check_nexthop()
255 {
256         local nharg="$1"
257         local expected="$2"
258         local out
259
260         out=$($IP nexthop ls ${nharg} 2>/dev/null)
261
262         check_output "${out}" "${expected}"
263 }
264
265 check_nexthop_bucket()
266 {
267         local nharg="$1"
268         local expected="$2"
269         local out
270
271         # remove the idle time since we cannot match it
272         out=$($IP nexthop bucket ${nharg} \
273                 | sed s/idle_time\ [0-9.]*\ // 2>/dev/null)
274
275         check_output "${out}" "${expected}"
276 }
277
278 check_route()
279 {
280         local pfx="$1"
281         local expected="$2"
282         local out
283
284         out=$($IP route ls match ${pfx} 2>/dev/null)
285
286         check_output "${out}" "${expected}"
287 }
288
289 check_route6()
290 {
291         local pfx="$1"
292         local expected="$2"
293         local out
294
295         out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
296
297         check_output "${out}" "${expected}"
298 }
299
300 check_large_grp()
301 {
302         local ipv=$1
303         local ecmp=$2
304         local grpnum=100
305         local nhidstart=100
306         local grpidstart=1000
307         local iter=0
308         local nhidstr=""
309         local grpidstr=""
310         local grpstr=""
311         local ipstr=""
312
313         if [ $ipv -eq 4 ]; then
314                 ipstr="172.16.1."
315         else
316                 ipstr="2001:db8:91::"
317         fi
318
319         #
320         # Create $grpnum groups with specified $ecmp and dump them
321         #
322
323         # create nexthops with different gateways
324         iter=2
325         while [ $iter -le $(($ecmp + 1)) ]
326         do
327                 nhidstr="$(($nhidstart + $iter))"
328                 run_cmd "$IP nexthop add id $nhidstr via $ipstr$iter dev veth1"
329                 check_nexthop "id $nhidstr" "id $nhidstr via $ipstr$iter dev veth1 scope link"
330
331                 if [ $iter -le $ecmp ]; then
332                         grpstr+="$nhidstr/"
333                 else
334                         grpstr+="$nhidstr"
335                 fi
336                 ((iter++))
337         done
338
339         # create duplicate large ecmp groups
340         iter=0
341         while [ $iter -le $grpnum ]
342         do
343                 grpidstr="$(($grpidstart + $iter))"
344                 run_cmd "$IP nexthop add id $grpidstr group $grpstr"
345                 check_nexthop "id $grpidstr" "id $grpidstr group $grpstr"
346                 ((iter++))
347         done
348
349         # dump large groups
350         run_cmd "$IP nexthop list"
351         log_test $? 0 "Dump large (x$ecmp) ecmp groups"
352 }
353
354 check_large_res_grp()
355 {
356         local ipv=$1
357         local buckets=$2
358         local ipstr=""
359
360         if [ $ipv -eq 4 ]; then
361                 ipstr="172.16.1.2"
362         else
363                 ipstr="2001:db8:91::2"
364         fi
365
366         # create a resilient group with $buckets buckets and dump them
367         run_cmd "$IP nexthop add id 100 via $ipstr dev veth1"
368         run_cmd "$IP nexthop add id 1000 group 100 type resilient buckets $buckets"
369         run_cmd "$IP nexthop bucket list"
370         log_test $? 0 "Dump large (x$buckets) nexthop buckets"
371 }
372
373 start_ip_monitor()
374 {
375         local mtype=$1
376
377         # start the monitor in the background
378         tmpfile=`mktemp /var/run/nexthoptestXXX`
379         mpid=`($IP monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
380         sleep 0.2
381         echo "$mpid $tmpfile"
382 }
383
384 stop_ip_monitor()
385 {
386         local mpid=$1
387         local tmpfile=$2
388         local el=$3
389
390         # check the monitor results
391         kill $mpid
392         lines=`wc -l $tmpfile | cut "-d " -f1`
393         test $lines -eq $el
394         rc=$?
395         rm -rf $tmpfile
396
397         return $rc
398 }
399
400 check_nexthop_fdb_support()
401 {
402         $IP nexthop help 2>&1 | grep -q fdb
403         if [ $? -ne 0 ]; then
404                 echo "SKIP: iproute2 too old, missing fdb nexthop support"
405                 return $ksft_skip
406         fi
407 }
408
409 check_nexthop_res_support()
410 {
411         $IP nexthop help 2>&1 | grep -q resilient
412         if [ $? -ne 0 ]; then
413                 echo "SKIP: iproute2 too old, missing resilient nexthop group support"
414                 return $ksft_skip
415         fi
416 }
417
418 ipv6_fdb_grp_fcnal()
419 {
420         local rc
421
422         echo
423         echo "IPv6 fdb groups functional"
424         echo "--------------------------"
425
426         check_nexthop_fdb_support
427         if [ $? -eq $ksft_skip ]; then
428                 return $ksft_skip
429         fi
430
431         # create group with multiple nexthops
432         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 fdb"
433         run_cmd "$IP nexthop add id 62 via 2001:db8:91::3 fdb"
434         run_cmd "$IP nexthop add id 102 group 61/62 fdb"
435         check_nexthop "id 102" "id 102 group 61/62 fdb"
436         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
437
438         ## get nexthop group
439         run_cmd "$IP nexthop get id 102"
440         check_nexthop "id 102" "id 102 group 61/62 fdb"
441         log_test $? 0 "Get Fdb nexthop group by id"
442
443         # fdb nexthop group can only contain fdb nexthops
444         run_cmd "$IP nexthop add id 63 via 2001:db8:91::4"
445         run_cmd "$IP nexthop add id 64 via 2001:db8:91::5"
446         run_cmd "$IP nexthop add id 103 group 63/64 fdb"
447         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
448
449         # Non fdb nexthop group can not contain fdb nexthops
450         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 fdb"
451         run_cmd "$IP nexthop add id 66 via 2001:db8:91::6 fdb"
452         run_cmd "$IP nexthop add id 104 group 65/66"
453         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
454
455         # fdb nexthop cannot have blackhole
456         run_cmd "$IP nexthop add id 67 blackhole fdb"
457         log_test $? 2 "Fdb Nexthop with blackhole"
458
459         # fdb nexthop with oif
460         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 dev veth1 fdb"
461         log_test $? 2 "Fdb Nexthop with oif"
462
463         # fdb nexthop with onlink
464         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 onlink fdb"
465         log_test $? 2 "Fdb Nexthop with onlink"
466
467         # fdb nexthop with encap
468         run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb"
469         log_test $? 2 "Fdb Nexthop with encap"
470
471         run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
472         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
473         log_test $? 0 "Fdb mac add with nexthop group"
474
475         ## fdb nexthops can only reference nexthop groups and not nexthops
476         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 61 self"
477         log_test $? 255 "Fdb mac add with nexthop"
478
479         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 66"
480         log_test $? 2 "Route add with fdb nexthop"
481
482         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 103"
483         log_test $? 2 "Route add with fdb nexthop group"
484
485         run_cmd "$IP nexthop del id 61"
486         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
487         log_test $? 0 "Fdb entry after deleting a single nexthop"
488
489         run_cmd "$IP nexthop del id 102"
490         log_test $? 0 "Fdb nexthop delete"
491
492         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
493         log_test $? 254 "Fdb entry after deleting a nexthop group"
494
495         $IP link del dev vx10
496 }
497
498 ipv4_fdb_grp_fcnal()
499 {
500         local rc
501
502         echo
503         echo "IPv4 fdb groups functional"
504         echo "--------------------------"
505
506         check_nexthop_fdb_support
507         if [ $? -eq $ksft_skip ]; then
508                 return $ksft_skip
509         fi
510
511         # create group with multiple nexthops
512         run_cmd "$IP nexthop add id 12 via 172.16.1.2 fdb"
513         run_cmd "$IP nexthop add id 13 via 172.16.1.3 fdb"
514         run_cmd "$IP nexthop add id 102 group 12/13 fdb"
515         check_nexthop "id 102" "id 102 group 12/13 fdb"
516         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
517
518         # get nexthop group
519         run_cmd "$IP nexthop get id 102"
520         check_nexthop "id 102" "id 102 group 12/13 fdb"
521         log_test $? 0 "Get Fdb nexthop group by id"
522
523         # fdb nexthop group can only contain fdb nexthops
524         run_cmd "$IP nexthop add id 14 via 172.16.1.2"
525         run_cmd "$IP nexthop add id 15 via 172.16.1.3"
526         run_cmd "$IP nexthop add id 103 group 14/15 fdb"
527         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
528
529         # Non fdb nexthop group can not contain fdb nexthops
530         run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb"
531         run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb"
532         run_cmd "$IP nexthop add id 104 group 14/15"
533         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
534
535         # fdb nexthop cannot have blackhole
536         run_cmd "$IP nexthop add id 18 blackhole fdb"
537         log_test $? 2 "Fdb Nexthop with blackhole"
538
539         # fdb nexthop with oif
540         run_cmd "$IP nexthop add id 16 via 172.16.1.2 dev veth1 fdb"
541         log_test $? 2 "Fdb Nexthop with oif"
542
543         # fdb nexthop with onlink
544         run_cmd "$IP nexthop add id 16 via 172.16.1.2 onlink fdb"
545         log_test $? 2 "Fdb Nexthop with onlink"
546
547         # fdb nexthop with encap
548         run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb"
549         log_test $? 2 "Fdb Nexthop with encap"
550
551         run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
552         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
553         log_test $? 0 "Fdb mac add with nexthop group"
554
555         # fdb nexthops can only reference nexthop groups and not nexthops
556         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self"
557         log_test $? 255 "Fdb mac add with nexthop"
558
559         run_cmd "$IP ro add 172.16.0.0/22 nhid 15"
560         log_test $? 2 "Route add with fdb nexthop"
561
562         run_cmd "$IP ro add 172.16.0.0/22 nhid 103"
563         log_test $? 2 "Route add with fdb nexthop group"
564
565         run_cmd "$IP nexthop del id 12"
566         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
567         log_test $? 0 "Fdb entry after deleting a single nexthop"
568
569         run_cmd "$IP nexthop del id 102"
570         log_test $? 0 "Fdb nexthop delete"
571
572         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
573         log_test $? 254 "Fdb entry after deleting a nexthop group"
574
575         $IP link del dev vx10
576 }
577
578 ################################################################################
579 # basic operations (add, delete, replace) on nexthops and nexthop groups
580 #
581 # IPv6
582
583 ipv6_fcnal()
584 {
585         local rc
586
587         echo
588         echo "IPv6"
589         echo "----------------------"
590
591         run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
592         rc=$?
593         log_test $rc 0 "Create nexthop with id, gw, dev"
594         if [ $rc -ne 0 ]; then
595                 echo "Basic IPv6 create fails; can not continue"
596                 return 1
597         fi
598
599         run_cmd "$IP nexthop get id 52"
600         log_test $? 0 "Get nexthop by id"
601         check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
602
603         run_cmd "$IP nexthop del id 52"
604         log_test $? 0 "Delete nexthop by id"
605         check_nexthop "id 52" ""
606
607         #
608         # gw, device spec
609         #
610         # gw validation, no device - fails since dev required
611         run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
612         log_test $? 2 "Create nexthop - gw only"
613
614         # gw is not reachable throught given dev
615         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
616         log_test $? 2 "Create nexthop - invalid gw+dev combination"
617
618         # onlink arg overrides gw+dev lookup
619         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
620         log_test $? 0 "Create nexthop - gw+dev and onlink"
621
622         # admin down should delete nexthops
623         set -e
624         run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
625         run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
626         run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
627         run_cmd "$IP li set dev veth1 down"
628         set +e
629         check_nexthop "dev veth1" ""
630         log_test $? 0 "Nexthops removed on admin down"
631 }
632
633 ipv6_grp_refs()
634 {
635         if [ ! -x "$(command -v mausezahn)" ]; then
636                 echo "SKIP: Could not run test; need mausezahn tool"
637                 return
638         fi
639
640         run_cmd "$IP link set dev veth1 up"
641         run_cmd "$IP link add veth1.10 link veth1 up type vlan id 10"
642         run_cmd "$IP link add veth1.20 link veth1 up type vlan id 20"
643         run_cmd "$IP -6 addr add 2001:db8:91::1/64 dev veth1.10"
644         run_cmd "$IP -6 addr add 2001:db8:92::1/64 dev veth1.20"
645         run_cmd "$IP -6 neigh add 2001:db8:91::2 lladdr 00:11:22:33:44:55 dev veth1.10"
646         run_cmd "$IP -6 neigh add 2001:db8:92::2 lladdr 00:11:22:33:44:55 dev veth1.20"
647         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1.10"
648         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth1.20"
649         run_cmd "$IP nexthop add id 102 group 100"
650         run_cmd "$IP route add 2001:db8:101::1/128 nhid 102"
651
652         # create per-cpu dsts through nh 100
653         run_cmd "ip netns exec me mausezahn -6 veth1.10 -B 2001:db8:101::1 -A 2001:db8:91::1 -c 5 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1"
654
655         # remove nh 100 from the group to delete the route potentially leaving
656         # a stale per-cpu dst which holds a reference to the nexthop's net
657         # device and to the IPv6 route
658         run_cmd "$IP nexthop replace id 102 group 101"
659         run_cmd "$IP route del 2001:db8:101::1/128"
660
661         # add both nexthops to the group so a reference is taken on them
662         run_cmd "$IP nexthop replace id 102 group 100/101"
663
664         # if the bug described in commit "net: nexthop: release IPv6 per-cpu
665         # dsts when replacing a nexthop group" exists at this point we have
666         # an unlinked IPv6 route (but not freed due to stale dst) with a
667         # reference over the group so we delete the group which will again
668         # only unlink it due to the route reference
669         run_cmd "$IP nexthop del id 102"
670
671         # delete the nexthop with stale dst, since we have an unlinked
672         # group with a ref to it and an unlinked IPv6 route with ref to the
673         # group, the nh will only be unlinked and not freed so the stale dst
674         # remains forever and we get a net device refcount imbalance
675         run_cmd "$IP nexthop del id 100"
676
677         # if a reference was lost this command will hang because the net device
678         # cannot be removed
679         timeout -s KILL 5 ip netns exec me ip link del veth1.10 >/dev/null 2>&1
680
681         # we can't cleanup if the command is hung trying to delete the netdev
682         if [ $? -eq 137 ]; then
683                 return 1
684         fi
685
686         # cleanup
687         run_cmd "$IP link del veth1.20"
688         run_cmd "$IP nexthop flush"
689
690         return 0
691 }
692
693 ipv6_grp_fcnal()
694 {
695         local rc
696
697         echo
698         echo "IPv6 groups functional"
699         echo "----------------------"
700
701         # basic functionality: create a nexthop group, default weight
702         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
703         run_cmd "$IP nexthop add id 101 group 61"
704         log_test $? 0 "Create nexthop group with single nexthop"
705
706         # get nexthop group
707         run_cmd "$IP nexthop get id 101"
708         log_test $? 0 "Get nexthop group by id"
709         check_nexthop "id 101" "id 101 group 61"
710
711         # delete nexthop group
712         run_cmd "$IP nexthop del id 101"
713         log_test $? 0 "Delete nexthop group by id"
714         check_nexthop "id 101" ""
715
716         $IP nexthop flush >/dev/null 2>&1
717         check_nexthop "id 101" ""
718
719         #
720         # create group with multiple nexthops - mix of gw and dev only
721         #
722         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
723         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
724         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
725         run_cmd "$IP nexthop add id 65 dev veth1"
726         run_cmd "$IP nexthop add id 102 group 62/63/64/65"
727         log_test $? 0 "Nexthop group with multiple nexthops"
728         check_nexthop "id 102" "id 102 group 62/63/64/65"
729
730         # Delete nexthop in a group and group is updated
731         run_cmd "$IP nexthop del id 63"
732         check_nexthop "id 102" "id 102 group 62/64/65"
733         log_test $? 0 "Nexthop group updated when entry is deleted"
734
735         # create group with multiple weighted nexthops
736         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
737         run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
738         log_test $? 0 "Nexthop group with weighted nexthops"
739         check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
740
741         # Delete nexthop in a weighted group and group is updated
742         run_cmd "$IP nexthop del id 63"
743         check_nexthop "id 103" "id 103 group 62/64,3/65,4"
744         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
745
746         # admin down - nexthop is removed from group
747         run_cmd "$IP li set dev veth1 down"
748         check_nexthop "dev veth1" ""
749         log_test $? 0 "Nexthops in groups removed on admin down"
750
751         # expect groups to have been deleted as well
752         check_nexthop "" ""
753
754         run_cmd "$IP li set dev veth1 up"
755
756         $IP nexthop flush >/dev/null 2>&1
757
758         # group with nexthops using different devices
759         set -e
760         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
761         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
762         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
763         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
764
765         run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
766         run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
767         run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
768         run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
769         set +e
770
771         # multiple groups with same nexthop
772         run_cmd "$IP nexthop add id 104 group 62"
773         run_cmd "$IP nexthop add id 105 group 62"
774         check_nexthop "group" "id 104 group 62 id 105 group 62"
775         log_test $? 0 "Multiple groups with same nexthop"
776
777         run_cmd "$IP nexthop flush groups"
778         [ $? -ne 0 ] && return 1
779
780         # on admin down of veth1, it should be removed from the group
781         run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
782         run_cmd "$IP li set veth1 down"
783         check_nexthop "id 105" "id 105 group 72/73"
784         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
785
786         run_cmd "$IP nexthop add id 106 group 105/74"
787         log_test $? 2 "Nexthop group can not have a group as an entry"
788
789         # a group can have a blackhole entry only if it is the only
790         # nexthop in the group. Needed for atomic replace with an
791         # actual nexthop group
792         run_cmd "$IP -6 nexthop add id 31 blackhole"
793         run_cmd "$IP nexthop add id 107 group 31"
794         log_test $? 0 "Nexthop group with a blackhole entry"
795
796         run_cmd "$IP nexthop add id 108 group 31/24"
797         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
798
799         ipv6_grp_refs
800         log_test $? 0 "Nexthop group replace refcounts"
801 }
802
803 ipv6_res_grp_fcnal()
804 {
805         local rc
806
807         echo
808         echo "IPv6 resilient groups functional"
809         echo "--------------------------------"
810
811         check_nexthop_res_support
812         if [ $? -eq $ksft_skip ]; then
813                 return $ksft_skip
814         fi
815
816         #
817         # migration of nexthop buckets - equal weights
818         #
819         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
820         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
821         run_cmd "$IP nexthop add id 102 group 62/63 type resilient buckets 2 idle_timer 0"
822
823         run_cmd "$IP nexthop del id 63"
824         check_nexthop "id 102" \
825                 "id 102 group 62 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
826         log_test $? 0 "Nexthop group updated when entry is deleted"
827         check_nexthop_bucket "list id 102" \
828                 "id 102 index 0 nhid 62 id 102 index 1 nhid 62"
829         log_test $? 0 "Nexthop buckets updated when entry is deleted"
830
831         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
832         run_cmd "$IP nexthop replace id 102 group 62/63 type resilient buckets 2 idle_timer 0"
833         check_nexthop "id 102" \
834                 "id 102 group 62/63 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
835         log_test $? 0 "Nexthop group updated after replace"
836         check_nexthop_bucket "list id 102" \
837                 "id 102 index 0 nhid 63 id 102 index 1 nhid 62"
838         log_test $? 0 "Nexthop buckets updated after replace"
839
840         $IP nexthop flush >/dev/null 2>&1
841
842         #
843         # migration of nexthop buckets - unequal weights
844         #
845         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
846         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
847         run_cmd "$IP nexthop add id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
848
849         run_cmd "$IP nexthop del id 63"
850         check_nexthop "id 102" \
851                 "id 102 group 62,3 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
852         log_test $? 0 "Nexthop group updated when entry is deleted - nECMP"
853         check_nexthop_bucket "list id 102" \
854                 "id 102 index 0 nhid 62 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
855         log_test $? 0 "Nexthop buckets updated when entry is deleted - nECMP"
856
857         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
858         run_cmd "$IP nexthop replace id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
859         check_nexthop "id 102" \
860                 "id 102 group 62,3/63 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
861         log_test $? 0 "Nexthop group updated after replace - nECMP"
862         check_nexthop_bucket "list id 102" \
863                 "id 102 index 0 nhid 63 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
864         log_test $? 0 "Nexthop buckets updated after replace - nECMP"
865 }
866
867 ipv6_fcnal_runtime()
868 {
869         local rc
870
871         echo
872         echo "IPv6 functional runtime"
873         echo "-----------------------"
874
875         #
876         # IPv6 - the basics
877         #
878         run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
879         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
880         log_test $? 0 "Route add"
881
882         run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
883         log_test $? 0 "Route delete"
884
885         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
886         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
887         log_test $? 0 "Ping with nexthop"
888
889         run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
890         run_cmd "$IP nexthop add id 122 group 81/82"
891         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
892         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
893         log_test $? 0 "Ping - multipath"
894
895         #
896         # IPv6 with blackhole nexthops
897         #
898         run_cmd "$IP -6 nexthop add id 83 blackhole"
899         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
900         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
901         log_test $? 2 "Ping - blackhole"
902
903         run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
904         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
905         log_test $? 0 "Ping - blackhole replaced with gateway"
906
907         run_cmd "$IP -6 nexthop replace id 83 blackhole"
908         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
909         log_test $? 2 "Ping - gateway replaced by blackhole"
910
911         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
912         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
913         if [ $? -eq 0 ]; then
914                 run_cmd "$IP nexthop replace id 122 group 83"
915                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
916                 log_test $? 2 "Ping - group with blackhole"
917
918                 run_cmd "$IP nexthop replace id 122 group 81/82"
919                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
920                 log_test $? 0 "Ping - group blackhole replaced with gateways"
921         else
922                 log_test 2 0 "Ping - multipath failed"
923         fi
924
925         #
926         # device only and gw + dev only mix
927         #
928         run_cmd "$IP -6 nexthop add id 85 dev veth1"
929         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
930         log_test $? 0 "IPv6 route with device only nexthop"
931         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
932
933         run_cmd "$IP nexthop add id 123 group 81/85"
934         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
935         log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
936         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 123 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop dev veth1 weight 1"
937
938         #
939         # IPv6 route with v4 nexthop - not allowed
940         #
941         run_cmd "$IP ro delete 2001:db8:101::1/128"
942         run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
943         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
944         log_test $? 2 "IPv6 route can not have a v4 gateway"
945
946         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
947         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
948         log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
949
950         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
951         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
952         log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
953
954         run_cmd "$IP nexthop add id 86 via 2001:db8:92::2 dev veth3"
955         run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
956         run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
957         run_cmd "$IP nexthop add id 124 group 86/87/88"
958         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
959         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
960
961         run_cmd "$IP nexthop del id 88"
962         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
963         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
964
965         run_cmd "$IP nexthop del id 87"
966         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
967         log_test $? 0 "IPv6 route using a group after removing v4 gateways"
968
969         run_cmd "$IP ro delete 2001:db8:101::1/128"
970         run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
971         run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
972         run_cmd "$IP nexthop replace id 124 group 86/87/88"
973         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
974         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
975
976         run_cmd "$IP nexthop replace id 88 via 2001:db8:92::2 dev veth3"
977         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
978         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
979
980         run_cmd "$IP nexthop replace id 87 via 2001:db8:92::2 dev veth3"
981         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
982         log_test $? 0 "IPv6 route using a group after replacing v4 gateways"
983
984         $IP nexthop flush >/dev/null 2>&1
985
986         #
987         # weird IPv6 cases
988         #
989         run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
990         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
991
992         # route can not use prefsrc with nexthops
993         run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 from 2001:db8:91::1"
994         log_test $? 2 "IPv6 route can not use src routing with external nexthop"
995
996         # check cleanup path on invalid metric
997         run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 congctl lock foo"
998         log_test $? 2 "IPv6 route with invalid metric"
999
1000         # rpfilter and default route
1001         $IP nexthop flush >/dev/null 2>&1
1002         run_cmd "ip netns exec me ip6tables -t mangle -I PREROUTING 1 -m rpfilter --invert -j DROP"
1003         run_cmd "$IP nexthop add id 91 via 2001:db8:91::2 dev veth1"
1004         run_cmd "$IP nexthop add id 92 via 2001:db8:92::2 dev veth3"
1005         run_cmd "$IP nexthop add id 93 group 91/92"
1006         run_cmd "$IP -6 ro add default nhid 91"
1007         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
1008         log_test $? 0 "Nexthop with default route and rpfilter"
1009         run_cmd "$IP -6 ro replace default nhid 93"
1010         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
1011         log_test $? 0 "Nexthop with multipath default route and rpfilter"
1012
1013         # TO-DO:
1014         # existing route with old nexthop; append route with new nexthop
1015         # existing route with old nexthop; replace route with new
1016         # existing route with new nexthop; replace route with old
1017         # route with src address and using nexthop - not allowed
1018 }
1019
1020 ipv6_large_grp()
1021 {
1022         local ecmp=32
1023
1024         echo
1025         echo "IPv6 large groups (x$ecmp)"
1026         echo "---------------------"
1027
1028         check_large_grp 6 $ecmp
1029
1030         $IP nexthop flush >/dev/null 2>&1
1031 }
1032
1033 ipv6_large_res_grp()
1034 {
1035         echo
1036         echo "IPv6 large resilient group (128k buckets)"
1037         echo "-----------------------------------------"
1038
1039         check_nexthop_res_support
1040         if [ $? -eq $ksft_skip ]; then
1041                 return $ksft_skip
1042         fi
1043
1044         check_large_res_grp 6 $((128 * 1024))
1045
1046         $IP nexthop flush >/dev/null 2>&1
1047 }
1048
1049 ipv6_del_add_loop1()
1050 {
1051         while :; do
1052                 $IP nexthop del id 100
1053                 $IP nexthop add id 100 via 2001:db8:91::2 dev veth1
1054         done >/dev/null 2>&1
1055 }
1056
1057 ipv6_grp_replace_loop()
1058 {
1059         while :; do
1060                 $IP nexthop replace id 102 group 100/101
1061         done >/dev/null 2>&1
1062 }
1063
1064 ipv6_torture()
1065 {
1066         local pid1
1067         local pid2
1068         local pid3
1069         local pid4
1070         local pid5
1071
1072         echo
1073         echo "IPv6 runtime torture"
1074         echo "--------------------"
1075         if [ ! -x "$(command -v mausezahn)" ]; then
1076                 echo "SKIP: Could not run test; need mausezahn tool"
1077                 return
1078         fi
1079
1080         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1"
1081         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth3"
1082         run_cmd "$IP nexthop add id 102 group 100/101"
1083         run_cmd "$IP route add 2001:db8:101::1 nhid 102"
1084         run_cmd "$IP route add 2001:db8:101::2 nhid 102"
1085
1086         ipv6_del_add_loop1 &
1087         pid1=$!
1088         ipv6_grp_replace_loop &
1089         pid2=$!
1090         ip netns exec me ping -f 2001:db8:101::1 >/dev/null 2>&1 &
1091         pid3=$!
1092         ip netns exec me ping -f 2001:db8:101::2 >/dev/null 2>&1 &
1093         pid4=$!
1094         ip netns exec me mausezahn -6 veth1 -B 2001:db8:101::2 -A 2001:db8:91::1 -c 0 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1095         pid5=$!
1096
1097         sleep 300
1098         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1099         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1100
1101         # if we did not crash, success
1102         log_test 0 0 "IPv6 torture test"
1103 }
1104
1105 ipv6_res_grp_replace_loop()
1106 {
1107         while :; do
1108                 $IP nexthop replace id 102 group 100/101 type resilient
1109         done >/dev/null 2>&1
1110 }
1111
1112 ipv6_res_torture()
1113 {
1114         local pid1
1115         local pid2
1116         local pid3
1117         local pid4
1118         local pid5
1119
1120         echo
1121         echo "IPv6 runtime resilient nexthop group torture"
1122         echo "--------------------------------------------"
1123
1124         check_nexthop_res_support
1125         if [ $? -eq $ksft_skip ]; then
1126                 return $ksft_skip
1127         fi
1128
1129         if [ ! -x "$(command -v mausezahn)" ]; then
1130                 echo "SKIP: Could not run test; need mausezahn tool"
1131                 return
1132         fi
1133
1134         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1"
1135         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth3"
1136         run_cmd "$IP nexthop add id 102 group 100/101 type resilient buckets 512 idle_timer 0"
1137         run_cmd "$IP route add 2001:db8:101::1 nhid 102"
1138         run_cmd "$IP route add 2001:db8:101::2 nhid 102"
1139
1140         ipv6_del_add_loop1 &
1141         pid1=$!
1142         ipv6_res_grp_replace_loop &
1143         pid2=$!
1144         ip netns exec me ping -f 2001:db8:101::1 >/dev/null 2>&1 &
1145         pid3=$!
1146         ip netns exec me ping -f 2001:db8:101::2 >/dev/null 2>&1 &
1147         pid4=$!
1148         ip netns exec me mausezahn -6 veth1 \
1149                             -B 2001:db8:101::2 -A 2001:db8:91::1 -c 0 \
1150                             -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1151         pid5=$!
1152
1153         sleep 300
1154         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1155         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1156
1157         # if we did not crash, success
1158         log_test 0 0 "IPv6 resilient nexthop group torture test"
1159 }
1160
1161 ipv4_fcnal()
1162 {
1163         local rc
1164
1165         echo
1166         echo "IPv4 functional"
1167         echo "----------------------"
1168
1169         #
1170         # basic IPv4 ops - add, get, delete
1171         #
1172         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1173         rc=$?
1174         log_test $rc 0 "Create nexthop with id, gw, dev"
1175         if [ $rc -ne 0 ]; then
1176                 echo "Basic IPv4 create fails; can not continue"
1177                 return 1
1178         fi
1179
1180         run_cmd "$IP nexthop get id 12"
1181         log_test $? 0 "Get nexthop by id"
1182         check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
1183
1184         run_cmd "$IP nexthop del id 12"
1185         log_test $? 0 "Delete nexthop by id"
1186         check_nexthop "id 52" ""
1187
1188         #
1189         # gw, device spec
1190         #
1191         # gw validation, no device - fails since dev is required
1192         run_cmd "$IP nexthop add id 12 via 172.16.2.3"
1193         log_test $? 2 "Create nexthop - gw only"
1194
1195         # gw not reachable through given dev
1196         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1"
1197         log_test $? 2 "Create nexthop - invalid gw+dev combination"
1198
1199         # onlink flag overrides gw+dev lookup
1200         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1 onlink"
1201         log_test $? 0 "Create nexthop - gw+dev and onlink"
1202
1203         # admin down should delete nexthops
1204         set -e
1205         run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
1206         run_cmd "$IP nexthop add id 16 via 172.16.1.4 dev veth1"
1207         run_cmd "$IP nexthop add id 17 via 172.16.1.5 dev veth1"
1208         run_cmd "$IP li set dev veth1 down"
1209         set +e
1210         check_nexthop "dev veth1" ""
1211         log_test $? 0 "Nexthops removed on admin down"
1212
1213         # nexthop route delete warning: route add with nhid and delete
1214         # using device
1215         run_cmd "$IP li set dev veth1 up"
1216         run_cmd "$IP nexthop add id 12 via 172.16.1.3 dev veth1"
1217         out1=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
1218         run_cmd "$IP route add 172.16.101.1/32 nhid 12"
1219         run_cmd "$IP route delete 172.16.101.1/32 dev veth1"
1220         out2=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
1221         [ $out1 -eq $out2 ]
1222         rc=$?
1223         log_test $rc 0 "Delete nexthop route warning"
1224         run_cmd "$IP route delete 172.16.101.1/32 nhid 12"
1225         run_cmd "$IP nexthop del id 12"
1226 }
1227
1228 ipv4_grp_fcnal()
1229 {
1230         local rc
1231
1232         echo
1233         echo "IPv4 groups functional"
1234         echo "----------------------"
1235
1236         # basic functionality: create a nexthop group, default weight
1237         run_cmd "$IP nexthop add id 11 via 172.16.1.2 dev veth1"
1238         run_cmd "$IP nexthop add id 101 group 11"
1239         log_test $? 0 "Create nexthop group with single nexthop"
1240
1241         # get nexthop group
1242         run_cmd "$IP nexthop get id 101"
1243         log_test $? 0 "Get nexthop group by id"
1244         check_nexthop "id 101" "id 101 group 11"
1245
1246         # delete nexthop group
1247         run_cmd "$IP nexthop del id 101"
1248         log_test $? 0 "Delete nexthop group by id"
1249         check_nexthop "id 101" ""
1250
1251         $IP nexthop flush >/dev/null 2>&1
1252
1253         #
1254         # create group with multiple nexthops
1255         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1256         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1257         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
1258         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
1259         run_cmd "$IP nexthop add id 102 group 12/13/14/15"
1260         log_test $? 0 "Nexthop group with multiple nexthops"
1261         check_nexthop "id 102" "id 102 group 12/13/14/15"
1262
1263         # Delete nexthop in a group and group is updated
1264         run_cmd "$IP nexthop del id 13"
1265         check_nexthop "id 102" "id 102 group 12/14/15"
1266         log_test $? 0 "Nexthop group updated when entry is deleted"
1267
1268         # create group with multiple weighted nexthops
1269         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1270         run_cmd "$IP nexthop add id 103 group 12/13,2/14,3/15,4"
1271         log_test $? 0 "Nexthop group with weighted nexthops"
1272         check_nexthop "id 103" "id 103 group 12/13,2/14,3/15,4"
1273
1274         # Delete nexthop in a weighted group and group is updated
1275         run_cmd "$IP nexthop del id 13"
1276         check_nexthop "id 103" "id 103 group 12/14,3/15,4"
1277         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
1278
1279         # admin down - nexthop is removed from group
1280         run_cmd "$IP li set dev veth1 down"
1281         check_nexthop "dev veth1" ""
1282         log_test $? 0 "Nexthops in groups removed on admin down"
1283
1284         # expect groups to have been deleted as well
1285         check_nexthop "" ""
1286
1287         run_cmd "$IP li set dev veth1 up"
1288
1289         $IP nexthop flush >/dev/null 2>&1
1290
1291         # group with nexthops using different devices
1292         set -e
1293         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1294         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1295         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
1296         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
1297
1298         run_cmd "$IP nexthop add id 22 via 172.16.2.2 dev veth3"
1299         run_cmd "$IP nexthop add id 23 via 172.16.2.3 dev veth3"
1300         run_cmd "$IP nexthop add id 24 via 172.16.2.4 dev veth3"
1301         run_cmd "$IP nexthop add id 25 via 172.16.2.5 dev veth3"
1302         set +e
1303
1304         # multiple groups with same nexthop
1305         run_cmd "$IP nexthop add id 104 group 12"
1306         run_cmd "$IP nexthop add id 105 group 12"
1307         check_nexthop "group" "id 104 group 12 id 105 group 12"
1308         log_test $? 0 "Multiple groups with same nexthop"
1309
1310         run_cmd "$IP nexthop flush groups"
1311         [ $? -ne 0 ] && return 1
1312
1313         # on admin down of veth1, it should be removed from the group
1314         run_cmd "$IP nexthop add id 105 group 12/13/22/23/14"
1315         run_cmd "$IP li set veth1 down"
1316         check_nexthop "id 105" "id 105 group 22/23"
1317         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
1318
1319         run_cmd "$IP nexthop add id 106 group 105/24"
1320         log_test $? 2 "Nexthop group can not have a group as an entry"
1321
1322         # a group can have a blackhole entry only if it is the only
1323         # nexthop in the group. Needed for atomic replace with an
1324         # actual nexthop group
1325         run_cmd "$IP nexthop add id 31 blackhole"
1326         run_cmd "$IP nexthop add id 107 group 31"
1327         log_test $? 0 "Nexthop group with a blackhole entry"
1328
1329         run_cmd "$IP nexthop add id 108 group 31/24"
1330         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
1331 }
1332
1333 ipv4_res_grp_fcnal()
1334 {
1335         local rc
1336
1337         echo
1338         echo "IPv4 resilient groups functional"
1339         echo "--------------------------------"
1340
1341         check_nexthop_res_support
1342         if [ $? -eq $ksft_skip ]; then
1343                 return $ksft_skip
1344         fi
1345
1346         #
1347         # migration of nexthop buckets - equal weights
1348         #
1349         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1350         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1351         run_cmd "$IP nexthop add id 102 group 12/13 type resilient buckets 2 idle_timer 0"
1352
1353         run_cmd "$IP nexthop del id 13"
1354         check_nexthop "id 102" \
1355                 "id 102 group 12 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1356         log_test $? 0 "Nexthop group updated when entry is deleted"
1357         check_nexthop_bucket "list id 102" \
1358                 "id 102 index 0 nhid 12 id 102 index 1 nhid 12"
1359         log_test $? 0 "Nexthop buckets updated when entry is deleted"
1360
1361         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1362         run_cmd "$IP nexthop replace id 102 group 12/13 type resilient buckets 2 idle_timer 0"
1363         check_nexthop "id 102" \
1364                 "id 102 group 12/13 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1365         log_test $? 0 "Nexthop group updated after replace"
1366         check_nexthop_bucket "list id 102" \
1367                 "id 102 index 0 nhid 13 id 102 index 1 nhid 12"
1368         log_test $? 0 "Nexthop buckets updated after replace"
1369
1370         $IP nexthop flush >/dev/null 2>&1
1371
1372         #
1373         # migration of nexthop buckets - unequal weights
1374         #
1375         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1376         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1377         run_cmd "$IP nexthop add id 102 group 12,3/13,1 type resilient buckets 4 idle_timer 0"
1378
1379         run_cmd "$IP nexthop del id 13"
1380         check_nexthop "id 102" \
1381                 "id 102 group 12,3 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1382         log_test $? 0 "Nexthop group updated when entry is deleted - nECMP"
1383         check_nexthop_bucket "list id 102" \
1384                 "id 102 index 0 nhid 12 id 102 index 1 nhid 12 id 102 index 2 nhid 12 id 102 index 3 nhid 12"
1385         log_test $? 0 "Nexthop buckets updated when entry is deleted - nECMP"
1386
1387         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1388         run_cmd "$IP nexthop replace id 102 group 12,3/13,1 type resilient buckets 4 idle_timer 0"
1389         check_nexthop "id 102" \
1390                 "id 102 group 12,3/13 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1391         log_test $? 0 "Nexthop group updated after replace - nECMP"
1392         check_nexthop_bucket "list id 102" \
1393                 "id 102 index 0 nhid 13 id 102 index 1 nhid 12 id 102 index 2 nhid 12 id 102 index 3 nhid 12"
1394         log_test $? 0 "Nexthop buckets updated after replace - nECMP"
1395 }
1396
1397 ipv4_withv6_fcnal()
1398 {
1399         local lladdr
1400
1401         set -e
1402         lladdr=$(get_linklocal veth2 peer)
1403         run_cmd "$IP nexthop add id 11 via ${lladdr} dev veth1"
1404         set +e
1405         run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
1406         log_test $? 0 "IPv6 nexthop with IPv4 route"
1407         check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
1408
1409         set -e
1410         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1411         run_cmd "$IP nexthop add id 101 group 11/12"
1412         set +e
1413         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
1414         log_test $? 0 "IPv6 nexthop with IPv4 route"
1415
1416         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1417
1418         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1419         log_test $? 0 "IPv4 route with IPv6 gateway"
1420         check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
1421
1422         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
1423         log_test $? 2 "IPv4 route with invalid IPv6 gateway"
1424 }
1425
1426 ipv4_fcnal_runtime()
1427 {
1428         local lladdr
1429         local rc
1430
1431         echo
1432         echo "IPv4 functional runtime"
1433         echo "-----------------------"
1434
1435         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
1436         run_cmd "$IP ro add 172.16.101.1/32 nhid 21"
1437         log_test $? 0 "Route add"
1438         check_route "172.16.101.1" "172.16.101.1 nhid 21 via 172.16.1.2 dev veth1"
1439
1440         run_cmd "$IP ro delete 172.16.101.1/32 nhid 21"
1441         log_test $? 0 "Route delete"
1442
1443         #
1444         # scope mismatch
1445         #
1446         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
1447         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
1448         log_test $? 2 "Route add - scope conflict with nexthop"
1449
1450         run_cmd "$IP nexthop replace id 22 dev veth3"
1451         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
1452         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
1453         log_test $? 2 "Nexthop replace with invalid scope for existing route"
1454
1455         # check cleanup path on invalid metric
1456         run_cmd "$IP ro add 172.16.101.2/32 nhid 22 congctl lock foo"
1457         log_test $? 2 "IPv4 route with invalid metric"
1458
1459         #
1460         # add route with nexthop and check traffic
1461         #
1462         run_cmd "$IP nexthop replace id 21 via 172.16.1.2 dev veth1"
1463         run_cmd "$IP ro replace 172.16.101.1/32 nhid 21"
1464         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1465         log_test $? 0 "Basic ping"
1466
1467         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
1468         run_cmd "$IP nexthop add id 122 group 21/22"
1469         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
1470         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1471         log_test $? 0 "Ping - multipath"
1472
1473         run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
1474
1475         #
1476         # multiple default routes
1477         # - tests fib_select_default
1478         run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
1479         run_cmd "$IP ro add default nhid 501"
1480         run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
1481         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1482         log_test $? 0 "Ping - multiple default routes, nh first"
1483
1484         # flip the order
1485         run_cmd "$IP ro del default nhid 501"
1486         run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
1487         run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
1488         run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
1489         run_cmd "$IP ro add default nhid 501 metric 20"
1490         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1491         log_test $? 0 "Ping - multiple default routes, nh second"
1492
1493         run_cmd "$IP nexthop delete nhid 501"
1494         run_cmd "$IP ro del default"
1495
1496         #
1497         # IPv4 with blackhole nexthops
1498         #
1499         run_cmd "$IP nexthop add id 23 blackhole"
1500         run_cmd "$IP ro replace 172.16.101.1/32 nhid 23"
1501         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1502         log_test $? 2 "Ping - blackhole"
1503
1504         run_cmd "$IP nexthop replace id 23 via 172.16.1.2 dev veth1"
1505         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1506         log_test $? 0 "Ping - blackhole replaced with gateway"
1507
1508         run_cmd "$IP nexthop replace id 23 blackhole"
1509         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1510         log_test $? 2 "Ping - gateway replaced by blackhole"
1511
1512         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
1513         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1514         if [ $? -eq 0 ]; then
1515                 run_cmd "$IP nexthop replace id 122 group 23"
1516                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1517                 log_test $? 2 "Ping - group with blackhole"
1518
1519                 run_cmd "$IP nexthop replace id 122 group 21/22"
1520                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1521                 log_test $? 0 "Ping - group blackhole replaced with gateways"
1522         else
1523                 log_test 2 0 "Ping - multipath failed"
1524         fi
1525
1526         #
1527         # device only and gw + dev only mix
1528         #
1529         run_cmd "$IP nexthop add id 85 dev veth1"
1530         run_cmd "$IP ro replace 172.16.101.1/32 nhid 85"
1531         log_test $? 0 "IPv4 route with device only nexthop"
1532         check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
1533
1534         run_cmd "$IP nexthop add id 123 group 21/85"
1535         run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
1536         log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
1537         check_route "172.16.101.1" "172.16.101.1 nhid 123 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop dev veth1 weight 1"
1538
1539         #
1540         # IPv4 with IPv6
1541         #
1542         set -e
1543         lladdr=$(get_linklocal veth2 peer)
1544         run_cmd "$IP nexthop add id 24 via ${lladdr} dev veth1"
1545         set +e
1546         run_cmd "$IP ro replace 172.16.101.1/32 nhid 24"
1547         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1548         log_test $? 0 "IPv6 nexthop with IPv4 route"
1549
1550         $IP neigh sh | grep -q "${lladdr} dev veth1"
1551         if [ $? -eq 1 ]; then
1552                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1553                 $IP neigh sh | grep 'dev veth1'
1554         fi
1555
1556         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1557         if [ $? -eq 0 ]; then
1558                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1559                 $IP neigh sh | grep 'dev veth1'
1560         fi
1561
1562         set -e
1563         run_cmd "$IP nexthop add id 25 via 172.16.1.2 dev veth1"
1564         run_cmd "$IP nexthop add id 101 group 24/25"
1565         set +e
1566         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
1567         log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
1568
1569         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1570
1571         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1572         log_test $? 0 "IPv6 nexthop with IPv4 route"
1573
1574         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1575         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1576         log_test $? 0 "IPv4 route with IPv6 gateway"
1577
1578         $IP neigh sh | grep -q "${lladdr} dev veth1"
1579         if [ $? -eq 1 ]; then
1580                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1581                 $IP neigh sh | grep 'dev veth1'
1582         fi
1583
1584         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1585         if [ $? -eq 0 ]; then
1586                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1587                 $IP neigh sh | grep 'dev veth1'
1588         fi
1589
1590         run_cmd "$IP ro del 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1591         run_cmd "$IP -4 ro add default via inet6 ${lladdr} dev veth1"
1592         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1593         log_test $? 0 "IPv4 default route with IPv6 gateway"
1594
1595         #
1596         # MPLS as an example of LWT encap
1597         #
1598         run_cmd "$IP nexthop add id 51 encap mpls 101 via 172.16.1.2 dev veth1"
1599         log_test $? 0 "IPv4 route with MPLS encap"
1600         check_nexthop "id 51" "id 51 encap mpls 101 via 172.16.1.2 dev veth1 scope link"
1601         log_test $? 0 "IPv4 route with MPLS encap - check"
1602
1603         run_cmd "$IP nexthop add id 52 encap mpls 102 via inet6 2001:db8:91::2 dev veth1"
1604         log_test $? 0 "IPv4 route with MPLS encap and v6 gateway"
1605         check_nexthop "id 52" "id 52 encap mpls 102 via 2001:db8:91::2 dev veth1 scope link"
1606         log_test $? 0 "IPv4 route with MPLS encap, v6 gw - check"
1607 }
1608
1609 ipv4_large_grp()
1610 {
1611         local ecmp=32
1612
1613         echo
1614         echo "IPv4 large groups (x$ecmp)"
1615         echo "---------------------"
1616
1617         check_large_grp 4 $ecmp
1618
1619         $IP nexthop flush >/dev/null 2>&1
1620 }
1621
1622 ipv4_large_res_grp()
1623 {
1624         echo
1625         echo "IPv4 large resilient group (128k buckets)"
1626         echo "-----------------------------------------"
1627
1628         check_nexthop_res_support
1629         if [ $? -eq $ksft_skip ]; then
1630                 return $ksft_skip
1631         fi
1632
1633         check_large_res_grp 4 $((128 * 1024))
1634
1635         $IP nexthop flush >/dev/null 2>&1
1636 }
1637
1638 sysctl_nexthop_compat_mode_check()
1639 {
1640         local sysctlname="net.ipv4.nexthop_compat_mode"
1641         local lprefix=$1
1642
1643         IPE="ip netns exec me"
1644
1645         $IPE sysctl -q $sysctlname 2>&1 >/dev/null
1646         if [ $? -ne 0 ]; then
1647                 echo "SKIP: kernel lacks nexthop compat mode sysctl control"
1648                 return $ksft_skip
1649         fi
1650
1651         out=$($IPE sysctl $sysctlname 2>/dev/null)
1652         log_test $? 0 "$lprefix default nexthop compat mode check"
1653         check_output "${out}" "$sysctlname = 1"
1654 }
1655
1656 sysctl_nexthop_compat_mode_set()
1657 {
1658         local sysctlname="net.ipv4.nexthop_compat_mode"
1659         local mode=$1
1660         local lprefix=$2
1661
1662         IPE="ip netns exec me"
1663
1664         out=$($IPE sysctl -w $sysctlname=$mode)
1665         log_test $? 0 "$lprefix set compat mode - $mode"
1666         check_output "${out}" "net.ipv4.nexthop_compat_mode = $mode"
1667 }
1668
1669 ipv6_compat_mode()
1670 {
1671         local rc
1672
1673         echo
1674         echo "IPv6 nexthop api compat mode test"
1675         echo "--------------------------------"
1676
1677         sysctl_nexthop_compat_mode_check "IPv6"
1678         if [ $? -eq $ksft_skip ]; then
1679                 return $ksft_skip
1680         fi
1681
1682         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1683         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1684         run_cmd "$IP nexthop add id 122 group 62/63"
1685         ipmout=$(start_ip_monitor route)
1686
1687         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1688         # route add notification should contain expanded nexthops
1689         stop_ip_monitor $ipmout 3
1690         log_test $? 0 "IPv6 compat mode on - route add notification"
1691
1692         # route dump should contain expanded nexthops
1693         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop via 2001:db8:91::3 dev veth1 weight 1"
1694         log_test $? 0 "IPv6 compat mode on - route dump"
1695
1696         # change in nexthop group should generate route notification
1697         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1698         ipmout=$(start_ip_monitor route)
1699         run_cmd "$IP nexthop replace id 122 group 62/64"
1700         stop_ip_monitor $ipmout 3
1701
1702         log_test $? 0 "IPv6 compat mode on - nexthop change"
1703
1704         # set compat mode off
1705         sysctl_nexthop_compat_mode_set 0 "IPv6"
1706
1707         run_cmd "$IP -6 ro del 2001:db8:101::1/128 nhid 122"
1708
1709         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1710         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1711         run_cmd "$IP nexthop add id 122 group 62/63"
1712         ipmout=$(start_ip_monitor route)
1713
1714         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1715         # route add notification should not contain expanded nexthops
1716         stop_ip_monitor $ipmout 1
1717         log_test $? 0 "IPv6 compat mode off - route add notification"
1718
1719         # route dump should not contain expanded nexthops
1720         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024"
1721         log_test $? 0 "IPv6 compat mode off - route dump"
1722
1723         # change in nexthop group should not generate route notification
1724         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1725         ipmout=$(start_ip_monitor route)
1726         run_cmd "$IP nexthop replace id 122 group 62/64"
1727         stop_ip_monitor $ipmout 0
1728         log_test $? 0 "IPv6 compat mode off - nexthop change"
1729
1730         # nexthop delete should not generate route notification
1731         ipmout=$(start_ip_monitor route)
1732         run_cmd "$IP nexthop del id 122"
1733         stop_ip_monitor $ipmout 0
1734         log_test $? 0 "IPv6 compat mode off - nexthop delete"
1735
1736         # set compat mode back on
1737         sysctl_nexthop_compat_mode_set 1 "IPv6"
1738 }
1739
1740 ipv4_compat_mode()
1741 {
1742         local rc
1743
1744         echo
1745         echo "IPv4 nexthop api compat mode"
1746         echo "----------------------------"
1747
1748         sysctl_nexthop_compat_mode_check "IPv4"
1749         if [ $? -eq $ksft_skip ]; then
1750                 return $ksft_skip
1751         fi
1752
1753         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
1754         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
1755         run_cmd "$IP nexthop add id 122 group 21/22"
1756         ipmout=$(start_ip_monitor route)
1757
1758         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1759         stop_ip_monitor $ipmout 3
1760
1761         # route add notification should contain expanded nexthops
1762         log_test $? 0 "IPv4 compat mode on - route add notification"
1763
1764         # route dump should contain expanded nexthops
1765         check_route "172.16.101.1" "172.16.101.1 nhid 122 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1766         log_test $? 0 "IPv4 compat mode on - route dump"
1767
1768         # change in nexthop group should generate route notification
1769         run_cmd "$IP nexthop add id 23 via 172.16.1.3 dev veth1"
1770         ipmout=$(start_ip_monitor route)
1771         run_cmd "$IP nexthop replace id 122 group 21/23"
1772         stop_ip_monitor $ipmout 3
1773         log_test $? 0 "IPv4 compat mode on - nexthop change"
1774
1775         sysctl_nexthop_compat_mode_set 0 "IPv4"
1776
1777         # cleanup
1778         run_cmd "$IP ro del 172.16.101.1/32 nhid 122"
1779
1780         ipmout=$(start_ip_monitor route)
1781         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1782         stop_ip_monitor $ipmout 1
1783         # route add notification should not contain expanded nexthops
1784         log_test $? 0 "IPv4 compat mode off - route add notification"
1785
1786         # route dump should not contain expanded nexthops
1787         check_route "172.16.101.1" "172.16.101.1 nhid 122"
1788         log_test $? 0 "IPv4 compat mode off - route dump"
1789
1790         # change in nexthop group should not generate route notification
1791         ipmout=$(start_ip_monitor route)
1792         run_cmd "$IP nexthop replace id 122 group 21/22"
1793         stop_ip_monitor $ipmout 0
1794         log_test $? 0 "IPv4 compat mode off - nexthop change"
1795
1796         # nexthop delete should not generate route notification
1797         ipmout=$(start_ip_monitor route)
1798         run_cmd "$IP nexthop del id 122"
1799         stop_ip_monitor $ipmout 0
1800         log_test $? 0 "IPv4 compat mode off - nexthop delete"
1801
1802         sysctl_nexthop_compat_mode_set 1 "IPv4"
1803 }
1804
1805 ipv4_del_add_loop1()
1806 {
1807         while :; do
1808                 $IP nexthop del id 100
1809                 $IP nexthop add id 100 via 172.16.1.2 dev veth1
1810         done >/dev/null 2>&1
1811 }
1812
1813 ipv4_grp_replace_loop()
1814 {
1815         while :; do
1816                 $IP nexthop replace id 102 group 100/101
1817         done >/dev/null 2>&1
1818 }
1819
1820 ipv4_torture()
1821 {
1822         local pid1
1823         local pid2
1824         local pid3
1825         local pid4
1826         local pid5
1827
1828         echo
1829         echo "IPv4 runtime torture"
1830         echo "--------------------"
1831         if [ ! -x "$(command -v mausezahn)" ]; then
1832                 echo "SKIP: Could not run test; need mausezahn tool"
1833                 return
1834         fi
1835
1836         run_cmd "$IP nexthop add id 100 via 172.16.1.2 dev veth1"
1837         run_cmd "$IP nexthop add id 101 via 172.16.2.2 dev veth3"
1838         run_cmd "$IP nexthop add id 102 group 100/101"
1839         run_cmd "$IP route add 172.16.101.1 nhid 102"
1840         run_cmd "$IP route add 172.16.101.2 nhid 102"
1841
1842         ipv4_del_add_loop1 &
1843         pid1=$!
1844         ipv4_grp_replace_loop &
1845         pid2=$!
1846         ip netns exec me ping -f 172.16.101.1 >/dev/null 2>&1 &
1847         pid3=$!
1848         ip netns exec me ping -f 172.16.101.2 >/dev/null 2>&1 &
1849         pid4=$!
1850         ip netns exec me mausezahn veth1 -B 172.16.101.2 -A 172.16.1.1 -c 0 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1851         pid5=$!
1852
1853         sleep 300
1854         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1855         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1856
1857         # if we did not crash, success
1858         log_test 0 0 "IPv4 torture test"
1859 }
1860
1861 ipv4_res_grp_replace_loop()
1862 {
1863         while :; do
1864                 $IP nexthop replace id 102 group 100/101 type resilient
1865         done >/dev/null 2>&1
1866 }
1867
1868 ipv4_res_torture()
1869 {
1870         local pid1
1871         local pid2
1872         local pid3
1873         local pid4
1874         local pid5
1875
1876         echo
1877         echo "IPv4 runtime resilient nexthop group torture"
1878         echo "--------------------------------------------"
1879
1880         check_nexthop_res_support
1881         if [ $? -eq $ksft_skip ]; then
1882                 return $ksft_skip
1883         fi
1884
1885         if [ ! -x "$(command -v mausezahn)" ]; then
1886                 echo "SKIP: Could not run test; need mausezahn tool"
1887                 return
1888         fi
1889
1890         run_cmd "$IP nexthop add id 100 via 172.16.1.2 dev veth1"
1891         run_cmd "$IP nexthop add id 101 via 172.16.2.2 dev veth3"
1892         run_cmd "$IP nexthop add id 102 group 100/101 type resilient buckets 512 idle_timer 0"
1893         run_cmd "$IP route add 172.16.101.1 nhid 102"
1894         run_cmd "$IP route add 172.16.101.2 nhid 102"
1895
1896         ipv4_del_add_loop1 &
1897         pid1=$!
1898         ipv4_res_grp_replace_loop &
1899         pid2=$!
1900         ip netns exec me ping -f 172.16.101.1 >/dev/null 2>&1 &
1901         pid3=$!
1902         ip netns exec me ping -f 172.16.101.2 >/dev/null 2>&1 &
1903         pid4=$!
1904         ip netns exec me mausezahn veth1 \
1905                                 -B 172.16.101.2 -A 172.16.1.1 -c 0 \
1906                                 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1907         pid5=$!
1908
1909         sleep 300
1910         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1911         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1912
1913         # if we did not crash, success
1914         log_test 0 0 "IPv4 resilient nexthop group torture test"
1915 }
1916
1917 basic()
1918 {
1919         echo
1920         echo "Basic functional tests"
1921         echo "----------------------"
1922         run_cmd "$IP nexthop ls"
1923         log_test $? 0 "List with nothing defined"
1924
1925         run_cmd "$IP nexthop get id 1"
1926         log_test $? 2 "Nexthop get on non-existent id"
1927
1928         # attempt to create nh without a device or gw - fails
1929         run_cmd "$IP nexthop add id 1"
1930         log_test $? 2 "Nexthop with no device or gateway"
1931
1932         # attempt to create nh with down device - fails
1933         $IP li set veth1 down
1934         run_cmd "$IP nexthop add id 1 dev veth1"
1935         log_test $? 2 "Nexthop with down device"
1936
1937         # create nh with linkdown device - fails
1938         $IP li set veth1 up
1939         ip -netns peer li set veth2 down
1940         run_cmd "$IP nexthop add id 1 dev veth1"
1941         log_test $? 2 "Nexthop with device that is linkdown"
1942         ip -netns peer li set veth2 up
1943
1944         # device only
1945         run_cmd "$IP nexthop add id 1 dev veth1"
1946         log_test $? 0 "Nexthop with device only"
1947
1948         # create nh with duplicate id
1949         run_cmd "$IP nexthop add id 1 dev veth3"
1950         log_test $? 2 "Nexthop with duplicate id"
1951
1952         # blackhole nexthop
1953         run_cmd "$IP nexthop add id 2 blackhole"
1954         log_test $? 0 "Blackhole nexthop"
1955
1956         # blackhole nexthop can not have other specs
1957         run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
1958         log_test $? 2 "Blackhole nexthop with other attributes"
1959
1960         # blackhole nexthop should not be affected by the state of the loopback
1961         # device
1962         run_cmd "$IP link set dev lo down"
1963         check_nexthop "id 2" "id 2 blackhole"
1964         log_test $? 0 "Blackhole nexthop with loopback device down"
1965
1966         run_cmd "$IP link set dev lo up"
1967
1968         #
1969         # groups
1970         #
1971
1972         run_cmd "$IP nexthop add id 101 group 1"
1973         log_test $? 0 "Create group"
1974
1975         run_cmd "$IP nexthop add id 102 group 2"
1976         log_test $? 0 "Create group with blackhole nexthop"
1977
1978         # multipath group can not have a blackhole as 1 path
1979         run_cmd "$IP nexthop add id 103 group 1/2"
1980         log_test $? 2 "Create multipath group where 1 path is a blackhole"
1981
1982         # multipath group can not have a member replaced by a blackhole
1983         run_cmd "$IP nexthop replace id 2 dev veth3"
1984         run_cmd "$IP nexthop replace id 102 group 1/2"
1985         run_cmd "$IP nexthop replace id 2 blackhole"
1986         log_test $? 2 "Multipath group can not have a member replaced by blackhole"
1987
1988         # attempt to create group with non-existent nexthop
1989         run_cmd "$IP nexthop add id 103 group 12"
1990         log_test $? 2 "Create group with non-existent nexthop"
1991
1992         # attempt to create group with same nexthop
1993         run_cmd "$IP nexthop add id 103 group 1/1"
1994         log_test $? 2 "Create group with same nexthop multiple times"
1995
1996         # replace nexthop with a group - fails
1997         run_cmd "$IP nexthop replace id 2 group 1"
1998         log_test $? 2 "Replace nexthop with nexthop group"
1999
2000         # replace nexthop group with a nexthop - fails
2001         run_cmd "$IP nexthop replace id 101 dev veth1"
2002         log_test $? 2 "Replace nexthop group with nexthop"
2003
2004         # nexthop group with other attributes fail
2005         run_cmd "$IP nexthop add id 104 group 1 dev veth1"
2006         log_test $? 2 "Nexthop group and device"
2007
2008         # Tests to ensure that flushing works as expected.
2009         run_cmd "$IP nexthop add id 105 blackhole proto 99"
2010         run_cmd "$IP nexthop add id 106 blackhole proto 100"
2011         run_cmd "$IP nexthop add id 107 blackhole proto 99"
2012         run_cmd "$IP nexthop flush proto 99"
2013         check_nexthop "id 105" ""
2014         check_nexthop "id 106" "id 106 blackhole proto 100"
2015         check_nexthop "id 107" ""
2016         run_cmd "$IP nexthop flush proto 100"
2017         check_nexthop "id 106" ""
2018
2019         run_cmd "$IP nexthop flush proto 100"
2020         log_test $? 0 "Test proto flush"
2021
2022         run_cmd "$IP nexthop add id 104 group 1 blackhole"
2023         log_test $? 2 "Nexthop group and blackhole"
2024
2025         $IP nexthop flush >/dev/null 2>&1
2026
2027         # Test to ensure that flushing with a multi-part nexthop dump works as
2028         # expected.
2029         local batch_file=$(mktemp)
2030
2031         for i in $(seq 1 $((64 * 1024))); do
2032                 echo "nexthop add id $i blackhole" >> $batch_file
2033         done
2034
2035         $IP -b $batch_file
2036         $IP nexthop flush >/dev/null 2>&1
2037         [[ $($IP nexthop | wc -l) -eq 0 ]]
2038         log_test $? 0 "Large scale nexthop flushing"
2039
2040         rm $batch_file
2041 }
2042
2043 check_nexthop_buckets_balance()
2044 {
2045         local nharg=$1; shift
2046         local ret
2047
2048         while (($# > 0)); do
2049                 local selector=$1; shift
2050                 local condition=$1; shift
2051                 local count
2052
2053                 count=$($IP -j nexthop bucket ${nharg} ${selector} | jq length)
2054                 (( $count $condition ))
2055                 ret=$?
2056                 if ((ret != 0)); then
2057                         return $ret
2058                 fi
2059         done
2060
2061         return 0
2062 }
2063
2064 basic_res()
2065 {
2066         echo
2067         echo "Basic resilient nexthop group functional tests"
2068         echo "----------------------------------------------"
2069
2070         check_nexthop_res_support
2071         if [ $? -eq $ksft_skip ]; then
2072                 return $ksft_skip
2073         fi
2074
2075         run_cmd "$IP nexthop add id 1 dev veth1"
2076
2077         #
2078         # resilient nexthop group addition
2079         #
2080
2081         run_cmd "$IP nexthop add id 101 group 1 type resilient buckets 8"
2082         log_test $? 0 "Add a nexthop group with default parameters"
2083
2084         run_cmd "$IP nexthop get id 101"
2085         check_nexthop "id 101" \
2086                 "id 101 group 1 type resilient buckets 8 idle_timer 120 unbalanced_timer 0 unbalanced_time 0"
2087         log_test $? 0 "Get a nexthop group with default parameters"
2088
2089         run_cmd "$IP nexthop add id 102 group 1 type resilient
2090                         buckets 4 idle_timer 100 unbalanced_timer 5"
2091         run_cmd "$IP nexthop get id 102"
2092         check_nexthop "id 102" \
2093                 "id 102 group 1 type resilient buckets 4 idle_timer 100 unbalanced_timer 5 unbalanced_time 0"
2094         log_test $? 0 "Get a nexthop group with non-default parameters"
2095
2096         run_cmd "$IP nexthop add id 103 group 1 type resilient buckets 0"
2097         log_test $? 2 "Add a nexthop group with 0 buckets"
2098
2099         #
2100         # resilient nexthop group replacement
2101         #
2102
2103         run_cmd "$IP nexthop replace id 101 group 1 type resilient
2104                         buckets 8 idle_timer 240 unbalanced_timer 80"
2105         log_test $? 0 "Replace nexthop group parameters"
2106         check_nexthop "id 101" \
2107                 "id 101 group 1 type resilient buckets 8 idle_timer 240 unbalanced_timer 80 unbalanced_time 0"
2108         log_test $? 0 "Get a nexthop group after replacing parameters"
2109
2110         run_cmd "$IP nexthop replace id 101 group 1 type resilient idle_timer 512"
2111         log_test $? 0 "Replace idle timer"
2112         check_nexthop "id 101" \
2113                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 80 unbalanced_time 0"
2114         log_test $? 0 "Get a nexthop group after replacing idle timer"
2115
2116         run_cmd "$IP nexthop replace id 101 group 1 type resilient unbalanced_timer 256"
2117         log_test $? 0 "Replace unbalanced timer"
2118         check_nexthop "id 101" \
2119                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2120         log_test $? 0 "Get a nexthop group after replacing unbalanced timer"
2121
2122         run_cmd "$IP nexthop replace id 101 group 1 type resilient"
2123         log_test $? 0 "Replace with no parameters"
2124         check_nexthop "id 101" \
2125                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2126         log_test $? 0 "Get a nexthop group after replacing no parameters"
2127
2128         run_cmd "$IP nexthop replace id 101 group 1"
2129         log_test $? 2 "Replace nexthop group type - implicit"
2130
2131         run_cmd "$IP nexthop replace id 101 group 1 type mpath"
2132         log_test $? 2 "Replace nexthop group type - explicit"
2133
2134         run_cmd "$IP nexthop replace id 101 group 1 type resilient buckets 1024"
2135         log_test $? 2 "Replace number of nexthop buckets"
2136
2137         check_nexthop "id 101" \
2138                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2139         log_test $? 0 "Get a nexthop group after replacing with invalid parameters"
2140
2141         #
2142         # resilient nexthop buckets dump
2143         #
2144
2145         $IP nexthop flush >/dev/null 2>&1
2146         run_cmd "$IP nexthop add id 1 dev veth1"
2147         run_cmd "$IP nexthop add id 2 dev veth3"
2148         run_cmd "$IP nexthop add id 101 group 1/2 type resilient buckets 4"
2149         run_cmd "$IP nexthop add id 201 group 1/2"
2150
2151         check_nexthop_bucket "" \
2152                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2153         log_test $? 0 "Dump all nexthop buckets"
2154
2155         check_nexthop_bucket "list id 101" \
2156                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2157         log_test $? 0 "Dump all nexthop buckets in a group"
2158
2159         sleep 0.1
2160         (( $($IP -j nexthop bucket list id 101 |
2161              jq '[.[] | select(.bucket.idle_time > 0 and
2162                                .bucket.idle_time < 2)] | length') == 4 ))
2163         log_test $? 0 "All nexthop buckets report a positive near-zero idle time"
2164
2165         check_nexthop_bucket "list dev veth1" \
2166                 "id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2167         log_test $? 0 "Dump all nexthop buckets with a specific nexthop device"
2168
2169         check_nexthop_bucket "list nhid 2" \
2170                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2"
2171         log_test $? 0 "Dump all nexthop buckets with a specific nexthop identifier"
2172
2173         run_cmd "$IP nexthop bucket list id 111"
2174         log_test $? 2 "Dump all nexthop buckets in a non-existent group"
2175
2176         run_cmd "$IP nexthop bucket list id 201"
2177         log_test $? 2 "Dump all nexthop buckets in a non-resilient group"
2178
2179         run_cmd "$IP nexthop bucket list dev bla"
2180         log_test $? 255 "Dump all nexthop buckets using a non-existent device"
2181
2182         run_cmd "$IP nexthop bucket list groups"
2183         log_test $? 255 "Dump all nexthop buckets with invalid 'groups' keyword"
2184
2185         run_cmd "$IP nexthop bucket list fdb"
2186         log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword"
2187
2188         #
2189         # resilient nexthop buckets get requests
2190         #
2191
2192         check_nexthop_bucket "get id 101 index 0" "id 101 index 0 nhid 2"
2193         log_test $? 0 "Get a valid nexthop bucket"
2194
2195         run_cmd "$IP nexthop bucket get id 101 index 999"
2196         log_test $? 2 "Get a nexthop bucket with valid group, but invalid index"
2197
2198         run_cmd "$IP nexthop bucket get id 201 index 0"
2199         log_test $? 2 "Get a nexthop bucket from a non-resilient group"
2200
2201         run_cmd "$IP nexthop bucket get id 999 index 0"
2202         log_test $? 2 "Get a nexthop bucket from a non-existent group"
2203
2204         #
2205         # tests for bucket migration
2206         #
2207
2208         $IP nexthop flush >/dev/null 2>&1
2209
2210         run_cmd "$IP nexthop add id 1 dev veth1"
2211         run_cmd "$IP nexthop add id 2 dev veth3"
2212         run_cmd "$IP nexthop add id 101
2213                         group 1/2 type resilient buckets 10
2214                         idle_timer 1 unbalanced_timer 20"
2215
2216         check_nexthop_buckets_balance "list id 101" \
2217                                       "nhid 1" "== 5" \
2218                                       "nhid 2" "== 5"
2219         log_test $? 0 "Initial bucket allocation"
2220
2221         run_cmd "$IP nexthop replace id 101
2222                         group 1,2/2,3 type resilient"
2223         check_nexthop_buckets_balance "list id 101" \
2224                                       "nhid 1" "== 4" \
2225                                       "nhid 2" "== 6"
2226         log_test $? 0 "Bucket allocation after replace"
2227
2228         # Check that increase in idle timer does not make buckets appear busy.
2229         run_cmd "$IP nexthop replace id 101
2230                         group 1,2/2,3 type resilient
2231                         idle_timer 10"
2232         run_cmd "$IP nexthop replace id 101
2233                         group 1/2 type resilient"
2234         check_nexthop_buckets_balance "list id 101" \
2235                                       "nhid 1" "== 5" \
2236                                       "nhid 2" "== 5"
2237         log_test $? 0 "Buckets migrated after idle timer change"
2238
2239         $IP nexthop flush >/dev/null 2>&1
2240 }
2241
2242 ################################################################################
2243 # usage
2244
2245 usage()
2246 {
2247         cat <<EOF
2248 usage: ${0##*/} OPTS
2249
2250         -t <test>   Test(s) to run (default: all)
2251                     (options: $ALL_TESTS)
2252         -4          IPv4 tests only
2253         -6          IPv6 tests only
2254         -p          Pause on fail
2255         -P          Pause after each test before cleanup
2256         -v          verbose mode (show commands and output)
2257         -w          Timeout for ping
2258
2259     Runtime test
2260         -n num      Number of nexthops to target
2261         -N          Use new style to install routes in DUT
2262
2263 done
2264 EOF
2265 }
2266
2267 ################################################################################
2268 # main
2269
2270 while getopts :t:pP46hv:w: o
2271 do
2272         case $o in
2273                 t) TESTS=$OPTARG;;
2274                 4) TESTS=${IPV4_TESTS};;
2275                 6) TESTS=${IPV6_TESTS};;
2276                 p) PAUSE_ON_FAIL=yes;;
2277                 P) PAUSE=yes;;
2278                 v) VERBOSE=$(($VERBOSE + 1));;
2279                 w) PING_TIMEOUT=$OPTARG;;
2280                 h) usage; exit 0;;
2281                 *) usage; exit 1;;
2282         esac
2283 done
2284
2285 # make sure we don't pause twice
2286 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2287
2288 if [ "$(id -u)" -ne 0 ];then
2289         echo "SKIP: Need root privileges"
2290         exit $ksft_skip;
2291 fi
2292
2293 if [ ! -x "$(command -v ip)" ]; then
2294         echo "SKIP: Could not run test without ip tool"
2295         exit $ksft_skip
2296 fi
2297
2298 ip help 2>&1 | grep -q nexthop
2299 if [ $? -ne 0 ]; then
2300         echo "SKIP: iproute2 too old, missing nexthop command"
2301         exit $ksft_skip
2302 fi
2303
2304 out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
2305 if [ $? -eq 0 ]; then
2306         echo "SKIP: kernel lacks nexthop support"
2307         exit $ksft_skip
2308 fi
2309
2310 for t in $TESTS
2311 do
2312         case $t in
2313         none) IP="ip -netns peer"; setup; exit 0;;
2314         *) setup; $t; cleanup;;
2315         esac
2316 done
2317
2318 if [ "$TESTS" != "none" ]; then
2319         printf "\nTests passed: %3d\n" ${nsuccess}
2320         printf "Tests failed: %3d\n"   ${nfail}
2321 fi
2322
2323 exit $ret