~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/net/fib_tests.sh

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/bin/bash
  2 # SPDX-License-Identifier: GPL-2.0
  3 
  4 # This test is for checking IPv4 and IPv6 FIB behavior in response to
  5 # different events.
  6 source lib.sh
  7 ret=0
  8 
  9 # all tests in this script. Can be overridden with -t option
 10 TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
 11        ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics \
 12        ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
 13        ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \
 14        ipv4_mpath_list ipv6_mpath_list"
 15 
 16 VERBOSE=0
 17 PAUSE_ON_FAIL=no
 18 PAUSE=no
 19 
 20 which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
 21 
 22 log_test()
 23 {
 24         local rc=$1
 25         local expected=$2
 26         local msg="$3"
 27 
 28         if [ ${rc} -eq ${expected} ]; then
 29                 printf "    TEST: %-60s  [ OK ]\n" "${msg}"
 30                 nsuccess=$((nsuccess+1))
 31         else
 32                 ret=1
 33                 nfail=$((nfail+1))
 34                 printf "    TEST: %-60s  [FAIL]\n" "${msg}"
 35                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
 36                 echo
 37                         echo "hit enter to continue, 'q' to quit"
 38                         read a
 39                         [ "$a" = "q" ] && exit 1
 40                 fi
 41         fi
 42 
 43         if [ "${PAUSE}" = "yes" ]; then
 44                 echo
 45                 echo "hit enter to continue, 'q' to quit"
 46                 read a
 47                 [ "$a" = "q" ] && exit 1
 48         fi
 49 }
 50 
 51 setup()
 52 {
 53         set -e
 54         setup_ns ns1
 55         IP="$(which ip) -netns $ns1"
 56         NS_EXEC="$(which ip) netns exec $ns1"
 57         ip netns exec $ns1 sysctl -qw net.ipv4.ip_forward=1
 58         ip netns exec $ns1 sysctl -qw net.ipv6.conf.all.forwarding=1
 59 
 60         $IP link add dummy0 type dummy
 61         $IP link set dev dummy0 up
 62         $IP address add 198.51.100.1/24 dev dummy0
 63         $IP -6 address add 2001:db8:1::1/64 dev dummy0
 64         set +e
 65 
 66 }
 67 
 68 cleanup()
 69 {
 70         $IP link del dev dummy0 &> /dev/null
 71         cleanup_ns $ns1 $ns2
 72 }
 73 
 74 get_linklocal()
 75 {
 76         local dev=$1
 77         local addr
 78 
 79         addr=$($IP -6 -br addr show dev ${dev} | \
 80         awk '{
 81                 for (i = 3; i <= NF; ++i) {
 82                         if ($i ~ /^fe80/)
 83                                 print $i
 84                 }
 85         }'
 86         )
 87         addr=${addr/\/*}
 88 
 89         [ -z "$addr" ] && return 1
 90 
 91         echo $addr
 92 
 93         return 0
 94 }
 95 
 96 fib_unreg_unicast_test()
 97 {
 98         echo
 99         echo "Single path route test"
100 
101         setup
102 
103         echo "    Start point"
104         $IP route get fibmatch 198.51.100.2 &> /dev/null
105         log_test $? 0 "IPv4 fibmatch"
106         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
107         log_test $? 0 "IPv6 fibmatch"
108 
109         set -e
110         $IP link del dev dummy0
111         set +e
112 
113         echo "    Nexthop device deleted"
114         $IP route get fibmatch 198.51.100.2 &> /dev/null
115         log_test $? 2 "IPv4 fibmatch - no route"
116         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
117         log_test $? 2 "IPv6 fibmatch - no route"
118 
119         cleanup
120 }
121 
122 fib_unreg_multipath_test()
123 {
124 
125         echo
126         echo "Multipath route test"
127 
128         setup
129 
130         set -e
131         $IP link add dummy1 type dummy
132         $IP link set dev dummy1 up
133         $IP address add 192.0.2.1/24 dev dummy1
134         $IP -6 address add 2001:db8:2::1/64 dev dummy1
135 
136         $IP route add 203.0.113.0/24 \
137                 nexthop via 198.51.100.2 dev dummy0 \
138                 nexthop via 192.0.2.2 dev dummy1
139         $IP -6 route add 2001:db8:3::/64 \
140                 nexthop via 2001:db8:1::2 dev dummy0 \
141                 nexthop via 2001:db8:2::2 dev dummy1
142         set +e
143 
144         echo "    Start point"
145         $IP route get fibmatch 203.0.113.1 &> /dev/null
146         log_test $? 0 "IPv4 fibmatch"
147         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
148         log_test $? 0 "IPv6 fibmatch"
149 
150         set -e
151         $IP link del dev dummy0
152         set +e
153 
154         echo "    One nexthop device deleted"
155         $IP route get fibmatch 203.0.113.1 &> /dev/null
156         log_test $? 2 "IPv4 - multipath route removed on delete"
157 
158         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
159         # In IPv6 we do not flush the entire multipath route.
160         log_test $? 0 "IPv6 - multipath down to single path"
161 
162         set -e
163         $IP link del dev dummy1
164         set +e
165 
166         echo "    Second nexthop device deleted"
167         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
168         log_test $? 2 "IPv6 - no route"
169 
170         cleanup
171 }
172 
173 fib_unreg_test()
174 {
175         fib_unreg_unicast_test
176         fib_unreg_multipath_test
177 }
178 
179 fib_down_unicast_test()
180 {
181         echo
182         echo "Single path, admin down"
183 
184         setup
185 
186         echo "    Start point"
187         $IP route get fibmatch 198.51.100.2 &> /dev/null
188         log_test $? 0 "IPv4 fibmatch"
189         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
190         log_test $? 0 "IPv6 fibmatch"
191 
192         set -e
193         $IP link set dev dummy0 down
194         set +e
195 
196         echo "    Route deleted on down"
197         $IP route get fibmatch 198.51.100.2 &> /dev/null
198         log_test $? 2 "IPv4 fibmatch"
199         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
200         log_test $? 2 "IPv6 fibmatch"
201 
202         cleanup
203 }
204 
205 fib_down_multipath_test_do()
206 {
207         local down_dev=$1
208         local up_dev=$2
209 
210         $IP route get fibmatch 203.0.113.1 \
211                 oif $down_dev &> /dev/null
212         log_test $? 2 "IPv4 fibmatch on down device"
213         $IP -6 route get fibmatch 2001:db8:3::1 \
214                 oif $down_dev &> /dev/null
215         log_test $? 2 "IPv6 fibmatch on down device"
216 
217         $IP route get fibmatch 203.0.113.1 \
218                 oif $up_dev &> /dev/null
219         log_test $? 0 "IPv4 fibmatch on up device"
220         $IP -6 route get fibmatch 2001:db8:3::1 \
221                 oif $up_dev &> /dev/null
222         log_test $? 0 "IPv6 fibmatch on up device"
223 
224         $IP route get fibmatch 203.0.113.1 | \
225                 grep $down_dev | grep -q "dead linkdown"
226         log_test $? 0 "IPv4 flags on down device"
227         $IP -6 route get fibmatch 2001:db8:3::1 | \
228                 grep $down_dev | grep -q "dead linkdown"
229         log_test $? 0 "IPv6 flags on down device"
230 
231         $IP route get fibmatch 203.0.113.1 | \
232                 grep $up_dev | grep -q "dead linkdown"
233         log_test $? 1 "IPv4 flags on up device"
234         $IP -6 route get fibmatch 2001:db8:3::1 | \
235                 grep $up_dev | grep -q "dead linkdown"
236         log_test $? 1 "IPv6 flags on up device"
237 }
238 
239 fib_down_multipath_test()
240 {
241         echo
242         echo "Admin down multipath"
243 
244         setup
245 
246         set -e
247         $IP link add dummy1 type dummy
248         $IP link set dev dummy1 up
249 
250         $IP address add 192.0.2.1/24 dev dummy1
251         $IP -6 address add 2001:db8:2::1/64 dev dummy1
252 
253         $IP route add 203.0.113.0/24 \
254                 nexthop via 198.51.100.2 dev dummy0 \
255                 nexthop via 192.0.2.2 dev dummy1
256         $IP -6 route add 2001:db8:3::/64 \
257                 nexthop via 2001:db8:1::2 dev dummy0 \
258                 nexthop via 2001:db8:2::2 dev dummy1
259         set +e
260 
261         echo "    Verify start point"
262         $IP route get fibmatch 203.0.113.1 &> /dev/null
263         log_test $? 0 "IPv4 fibmatch"
264 
265         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
266         log_test $? 0 "IPv6 fibmatch"
267 
268         set -e
269         $IP link set dev dummy0 down
270         set +e
271 
272         echo "    One device down, one up"
273         fib_down_multipath_test_do "dummy0" "dummy1"
274 
275         set -e
276         $IP link set dev dummy0 up
277         $IP link set dev dummy1 down
278         set +e
279 
280         echo "    Other device down and up"
281         fib_down_multipath_test_do "dummy1" "dummy0"
282 
283         set -e
284         $IP link set dev dummy0 down
285         set +e
286 
287         echo "    Both devices down"
288         $IP route get fibmatch 203.0.113.1 &> /dev/null
289         log_test $? 2 "IPv4 fibmatch"
290         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
291         log_test $? 2 "IPv6 fibmatch"
292 
293         $IP link del dev dummy1
294         cleanup
295 }
296 
297 fib_down_test()
298 {
299         fib_down_unicast_test
300         fib_down_multipath_test
301 }
302 
303 # Local routes should not be affected when carrier changes.
304 fib_carrier_local_test()
305 {
306         echo
307         echo "Local carrier tests - single path"
308 
309         setup
310 
311         set -e
312         $IP link set dev dummy0 carrier on
313         set +e
314 
315         echo "    Start point"
316         $IP route get fibmatch 198.51.100.1 &> /dev/null
317         log_test $? 0 "IPv4 fibmatch"
318         $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
319         log_test $? 0 "IPv6 fibmatch"
320 
321         $IP route get fibmatch 198.51.100.1 | \
322                 grep -q "linkdown"
323         log_test $? 1 "IPv4 - no linkdown flag"
324         $IP -6 route get fibmatch 2001:db8:1::1 | \
325                 grep -q "linkdown"
326         log_test $? 1 "IPv6 - no linkdown flag"
327 
328         set -e
329         $IP link set dev dummy0 carrier off
330         sleep 1
331         set +e
332 
333         echo "    Carrier off on nexthop"
334         $IP route get fibmatch 198.51.100.1 &> /dev/null
335         log_test $? 0 "IPv4 fibmatch"
336         $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
337         log_test $? 0 "IPv6 fibmatch"
338 
339         $IP route get fibmatch 198.51.100.1 | \
340                 grep -q "linkdown"
341         log_test $? 1 "IPv4 - linkdown flag set"
342         $IP -6 route get fibmatch 2001:db8:1::1 | \
343                 grep -q "linkdown"
344         log_test $? 1 "IPv6 - linkdown flag set"
345 
346         set -e
347         $IP address add 192.0.2.1/24 dev dummy0
348         $IP -6 address add 2001:db8:2::1/64 dev dummy0
349         set +e
350 
351         echo "    Route to local address with carrier down"
352         $IP route get fibmatch 192.0.2.1 &> /dev/null
353         log_test $? 0 "IPv4 fibmatch"
354         $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
355         log_test $? 0 "IPv6 fibmatch"
356 
357         $IP route get fibmatch 192.0.2.1 | \
358                 grep -q "linkdown"
359         log_test $? 1 "IPv4 linkdown flag set"
360         $IP -6 route get fibmatch 2001:db8:2::1 | \
361                 grep -q "linkdown"
362         log_test $? 1 "IPv6 linkdown flag set"
363 
364         cleanup
365 }
366 
367 fib_carrier_unicast_test()
368 {
369         ret=0
370 
371         echo
372         echo "Single path route carrier test"
373 
374         setup
375 
376         set -e
377         $IP link set dev dummy0 carrier on
378         set +e
379 
380         echo "    Start point"
381         $IP route get fibmatch 198.51.100.2 &> /dev/null
382         log_test $? 0 "IPv4 fibmatch"
383         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
384         log_test $? 0 "IPv6 fibmatch"
385 
386         $IP route get fibmatch 198.51.100.2 | \
387                 grep -q "linkdown"
388         log_test $? 1 "IPv4 no linkdown flag"
389         $IP -6 route get fibmatch 2001:db8:1::2 | \
390                 grep -q "linkdown"
391         log_test $? 1 "IPv6 no linkdown flag"
392 
393         set -e
394         $IP link set dev dummy0 carrier off
395         sleep 1
396         set +e
397 
398         echo "    Carrier down"
399         $IP route get fibmatch 198.51.100.2 &> /dev/null
400         log_test $? 0 "IPv4 fibmatch"
401         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
402         log_test $? 0 "IPv6 fibmatch"
403 
404         $IP route get fibmatch 198.51.100.2 | \
405                 grep -q "linkdown"
406         log_test $? 0 "IPv4 linkdown flag set"
407         $IP -6 route get fibmatch 2001:db8:1::2 | \
408                 grep -q "linkdown"
409         log_test $? 0 "IPv6 linkdown flag set"
410 
411         set -e
412         $IP address add 192.0.2.1/24 dev dummy0
413         $IP -6 address add 2001:db8:2::1/64 dev dummy0
414         set +e
415 
416         echo "    Second address added with carrier down"
417         $IP route get fibmatch 192.0.2.2 &> /dev/null
418         log_test $? 0 "IPv4 fibmatch"
419         $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
420         log_test $? 0 "IPv6 fibmatch"
421 
422         $IP route get fibmatch 192.0.2.2 | \
423                 grep -q "linkdown"
424         log_test $? 0 "IPv4 linkdown flag set"
425         $IP -6 route get fibmatch 2001:db8:2::2 | \
426                 grep -q "linkdown"
427         log_test $? 0 "IPv6 linkdown flag set"
428 
429         cleanup
430 }
431 
432 fib_carrier_test()
433 {
434         fib_carrier_local_test
435         fib_carrier_unicast_test
436 }
437 
438 fib_rp_filter_test()
439 {
440         echo
441         echo "IPv4 rp_filter tests"
442 
443         setup
444 
445         set -e
446         setup_ns ns2
447 
448         $IP link add name veth1 type veth peer name veth2
449         $IP link set dev veth2 netns $ns2
450         $IP address add 192.0.2.1/24 dev veth1
451         ip -netns $ns2 address add 192.0.2.1/24 dev veth2
452         $IP link set dev veth1 up
453         ip -netns $ns2 link set dev veth2 up
454 
455         $IP link set dev lo address 52:54:00:6a:c7:5e
456         $IP link set dev veth1 address 52:54:00:6a:c7:5e
457         ip -netns $ns2 link set dev lo address 52:54:00:6a:c7:5e
458         ip -netns $ns2 link set dev veth2 address 52:54:00:6a:c7:5e
459 
460         # 1. (ns2) redirect lo's egress to veth2's egress
461         ip netns exec $ns2 tc qdisc add dev lo parent root handle 1: fq_codel
462         ip netns exec $ns2 tc filter add dev lo parent 1: protocol arp basic \
463                 action mirred egress redirect dev veth2
464         ip netns exec $ns2 tc filter add dev lo parent 1: protocol ip basic \
465                 action mirred egress redirect dev veth2
466 
467         # 2. (ns1) redirect veth1's ingress to lo's ingress
468         $NS_EXEC tc qdisc add dev veth1 ingress
469         $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \
470                 action mirred ingress redirect dev lo
471         $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \
472                 action mirred ingress redirect dev lo
473 
474         # 3. (ns1) redirect lo's egress to veth1's egress
475         $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel
476         $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \
477                 action mirred egress redirect dev veth1
478         $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \
479                 action mirred egress redirect dev veth1
480 
481         # 4. (ns2) redirect veth2's ingress to lo's ingress
482         ip netns exec $ns2 tc qdisc add dev veth2 ingress
483         ip netns exec $ns2 tc filter add dev veth2 ingress protocol arp basic \
484                 action mirred ingress redirect dev lo
485         ip netns exec $ns2 tc filter add dev veth2 ingress protocol ip basic \
486                 action mirred ingress redirect dev lo
487 
488         $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1
489         $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1
490         $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1
491         ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1
492         ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.accept_local=1
493         ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1
494         set +e
495 
496         run_cmd "ip netns exec $ns2 ping -w1 -c1 192.0.2.1"
497         log_test $? 0 "rp_filter passes local packets"
498 
499         run_cmd "ip netns exec $ns2 ping -w1 -c1 127.0.0.1"
500         log_test $? 0 "rp_filter passes loopback packets"
501 
502         cleanup
503 }
504 
505 ################################################################################
506 # Tests on nexthop spec
507 
508 # run 'ip route add' with given spec
509 add_rt()
510 {
511         local desc="$1"
512         local erc=$2
513         local vrf=$3
514         local pfx=$4
515         local gw=$5
516         local dev=$6
517         local cmd out rc
518 
519         [ "$vrf" = "-" ] && vrf="default"
520         [ -n "$gw" ] && gw="via $gw"
521         [ -n "$dev" ] && dev="dev $dev"
522 
523         cmd="$IP route add vrf $vrf $pfx $gw $dev"
524         if [ "$VERBOSE" = "1" ]; then
525                 printf "\n    COMMAND: $cmd\n"
526         fi
527 
528         out=$(eval $cmd 2>&1)
529         rc=$?
530         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
531                 echo "    $out"
532         fi
533         log_test $rc $erc "$desc"
534 }
535 
536 fib4_nexthop()
537 {
538         echo
539         echo "IPv4 nexthop tests"
540 
541         echo "<<< write me >>>"
542 }
543 
544 fib6_nexthop()
545 {
546         local lldummy=$(get_linklocal dummy0)
547         local llv1=$(get_linklocal dummy0)
548 
549         if [ -z "$lldummy" ]; then
550                 echo "Failed to get linklocal address for dummy0"
551                 return 1
552         fi
553         if [ -z "$llv1" ]; then
554                 echo "Failed to get linklocal address for veth1"
555                 return 1
556         fi
557 
558         echo
559         echo "IPv6 nexthop tests"
560 
561         add_rt "Directly connected nexthop, unicast address" 0 \
562                 - 2001:db8:101::/64 2001:db8:1::2
563         add_rt "Directly connected nexthop, unicast address with device" 0 \
564                 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
565         add_rt "Gateway is linklocal address" 0 \
566                 - 2001:db8:103::1/64 $llv1 "veth0"
567 
568         # fails because LL address requires a device
569         add_rt "Gateway is linklocal address, no device" 2 \
570                 - 2001:db8:104::1/64 $llv1
571 
572         # local address can not be a gateway
573         add_rt "Gateway can not be local unicast address" 2 \
574                 - 2001:db8:105::/64 2001:db8:1::1
575         add_rt "Gateway can not be local unicast address, with device" 2 \
576                 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
577         add_rt "Gateway can not be a local linklocal address" 2 \
578                 - 2001:db8:107::1/64 $lldummy "dummy0"
579 
580         # VRF tests
581         add_rt "Gateway can be local address in a VRF" 0 \
582                 - 2001:db8:108::/64 2001:db8:51::2
583         add_rt "Gateway can be local address in a VRF, with device" 0 \
584                 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
585         add_rt "Gateway can be local linklocal address in a VRF" 0 \
586                 - 2001:db8:110::1/64 $llv1 "veth0"
587 
588         add_rt "Redirect to VRF lookup" 0 \
589                 - 2001:db8:111::/64 "" "red"
590 
591         add_rt "VRF route, gateway can be local address in default VRF" 0 \
592                 red 2001:db8:112::/64 2001:db8:51::1
593 
594         # local address in same VRF fails
595         add_rt "VRF route, gateway can not be a local address" 2 \
596                 red 2001:db8:113::1/64 2001:db8:2::1
597         add_rt "VRF route, gateway can not be a local addr with device" 2 \
598                 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
599 }
600 
601 # Default VRF:
602 #   dummy0 - 198.51.100.1/24 2001:db8:1::1/64
603 #   veth0  - 192.0.2.1/24    2001:db8:51::1/64
604 #
605 # VRF red:
606 #   dummy1 - 192.168.2.1/24 2001:db8:2::1/64
607 #   veth1  - 192.0.2.2/24   2001:db8:51::2/64
608 #
609 #  [ dummy0   veth0 ]--[ veth1   dummy1 ]
610 
611 fib_nexthop_test()
612 {
613         setup
614 
615         set -e
616 
617         $IP -4 rule add pref 32765 table local
618         $IP -4 rule del pref 0
619         $IP -6 rule add pref 32765 table local
620         $IP -6 rule del pref 0
621 
622         $IP link add red type vrf table 1
623         $IP link set red up
624         $IP -4 route add vrf red unreachable default metric 4278198272
625         $IP -6 route add vrf red unreachable default metric 4278198272
626 
627         $IP link add veth0 type veth peer name veth1
628         $IP link set dev veth0 up
629         $IP address add 192.0.2.1/24 dev veth0
630         $IP -6 address add 2001:db8:51::1/64 dev veth0
631 
632         $IP link set dev veth1 vrf red up
633         $IP address add 192.0.2.2/24 dev veth1
634         $IP -6 address add 2001:db8:51::2/64 dev veth1
635 
636         $IP link add dummy1 type dummy
637         $IP link set dev dummy1 vrf red up
638         $IP address add 192.168.2.1/24 dev dummy1
639         $IP -6 address add 2001:db8:2::1/64 dev dummy1
640         set +e
641 
642         sleep 1
643         fib4_nexthop
644         fib6_nexthop
645 
646         (
647         $IP link del dev dummy1
648         $IP link del veth0
649         $IP link del red
650         ) 2>/dev/null
651         cleanup
652 }
653 
654 fib6_notify_test()
655 {
656         setup
657 
658         echo
659         echo "Fib6 info length calculation in route notify test"
660         set -e
661 
662         for i in 10 20 30 40 50 60 70;
663         do
664                 $IP link add dummy_$i type dummy
665                 $IP link set dev dummy_$i up
666                 $IP -6 address add 2001:$i::1/64 dev dummy_$i
667         done
668 
669         $NS_EXEC ip monitor route &> errors.txt &
670         sleep 2
671 
672         $IP -6 route add 2001::/64 \
673                 nexthop via 2001:10::2 dev dummy_10 \
674                 nexthop encap ip6 dst 2002::20 via 2001:20::2 dev dummy_20 \
675                 nexthop encap ip6 dst 2002::30 via 2001:30::2 dev dummy_30 \
676                 nexthop encap ip6 dst 2002::40 via 2001:40::2 dev dummy_40 \
677                 nexthop encap ip6 dst 2002::50 via 2001:50::2 dev dummy_50 \
678                 nexthop encap ip6 dst 2002::60 via 2001:60::2 dev dummy_60 \
679                 nexthop encap ip6 dst 2002::70 via 2001:70::2 dev dummy_70
680 
681         set +e
682 
683         err=`cat errors.txt |grep "Message too long"`
684         if [ -z "$err" ];then
685                 ret=0
686         else
687                 ret=1
688         fi
689 
690         log_test $ret 0 "ipv6 route add notify"
691 
692         { kill %% && wait %%; } 2>/dev/null
693 
694         #rm errors.txt
695 
696         cleanup &> /dev/null
697 }
698 
699 
700 fib_notify_test()
701 {
702         setup
703 
704         echo
705         echo "Fib4 info length calculation in route notify test"
706 
707         set -e
708 
709         for i in 10 20 30 40 50 60 70;
710         do
711                 $IP link add dummy_$i type dummy
712                 $IP link set dev dummy_$i up
713                 $IP address add 20.20.$i.2/24 dev dummy_$i
714         done
715 
716         $NS_EXEC ip monitor route &> errors.txt &
717         sleep 2
718 
719         $IP route add 10.0.0.0/24 \
720                 nexthop via 20.20.10.1 dev dummy_10 \
721                 nexthop encap ip dst 192.168.10.20 via 20.20.20.1 dev dummy_20 \
722                 nexthop encap ip dst 192.168.10.30 via 20.20.30.1 dev dummy_30 \
723                 nexthop encap ip dst 192.168.10.40 via 20.20.40.1 dev dummy_40 \
724                 nexthop encap ip dst 192.168.10.50 via 20.20.50.1 dev dummy_50 \
725                 nexthop encap ip dst 192.168.10.60 via 20.20.60.1 dev dummy_60 \
726                 nexthop encap ip dst 192.168.10.70 via 20.20.70.1 dev dummy_70
727 
728         set +e
729 
730         err=`cat errors.txt |grep "Message too long"`
731         if [ -z "$err" ];then
732                 ret=0
733         else
734                 ret=1
735         fi
736 
737         log_test $ret 0 "ipv4 route add notify"
738 
739         { kill %% && wait %%; } 2>/dev/null
740 
741         rm  errors.txt
742 
743         cleanup &> /dev/null
744 }
745 
746 # Create a new dummy_10 to remove all associated routes.
747 reset_dummy_10()
748 {
749         $IP link del dev dummy_10
750 
751         $IP link add dummy_10 type dummy
752         $IP link set dev dummy_10 up
753         $IP -6 address add 2001:10::1/64 dev dummy_10
754 }
755 
756 check_rt_num()
757 {
758     local expected=$1
759     local num=$2
760 
761     if [ $num -ne $expected ]; then
762         echo "FAIL: Expected $expected routes, got $num"
763         ret=1
764     else
765         ret=0
766     fi
767 }
768 
769 check_rt_num_clean()
770 {
771     local expected=$1
772     local num=$2
773 
774     if [ $num -ne $expected ]; then
775         log_test 1 0 "expected $expected routes, got $num"
776         set +e
777         cleanup &> /dev/null
778         return 1
779     fi
780     return 0
781 }
782 
783 fib6_gc_test()
784 {
785         setup
786 
787         echo
788         echo "Fib6 garbage collection test"
789         set -e
790 
791         EXPIRE=5
792         GC_WAIT_TIME=$((EXPIRE * 2 + 2))
793 
794         # Check expiration of routes every $EXPIRE seconds (GC)
795         $NS_EXEC sysctl -wq net.ipv6.route.gc_interval=$EXPIRE
796 
797         $IP link add dummy_10 type dummy
798         $IP link set dev dummy_10 up
799         $IP -6 address add 2001:10::1/64 dev dummy_10
800 
801         $NS_EXEC sysctl -wq net.ipv6.route.flush=1
802 
803         # Temporary routes
804         for i in $(seq 1 5); do
805             # Expire route after $EXPIRE seconds
806             $IP -6 route add 2001:20::$i \
807                 via 2001:10::2 dev dummy_10 expires $EXPIRE
808         done
809         sleep $GC_WAIT_TIME
810         $NS_EXEC sysctl -wq net.ipv6.route.flush=1
811         check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
812         log_test $ret 0 "ipv6 route garbage collection"
813 
814         reset_dummy_10
815 
816         # Permanent routes
817         for i in $(seq 1 5); do
818             $IP -6 route add 2001:30::$i \
819                 via 2001:10::2 dev dummy_10
820         done
821         # Temporary routes
822         for i in $(seq 1 5); do
823             # Expire route after $EXPIRE seconds
824             $IP -6 route add 2001:20::$i \
825                 via 2001:10::2 dev dummy_10 expires $EXPIRE
826         done
827         # Wait for GC
828         sleep $GC_WAIT_TIME
829         check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
830         log_test $ret 0 "ipv6 route garbage collection (with permanent routes)"
831 
832         reset_dummy_10
833 
834         # Permanent routes
835         for i in $(seq 1 5); do
836             $IP -6 route add 2001:20::$i \
837                 via 2001:10::2 dev dummy_10
838         done
839         # Replace with temporary routes
840         for i in $(seq 1 5); do
841             # Expire route after $EXPIRE seconds
842             $IP -6 route replace 2001:20::$i \
843                 via 2001:10::2 dev dummy_10 expires $EXPIRE
844         done
845         # Wait for GC
846         sleep $GC_WAIT_TIME
847         check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
848         log_test $ret 0 "ipv6 route garbage collection (replace with expires)"
849 
850         reset_dummy_10
851 
852         # Temporary routes
853         for i in $(seq 1 5); do
854             # Expire route after $EXPIRE seconds
855             $IP -6 route add 2001:20::$i \
856                 via 2001:10::2 dev dummy_10 expires $EXPIRE
857         done
858         # Replace with permanent routes
859         for i in $(seq 1 5); do
860             $IP -6 route replace 2001:20::$i \
861                 via 2001:10::2 dev dummy_10
862         done
863         check_rt_num_clean 0 $($IP -6 route list |grep expires|wc -l) || return
864 
865         # Wait for GC
866         sleep $GC_WAIT_TIME
867         check_rt_num 5 $($IP -6 route list |grep -v expires|grep 2001:20::|wc -l)
868         log_test $ret 0 "ipv6 route garbage collection (replace with permanent)"
869 
870         # ra6 is required for the next test. (ipv6toolkit)
871         if [ ! -x "$(command -v ra6)" ]; then
872             echo "SKIP: ra6 not found."
873             set +e
874             cleanup &> /dev/null
875             return
876         fi
877 
878         # Delete dummy_10 and remove all routes
879         $IP link del dev dummy_10
880 
881         # Create a pair of veth devices to send a RA message from one
882         # device to another.
883         $IP link add veth1 type veth peer name veth2
884         $IP link set dev veth1 up
885         $IP link set dev veth2 up
886         $IP -6 address add 2001:10::1/64 dev veth1 nodad
887         $IP -6 address add 2001:10::2/64 dev veth2 nodad
888 
889         # Make veth1 ready to receive RA messages.
890         $NS_EXEC sysctl -wq net.ipv6.conf.veth1.accept_ra=2
891 
892         # Send a RA message with a route from veth2 to veth1.
893         $NS_EXEC ra6 -i veth2 -d 2001:10::1 -t $EXPIRE
894 
895         # Wait for the RA message.
896         sleep 1
897 
898         # systemd may mess up the test.  You syould make sure that
899         # systemd-networkd.service and systemd-networkd.socket are stopped.
900         check_rt_num_clean 1 $($IP -6 route list|grep expires|wc -l) || return
901 
902         # Wait for GC
903         sleep $GC_WAIT_TIME
904         check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
905         log_test $ret 0 "ipv6 route garbage collection (RA message)"
906 
907         set +e
908 
909         cleanup &> /dev/null
910 }
911 
912 fib_suppress_test()
913 {
914         echo
915         echo "FIB rule with suppress_prefixlength"
916         setup
917 
918         $IP link add dummy1 type dummy
919         $IP link set dummy1 up
920         $IP -6 route add default dev dummy1
921         $IP -6 rule add table main suppress_prefixlength 0
922         ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
923         $IP -6 rule del table main suppress_prefixlength 0
924         $IP link del dummy1
925 
926         # If we got here without crashing, we're good.
927         log_test 0 0 "FIB rule suppress test"
928 
929         cleanup
930 }
931 
932 ################################################################################
933 # Tests on route add and replace
934 
935 run_cmd()
936 {
937         local cmd="$1"
938         local out
939         local stderr="2>/dev/null"
940 
941         if [ "$VERBOSE" = "1" ]; then
942                 printf "    COMMAND: $cmd\n"
943                 stderr=
944         fi
945 
946         out=$(eval $cmd $stderr)
947         rc=$?
948         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
949                 echo "    $out"
950         fi
951 
952         [ "$VERBOSE" = "1" ] && echo
953 
954         return $rc
955 }
956 
957 check_expected()
958 {
959         local out="$1"
960         local expected="$2"
961         local rc=0
962 
963         [ "${out}" = "${expected}" ] && return 0
964 
965         if [ -z "${out}" ]; then
966                 if [ "$VERBOSE" = "1" ]; then
967                         printf "\nNo route entry found\n"
968                         printf "Expected:\n"
969                         printf "    ${expected}\n"
970                 fi
971                 return 1
972         fi
973 
974         # tricky way to convert output to 1-line without ip's
975         # messy '\'; this drops all extra white space
976         out=$(echo ${out})
977         if [ "${out}" != "${expected}" ]; then
978                 rc=1
979                 if [ "${VERBOSE}" = "1" ]; then
980                         printf "    Unexpected route entry. Have:\n"
981                         printf "        ${out}\n"
982                         printf "    Expected:\n"
983                         printf "        ${expected}\n\n"
984                 fi
985         fi
986 
987         return $rc
988 }
989 
990 # add route for a prefix, flushing any existing routes first
991 # expected to be the first step of a test
992 add_route6()
993 {
994         local pfx="$1"
995         local nh="$2"
996         local out
997 
998         if [ "$VERBOSE" = "1" ]; then
999                 echo
1000                 echo "    ##################################################"
1001                 echo
1002         fi
1003 
1004         run_cmd "$IP -6 ro flush ${pfx}"
1005         [ $? -ne 0 ] && exit 1
1006 
1007         out=$($IP -6 ro ls match ${pfx})
1008         if [ -n "$out" ]; then
1009                 echo "Failed to flush routes for prefix used for tests."
1010                 exit 1
1011         fi
1012 
1013         run_cmd "$IP -6 ro add ${pfx} ${nh}"
1014         if [ $? -ne 0 ]; then
1015                 echo "Failed to add initial route for test."
1016                 exit 1
1017         fi
1018 }
1019 
1020 # add initial route - used in replace route tests
1021 add_initial_route6()
1022 {
1023         add_route6 "2001:db8:104::/64" "$1"
1024 }
1025 
1026 check_route6()
1027 {
1028         local pfx
1029         local expected="$1"
1030         local out
1031         local rc=0
1032 
1033         set -- $expected
1034         pfx=$1
1035 
1036         out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
1037         check_expected "${out}" "${expected}"
1038 }
1039 
1040 route_cleanup()
1041 {
1042         $IP li del red 2>/dev/null
1043         $IP li del dummy1 2>/dev/null
1044         $IP li del veth1 2>/dev/null
1045         $IP li del veth3 2>/dev/null
1046 
1047         cleanup &> /dev/null
1048 }
1049 
1050 route_setup()
1051 {
1052         route_cleanup
1053         setup
1054 
1055         [ "${VERBOSE}" = "1" ] && set -x
1056         set -e
1057 
1058         setup_ns ns2
1059         ip netns exec $ns2 sysctl -qw net.ipv4.ip_forward=1
1060         ip netns exec $ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
1061 
1062         $IP li add veth1 type veth peer name veth2
1063         $IP li add veth3 type veth peer name veth4
1064 
1065         $IP li set veth1 up
1066         $IP li set veth3 up
1067         $IP li set veth2 netns $ns2 up
1068         $IP li set veth4 netns $ns2 up
1069         ip -netns $ns2 li add dummy1 type dummy
1070         ip -netns $ns2 li set dummy1 up
1071 
1072         $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
1073         $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
1074         $IP addr add 172.16.101.1/24 dev veth1
1075         $IP addr add 172.16.103.1/24 dev veth3
1076 
1077         ip -netns $ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
1078         ip -netns $ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
1079         ip -netns $ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
1080 
1081         ip -netns $ns2 addr add 172.16.101.2/24 dev veth2
1082         ip -netns $ns2 addr add 172.16.103.2/24 dev veth4
1083         ip -netns $ns2 addr add 172.16.104.1/24 dev dummy1
1084 
1085         set +e
1086 }
1087 
1088 # assumption is that basic add of a single path route works
1089 # otherwise just adding an address on an interface is broken
1090 ipv6_rt_add()
1091 {
1092         local rc
1093 
1094         echo
1095         echo "IPv6 route add / append tests"
1096 
1097         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1098         add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1099         run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
1100         log_test $? 2 "Attempt to add duplicate route - gw"
1101 
1102         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1103         add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1104         run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
1105         log_test $? 2 "Attempt to add duplicate route - dev only"
1106 
1107         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1108         add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1109         run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
1110         log_test $? 2 "Attempt to add duplicate route - reject route"
1111 
1112         # route append with same prefix adds a new route
1113         # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1114         add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1115         run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
1116         check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1117         log_test $? 0 "Append nexthop to existing route - gw"
1118 
1119         # insert mpath directly
1120         add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1121         check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1122         log_test $? 0 "Add multipath route"
1123 
1124         add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1125         run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1126         log_test $? 2 "Attempt to add duplicate multipath route"
1127 
1128         # insert of a second route without append but different metric
1129         add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1130         run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
1131         rc=$?
1132         if [ $rc -eq 0 ]; then
1133                 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
1134                 rc=$?
1135         fi
1136         log_test $rc 0 "Route add with different metrics"
1137 
1138         run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
1139         rc=$?
1140         if [ $rc -eq 0 ]; then
1141                 check_route6 "2001:db8:104::/64 via 2001:db8:103::3 dev veth3 metric 256 2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1142                 rc=$?
1143         fi
1144         log_test $rc 0 "Route delete with metric"
1145 }
1146 
1147 ipv6_rt_replace_single()
1148 {
1149         # single path with single path
1150         #
1151         add_initial_route6 "via 2001:db8:101::2"
1152         run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
1153         check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1154         log_test $? 0 "Single path with single path"
1155 
1156         # single path with multipath
1157         #
1158         add_initial_route6 "nexthop via 2001:db8:101::2"
1159         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
1160         check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1161         log_test $? 0 "Single path with multipath"
1162 
1163         # single path with single path using MULTIPATH attribute
1164         #
1165         add_initial_route6 "via 2001:db8:101::2"
1166         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
1167         check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1168         log_test $? 0 "Single path with single path via multipath attribute"
1169 
1170         # route replace fails - invalid nexthop
1171         add_initial_route6 "via 2001:db8:101::2"
1172         run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
1173         if [ $? -eq 0 ]; then
1174                 # previous command is expected to fail so if it returns 0
1175                 # that means the test failed.
1176                 log_test 0 1 "Invalid nexthop"
1177         else
1178                 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1179                 log_test $? 0 "Invalid nexthop"
1180         fi
1181 
1182         # replace non-existent route
1183         # - note use of change versus replace since ip adds NLM_F_CREATE
1184         #   for replace
1185         add_initial_route6 "via 2001:db8:101::2"
1186         run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
1187         log_test $? 2 "Single path - replace of non-existent route"
1188 }
1189 
1190 ipv6_rt_replace_mpath()
1191 {
1192         # multipath with multipath
1193         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1194         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1195         check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::3 dev veth3 weight 1"
1196         log_test $? 0 "Multipath with multipath"
1197 
1198         # multipath with single
1199         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1200         run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
1201         check_route6  "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1202         log_test $? 0 "Multipath with single path"
1203 
1204         # multipath with single
1205         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1206         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
1207         check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1208         log_test $? 0 "Multipath with single path via multipath attribute"
1209 
1210         # multipath with dev-only
1211         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1212         run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
1213         check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
1214         log_test $? 0 "Multipath with dev-only"
1215 
1216         # route replace fails - invalid nexthop 1
1217         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1218         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
1219         check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1220         log_test $? 0 "Multipath - invalid first nexthop"
1221 
1222         # route replace fails - invalid nexthop 2
1223         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1224         run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
1225         check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1226         log_test $? 0 "Multipath - invalid second nexthop"
1227 
1228         # multipath non-existent route
1229         add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1230         run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1231         log_test $? 2 "Multipath - replace of non-existent route"
1232 }
1233 
1234 ipv6_rt_replace()
1235 {
1236         echo
1237         echo "IPv6 route replace tests"
1238 
1239         ipv6_rt_replace_single
1240         ipv6_rt_replace_mpath
1241 }
1242 
1243 ipv6_rt_dsfield()
1244 {
1245         echo
1246         echo "IPv6 route with dsfield tests"
1247 
1248         run_cmd "$IP -6 route flush 2001:db8:102::/64"
1249 
1250         # IPv6 doesn't support routing based on dsfield
1251         run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1252         log_test $? 2 "Reject route with dsfield"
1253 }
1254 
1255 ipv6_route_test()
1256 {
1257         route_setup
1258 
1259         ipv6_rt_add
1260         ipv6_rt_replace
1261         ipv6_rt_dsfield
1262 
1263         route_cleanup
1264 }
1265 
1266 ip_addr_metric_check()
1267 {
1268         ip addr help 2>&1 | grep -q metric
1269         if [ $? -ne 0 ]; then
1270                 echo "iproute2 command does not support metric for addresses. Skipping test"
1271                 return 1
1272         fi
1273 
1274         return 0
1275 }
1276 
1277 ipv6_addr_metric_test()
1278 {
1279         local rc
1280 
1281         echo
1282         echo "IPv6 prefix route tests"
1283 
1284         ip_addr_metric_check || return 1
1285 
1286         setup
1287 
1288         set -e
1289         $IP li add dummy1 type dummy
1290         $IP li add dummy2 type dummy
1291         $IP li set dummy1 up
1292         $IP li set dummy2 up
1293 
1294         # default entry is metric 256
1295         run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1296         run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1297         set +e
1298 
1299         check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1300         log_test $? 0 "Default metric"
1301 
1302         set -e
1303         run_cmd "$IP -6 addr flush dev dummy1"
1304         run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1305         set +e
1306 
1307         check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1308         log_test $? 0 "User specified metric on first device"
1309 
1310         set -e
1311         run_cmd "$IP -6 addr flush dev dummy2"
1312         run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1313         set +e
1314 
1315         check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1316         log_test $? 0 "User specified metric on second device"
1317 
1318         run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1319         rc=$?
1320         if [ $rc -eq 0 ]; then
1321                 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1322                 rc=$?
1323         fi
1324         log_test $rc 0 "Delete of address on first device"
1325 
1326         run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1327         rc=$?
1328         if [ $rc -eq 0 ]; then
1329                 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1330                 rc=$?
1331         fi
1332         log_test $rc 0 "Modify metric of address"
1333 
1334         # verify prefix route removed on down
1335         run_cmd "ip netns exec $ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1336         run_cmd "$IP li set dev dummy2 down"
1337         rc=$?
1338         if [ $rc -eq 0 ]; then
1339                 out=$($IP -6 ro ls match 2001:db8:104::/64)
1340                 check_expected "${out}" ""
1341                 rc=$?
1342         fi
1343         log_test $rc 0 "Prefix route removed on link down"
1344 
1345         # verify prefix route re-inserted with assigned metric
1346         run_cmd "$IP li set dev dummy2 up"
1347         rc=$?
1348         if [ $rc -eq 0 ]; then
1349                 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1350                 rc=$?
1351         fi
1352         log_test $rc 0 "Prefix route with metric on link up"
1353 
1354         # verify peer metric added correctly
1355         set -e
1356         run_cmd "$IP -6 addr flush dev dummy2"
1357         run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1358         set +e
1359 
1360         check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1361         log_test $? 0 "Set metric with peer route on local side"
1362         check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1363         log_test $? 0 "Set metric with peer route on peer side"
1364 
1365         set -e
1366         run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1367         set +e
1368 
1369         check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1370         log_test $? 0 "Modify metric and peer address on local side"
1371         check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1372         log_test $? 0 "Modify metric and peer address on peer side"
1373 
1374         $IP li del dummy1
1375         $IP li del dummy2
1376         cleanup
1377 }
1378 
1379 ipv6_route_metrics_test()
1380 {
1381         local rc
1382 
1383         echo
1384         echo "IPv6 routes with metrics"
1385 
1386         route_setup
1387 
1388         #
1389         # single path with metrics
1390         #
1391         run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1392         rc=$?
1393         if [ $rc -eq 0 ]; then
1394                 check_route6  "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1395                 rc=$?
1396         fi
1397         log_test $rc 0 "Single path route with mtu metric"
1398 
1399 
1400         #
1401         # multipath via separate routes with metrics
1402         #
1403         run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1404         run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1405         rc=$?
1406         if [ $rc -eq 0 ]; then
1407                 check_route6 "2001:db8:112::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1408                 rc=$?
1409         fi
1410         log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1411 
1412         # second route is coalesced to first to make a multipath route.
1413         # MTU of the second path is hidden from display!
1414         run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1415         run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1416         rc=$?
1417         if [ $rc -eq 0 ]; then
1418                 check_route6 "2001:db8:113::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1419                 rc=$?
1420         fi
1421         log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1422 
1423         run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1424         if [ $? -eq 0 ]; then
1425                 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1426                 log_test $? 0 "    MTU of second leg"
1427         fi
1428 
1429         #
1430         # multipath with metrics
1431         #
1432         run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1433         rc=$?
1434         if [ $rc -eq 0 ]; then
1435                 check_route6  "2001:db8:115::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1436                 rc=$?
1437         fi
1438         log_test $rc 0 "Multipath route with mtu metric"
1439 
1440         $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1441         run_cmd "ip netns exec $ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1442         log_test $? 0 "Using route with mtu metric"
1443 
1444         run_cmd "$IP -6 ro add 2001:db8:114::/64 via  2001:db8:101::2  congctl lock foo"
1445         log_test $? 2 "Invalid metric (fails metric_convert)"
1446 
1447         route_cleanup
1448 }
1449 
1450 # add route for a prefix, flushing any existing routes first
1451 # expected to be the first step of a test
1452 add_route()
1453 {
1454         local pfx="$1"
1455         local nh="$2"
1456         local out
1457 
1458         if [ "$VERBOSE" = "1" ]; then
1459                 echo
1460                 echo "    ##################################################"
1461                 echo
1462         fi
1463 
1464         run_cmd "$IP ro flush ${pfx}"
1465         [ $? -ne 0 ] && exit 1
1466 
1467         out=$($IP ro ls match ${pfx})
1468         if [ -n "$out" ]; then
1469                 echo "Failed to flush routes for prefix used for tests."
1470                 exit 1
1471         fi
1472 
1473         run_cmd "$IP ro add ${pfx} ${nh}"
1474         if [ $? -ne 0 ]; then
1475                 echo "Failed to add initial route for test."
1476                 exit 1
1477         fi
1478 }
1479 
1480 # add initial route - used in replace route tests
1481 add_initial_route()
1482 {
1483         add_route "172.16.104.0/24" "$1"
1484 }
1485 
1486 check_route()
1487 {
1488         local pfx
1489         local expected="$1"
1490         local out
1491 
1492         set -- $expected
1493         pfx=$1
1494         [ "${pfx}" = "unreachable" ] && pfx=$2
1495 
1496         out=$($IP ro ls match ${pfx})
1497         check_expected "${out}" "${expected}"
1498 }
1499 
1500 # assumption is that basic add of a single path route works
1501 # otherwise just adding an address on an interface is broken
1502 ipv4_rt_add()
1503 {
1504         local rc
1505 
1506         echo
1507         echo "IPv4 route add / append tests"
1508 
1509         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1510         add_route "172.16.104.0/24" "via 172.16.101.2"
1511         run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1512         log_test $? 2 "Attempt to add duplicate route - gw"
1513 
1514         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1515         add_route "172.16.104.0/24" "via 172.16.101.2"
1516         run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1517         log_test $? 2 "Attempt to add duplicate route - dev only"
1518 
1519         # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1520         add_route "172.16.104.0/24" "via 172.16.101.2"
1521         run_cmd "$IP ro add unreachable 172.16.104.0/24"
1522         log_test $? 2 "Attempt to add duplicate route - reject route"
1523 
1524         # iproute2 prepend only sets NLM_F_CREATE
1525         # - adds a new route; does NOT convert existing route to ECMP
1526         add_route "172.16.104.0/24" "via 172.16.101.2"
1527         run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1528         check_route "172.16.104.0/24 via 172.16.103.2 dev veth3 172.16.104.0/24 via 172.16.101.2 dev veth1"
1529         log_test $? 0 "Add new nexthop for existing prefix"
1530 
1531         # route append with same prefix adds a new route
1532         # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1533         add_route "172.16.104.0/24" "via 172.16.101.2"
1534         run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1535         check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.2 dev veth3"
1536         log_test $? 0 "Append nexthop to existing route - gw"
1537 
1538         add_route "172.16.104.0/24" "via 172.16.101.2"
1539         run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1540         check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1541         log_test $? 0 "Append nexthop to existing route - dev only"
1542 
1543         add_route "172.16.104.0/24" "via 172.16.101.2"
1544         run_cmd "$IP ro append unreachable 172.16.104.0/24"
1545         check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1546         log_test $? 0 "Append nexthop to existing route - reject route"
1547 
1548         run_cmd "$IP ro flush 172.16.104.0/24"
1549         run_cmd "$IP ro add unreachable 172.16.104.0/24"
1550         run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1551         check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1552         log_test $? 0 "Append nexthop to existing reject route - gw"
1553 
1554         run_cmd "$IP ro flush 172.16.104.0/24"
1555         run_cmd "$IP ro add unreachable 172.16.104.0/24"
1556         run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1557         check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1558         log_test $? 0 "Append nexthop to existing reject route - dev only"
1559 
1560         # insert mpath directly
1561         add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1562         check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1563         log_test $? 0 "add multipath route"
1564 
1565         add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1566         run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1567         log_test $? 2 "Attempt to add duplicate multipath route"
1568 
1569         # insert of a second route without append but different metric
1570         add_route "172.16.104.0/24" "via 172.16.101.2"
1571         run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1572         rc=$?
1573         if [ $rc -eq 0 ]; then
1574                 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1575                 rc=$?
1576         fi
1577         log_test $rc 0 "Route add with different metrics"
1578 
1579         run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1580         rc=$?
1581         if [ $rc -eq 0 ]; then
1582                 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.3 dev veth3 metric 256"
1583                 rc=$?
1584         fi
1585         log_test $rc 0 "Route delete with metric"
1586 }
1587 
1588 ipv4_rt_replace_single()
1589 {
1590         # single path with single path
1591         #
1592         add_initial_route "via 172.16.101.2"
1593         run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1594         check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1595         log_test $? 0 "Single path with single path"
1596 
1597         # single path with multipath
1598         #
1599         add_initial_route "nexthop via 172.16.101.2"
1600         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1601         check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1602         log_test $? 0 "Single path with multipath"
1603 
1604         # single path with reject
1605         #
1606         add_initial_route "nexthop via 172.16.101.2"
1607         run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1608         check_route "unreachable 172.16.104.0/24"
1609         log_test $? 0 "Single path with reject route"
1610 
1611         # single path with single path using MULTIPATH attribute
1612         #
1613         add_initial_route "via 172.16.101.2"
1614         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1615         check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1616         log_test $? 0 "Single path with single path via multipath attribute"
1617 
1618         # route replace fails - invalid nexthop
1619         add_initial_route "via 172.16.101.2"
1620         run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1621         if [ $? -eq 0 ]; then
1622                 # previous command is expected to fail so if it returns 0
1623                 # that means the test failed.
1624                 log_test 0 1 "Invalid nexthop"
1625         else
1626                 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1627                 log_test $? 0 "Invalid nexthop"
1628         fi
1629 
1630         # replace non-existent route
1631         # - note use of change versus replace since ip adds NLM_F_CREATE
1632         #   for replace
1633         add_initial_route "via 172.16.101.2"
1634         run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1635         log_test $? 2 "Single path - replace of non-existent route"
1636 }
1637 
1638 ipv4_rt_replace_mpath()
1639 {
1640         # multipath with multipath
1641         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1642         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1643         check_route  "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.3 dev veth3 weight 1"
1644         log_test $? 0 "Multipath with multipath"
1645 
1646         # multipath with single
1647         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1648         run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1649         check_route  "172.16.104.0/24 via 172.16.101.3 dev veth1"
1650         log_test $? 0 "Multipath with single path"
1651 
1652         # multipath with single
1653         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1654         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1655         check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1656         log_test $? 0 "Multipath with single path via multipath attribute"
1657 
1658         # multipath with reject
1659         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1660         run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1661         check_route "unreachable 172.16.104.0/24"
1662         log_test $? 0 "Multipath with reject route"
1663 
1664         # route replace fails - invalid nexthop 1
1665         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1666         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1667         check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1668         log_test $? 0 "Multipath - invalid first nexthop"
1669 
1670         # route replace fails - invalid nexthop 2
1671         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1672         run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1673         check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1674         log_test $? 0 "Multipath - invalid second nexthop"
1675 
1676         # multipath non-existent route
1677         add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1678         run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1679         log_test $? 2 "Multipath - replace of non-existent route"
1680 }
1681 
1682 ipv4_rt_replace()
1683 {
1684         echo
1685         echo "IPv4 route replace tests"
1686 
1687         ipv4_rt_replace_single
1688         ipv4_rt_replace_mpath
1689 }
1690 
1691 # checks that cached input route on VRF port is deleted
1692 # when VRF is deleted
1693 ipv4_local_rt_cache()
1694 {
1695         run_cmd "ip addr add 10.0.0.1/32 dev lo"
1696         run_cmd "setup_ns test-ns"
1697         run_cmd "ip link add veth-outside type veth peer name veth-inside"
1698         run_cmd "ip link add vrf-100 type vrf table 1100"
1699         run_cmd "ip link set veth-outside master vrf-100"
1700         run_cmd "ip link set veth-inside netns $test-ns"
1701         run_cmd "ip link set veth-outside up"
1702         run_cmd "ip link set vrf-100 up"
1703         run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1704         run_cmd "ip netns exec $test-ns ip link set veth-inside up"
1705         run_cmd "ip netns exec $test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1706         run_cmd "ip netns exec $test-ns ip route add 10.0.0.1/32 dev veth-inside"
1707         run_cmd "ip netns exec $test-ns ip route add default via 10.0.0.1"
1708         run_cmd "ip netns exec $test-ns ping 10.0.0.1 -c 1 -i 1"
1709         run_cmd "ip link delete vrf-100"
1710 
1711         # if we do not hang test is a success
1712         log_test $? 0 "Cached route removed from VRF port device"
1713 }
1714 
1715 ipv4_rt_dsfield()
1716 {
1717         echo
1718         echo "IPv4 route with dsfield tests"
1719 
1720         run_cmd "$IP route flush 172.16.102.0/24"
1721 
1722         # New routes should reject dsfield options that interfere with ECN
1723         run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1724         log_test $? 2 "Reject route with dsfield 0x01"
1725 
1726         run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1727         log_test $? 2 "Reject route with dsfield 0x02"
1728 
1729         run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1730         log_test $? 2 "Reject route with dsfield 0x03"
1731 
1732         # A generic route that doesn't take DSCP into account
1733         run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1734 
1735         # A more specific route for DSCP 0x10
1736         run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1737 
1738         # DSCP 0x10 should match the specific route, no matter the ECN bits
1739         $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1740                 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1741         log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1742 
1743         $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1744                 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1745         log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1746 
1747         $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1748                 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1749         log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1750 
1751         $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1752                 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1753         log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1754 
1755         # Unknown DSCP should match the generic route, no matter the ECN bits
1756         $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1757                 grep -q "172.16.102.0/24 via 172.16.101.2"
1758         log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1759 
1760         $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1761                 grep -q "172.16.102.0/24 via 172.16.101.2"
1762         log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1763 
1764         $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1765                 grep -q "172.16.102.0/24 via 172.16.101.2"
1766         log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1767 
1768         $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1769                 grep -q "172.16.102.0/24 via 172.16.101.2"
1770         log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1771 
1772         # Null DSCP should match the generic route, no matter the ECN bits
1773         $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1774                 grep -q "172.16.102.0/24 via 172.16.101.2"
1775         log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1776 
1777         $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1778                 grep -q "172.16.102.0/24 via 172.16.101.2"
1779         log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1780 
1781         $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1782                 grep -q "172.16.102.0/24 via 172.16.101.2"
1783         log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1784 
1785         $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1786                 grep -q "172.16.102.0/24 via 172.16.101.2"
1787         log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1788 }
1789 
1790 ipv4_route_test()
1791 {
1792         route_setup
1793 
1794         ipv4_rt_add
1795         ipv4_rt_replace
1796         ipv4_local_rt_cache
1797         ipv4_rt_dsfield
1798 
1799         route_cleanup
1800 }
1801 
1802 ipv4_addr_metric_test()
1803 {
1804         local rc
1805 
1806         echo
1807         echo "IPv4 prefix route tests"
1808 
1809         ip_addr_metric_check || return 1
1810 
1811         setup
1812 
1813         set -e
1814         $IP li add dummy1 type dummy
1815         $IP li add dummy2 type dummy
1816         $IP li set dummy1 up
1817         $IP li set dummy2 up
1818 
1819         # default entry is metric 256
1820         run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1821         run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1822         set +e
1823 
1824         check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2"
1825         log_test $? 0 "Default metric"
1826 
1827         set -e
1828         run_cmd "$IP addr flush dev dummy1"
1829         run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1830         set +e
1831 
1832         check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257"
1833         log_test $? 0 "User specified metric on first device"
1834 
1835         set -e
1836         run_cmd "$IP addr flush dev dummy2"
1837         run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1838         set +e
1839 
1840         check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1841         log_test $? 0 "User specified metric on second device"
1842 
1843         run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1844         rc=$?
1845         if [ $rc -eq 0 ]; then
1846                 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1847                 rc=$?
1848         fi
1849         log_test $rc 0 "Delete of address on first device"
1850 
1851         run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1852         rc=$?
1853         if [ $rc -eq 0 ]; then
1854                 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1855                 rc=$?
1856         fi
1857         log_test $rc 0 "Modify metric of address"
1858 
1859         # verify prefix route removed on down
1860         run_cmd "$IP li set dev dummy2 down"
1861         rc=$?
1862         if [ $rc -eq 0 ]; then
1863                 out=$($IP ro ls match 172.16.104.0/24)
1864                 check_expected "${out}" ""
1865                 rc=$?
1866         fi
1867         log_test $rc 0 "Prefix route removed on link down"
1868 
1869         # verify prefix route re-inserted with assigned metric
1870         run_cmd "$IP li set dev dummy2 up"
1871         rc=$?
1872         if [ $rc -eq 0 ]; then
1873                 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1874                 rc=$?
1875         fi
1876         log_test $rc 0 "Prefix route with metric on link up"
1877 
1878         # explicitly check for metric changes on edge scenarios
1879         run_cmd "$IP addr flush dev dummy2"
1880         run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1881         run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1882         rc=$?
1883         if [ $rc -eq 0 ]; then
1884                 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1885                 rc=$?
1886         fi
1887         log_test $rc 0 "Modify metric of .0/24 address"
1888 
1889         run_cmd "$IP addr flush dev dummy2"
1890         run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1891         rc=$?
1892         if [ $rc -eq 0 ]; then
1893                 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1894                 rc=$?
1895         fi
1896         log_test $rc 0 "Set metric of address with peer route"
1897 
1898         run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1899         rc=$?
1900         if [ $rc -eq 0 ]; then
1901                 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1902                 rc=$?
1903         fi
1904         log_test $rc 0 "Modify metric and peer address for peer route"
1905 
1906         $IP li del dummy1
1907         $IP li del dummy2
1908         cleanup
1909 }
1910 
1911 ipv4_route_metrics_test()
1912 {
1913         local rc
1914 
1915         echo
1916         echo "IPv4 route add / append tests"
1917 
1918         route_setup
1919 
1920         run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1921         rc=$?
1922         if [ $rc -eq 0 ]; then
1923                 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1924                 rc=$?
1925         fi
1926         log_test $rc 0 "Single path route with mtu metric"
1927 
1928 
1929         run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1930         rc=$?
1931         if [ $rc -eq 0 ]; then
1932                 check_route "172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1933                 rc=$?
1934         fi
1935         log_test $rc 0 "Multipath route with mtu metric"
1936 
1937         $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1938         run_cmd "ip netns exec $ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1939         log_test $? 0 "Using route with mtu metric"
1940 
1941         run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1942         log_test $? 2 "Invalid metric (fails metric_convert)"
1943 
1944         route_cleanup
1945 }
1946 
1947 ipv4_del_addr_test()
1948 {
1949         echo
1950         echo "IPv4 delete address route tests"
1951 
1952         setup
1953 
1954         set -e
1955         $IP li add dummy1 type dummy
1956         $IP li set dummy1 up
1957         $IP li add dummy2 type dummy
1958         $IP li set dummy2 up
1959         $IP li add red type vrf table 1111
1960         $IP li set red up
1961         $IP ro add vrf red unreachable default
1962         $IP li set dummy2 vrf red
1963 
1964         $IP addr add dev dummy1 172.16.104.1/24
1965         $IP addr add dev dummy1 172.16.104.11/24
1966         $IP addr add dev dummy1 172.16.104.12/24
1967         $IP addr add dev dummy1 172.16.104.13/24
1968         $IP addr add dev dummy2 172.16.104.1/24
1969         $IP addr add dev dummy2 172.16.104.11/24
1970         $IP addr add dev dummy2 172.16.104.12/24
1971         $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1972         $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1973         $IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
1974         $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1975         $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1976         set +e
1977 
1978         # removing address from device in vrf should only remove route from vrf table
1979         echo "    Regular FIB info"
1980 
1981         $IP addr del dev dummy2 172.16.104.11/24
1982         $IP ro ls vrf red | grep -q 172.16.105.0/24
1983         log_test $? 1 "Route removed from VRF when source address deleted"
1984 
1985         $IP ro ls | grep -q 172.16.105.0/24
1986         log_test $? 0 "Route in default VRF not removed"
1987 
1988         $IP addr add dev dummy2 172.16.104.11/24
1989         $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1990 
1991         $IP addr del dev dummy1 172.16.104.11/24
1992         $IP ro ls | grep -q 172.16.105.0/24
1993         log_test $? 1 "Route removed in default VRF when source address deleted"
1994 
1995         $IP ro ls vrf red | grep -q 172.16.105.0/24
1996         log_test $? 0 "Route in VRF is not removed by address delete"
1997 
1998         # removing address from device in vrf should only remove route from vrf
1999         # table even when the associated fib info only differs in table ID
2000         echo "    Identical FIB info with different table ID"
2001 
2002         $IP addr del dev dummy2 172.16.104.12/24
2003         $IP ro ls vrf red | grep -q 172.16.106.0/24
2004         log_test $? 1 "Route removed from VRF when source address deleted"
2005 
2006         $IP ro ls | grep -q 172.16.106.0/24
2007         log_test $? 0 "Route in default VRF not removed"
2008 
2009         $IP addr add dev dummy2 172.16.104.12/24
2010         $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
2011 
2012         $IP addr del dev dummy1 172.16.104.12/24
2013         $IP ro ls | grep -q 172.16.106.0/24
2014         log_test $? 1 "Route removed in default VRF when source address deleted"
2015 
2016         $IP ro ls vrf red | grep -q 172.16.106.0/24
2017         log_test $? 0 "Route in VRF is not removed by address delete"
2018 
2019         # removing address from device in default vrf should remove route from
2020         # the default vrf even when route was inserted with a table ID of 0.
2021         echo "    Table ID 0"
2022 
2023         $IP addr del dev dummy1 172.16.104.13/24
2024         $IP ro ls | grep -q 172.16.107.0/24
2025         log_test $? 1 "Route removed in default VRF when source address deleted"
2026 
2027         $IP li del dummy1
2028         $IP li del dummy2
2029         cleanup
2030 }
2031 
2032 ipv6_del_addr_test()
2033 {
2034         echo
2035         echo "IPv6 delete address route tests"
2036 
2037         setup
2038 
2039         set -e
2040         for i in $(seq 6); do
2041                 $IP li add dummy${i} up type dummy
2042         done
2043 
2044         $IP li add red up type vrf table 1111
2045         $IP ro add vrf red unreachable default
2046         for i in $(seq 4 6); do
2047                 $IP li set dummy${i} vrf red
2048         done
2049 
2050         $IP addr add dev dummy1 fe80::1/128
2051         $IP addr add dev dummy1 2001:db8:101::1/64
2052         $IP addr add dev dummy1 2001:db8:101::10/64
2053         $IP addr add dev dummy1 2001:db8:101::11/64
2054         $IP addr add dev dummy1 2001:db8:101::12/64
2055         $IP addr add dev dummy1 2001:db8:101::13/64
2056         $IP addr add dev dummy1 2001:db8:101::14/64
2057         $IP addr add dev dummy1 2001:db8:101::15/64
2058         $IP addr add dev dummy2 fe80::1/128
2059         $IP addr add dev dummy2 2001:db8:101::1/64
2060         $IP addr add dev dummy2 2001:db8:101::11/64
2061         $IP addr add dev dummy3 fe80::1/128
2062 
2063         $IP addr add dev dummy4 2001:db8:101::1/64
2064         $IP addr add dev dummy4 2001:db8:101::10/64
2065         $IP addr add dev dummy4 2001:db8:101::11/64
2066         $IP addr add dev dummy4 2001:db8:101::12/64
2067         $IP addr add dev dummy4 2001:db8:101::13/64
2068         $IP addr add dev dummy4 2001:db8:101::14/64
2069         $IP addr add dev dummy5 2001:db8:101::1/64
2070         $IP addr add dev dummy5 2001:db8:101::11/64
2071 
2072         # Single device using src address
2073         $IP route add 2001:db8:110::/64 dev dummy3 src 2001:db8:101::10
2074         # Two devices with the same source address
2075         $IP route add 2001:db8:111::/64 dev dummy3 src 2001:db8:101::11
2076         # VRF with single device using src address
2077         $IP route add vrf red 2001:db8:110::/64 dev dummy6 src 2001:db8:101::10
2078         # VRF with two devices using src address
2079         $IP route add vrf red 2001:db8:111::/64 dev dummy6 src 2001:db8:101::11
2080         # src address and nexthop dev in same VRF
2081         $IP route add 2001:db8:112::/64 dev dummy3 src 2001:db8:101::12
2082         $IP route add vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2083         # src address and nexthop device in different VRF
2084         $IP route add 2001:db8:113::/64 dev lo src 2001:db8:101::13
2085         $IP route add vrf red 2001:db8:113::/64 dev lo src 2001:db8:101::13
2086         # table ID 0
2087         $IP route add table 0 2001:db8:115::/64 via 2001:db8:101::2 src 2001:db8:101::15
2088         # Link local source route
2089         $IP route add 2001:db8:116::/64 dev dummy2 src fe80::1
2090         $IP route add 2001:db8:117::/64 dev dummy3 src fe80::1
2091         set +e
2092 
2093         echo "    Single device using src address"
2094 
2095         $IP addr del dev dummy1 2001:db8:101::10/64
2096         $IP -6 route show | grep -q "src 2001:db8:101::10 "
2097         log_test $? 1 "Prefsrc removed when src address removed on other device"
2098 
2099         echo "    Two devices with the same source address"
2100 
2101         $IP addr del dev dummy1 2001:db8:101::11/64
2102         $IP -6 route show | grep -q "src 2001:db8:101::11 "
2103         log_test $? 0 "Prefsrc not removed when src address exist on other device"
2104 
2105         $IP addr del dev dummy2 2001:db8:101::11/64
2106         $IP -6 route show | grep -q "src 2001:db8:101::11 "
2107         log_test $? 1 "Prefsrc removed when src address removed on all devices"
2108 
2109         echo "    VRF with single device using src address"
2110 
2111         $IP addr del dev dummy4 2001:db8:101::10/64
2112         $IP -6 route show vrf red | grep -q "src 2001:db8:101::10 "
2113         log_test $? 1 "Prefsrc removed when src address removed on other device"
2114 
2115         echo "    VRF with two devices using src address"
2116 
2117         $IP addr del dev dummy4 2001:db8:101::11/64
2118         $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2119         log_test $? 0 "Prefsrc not removed when src address exist on other device"
2120 
2121         $IP addr del dev dummy5 2001:db8:101::11/64
2122         $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2123         log_test $? 1 "Prefsrc removed when src address removed on all devices"
2124 
2125         echo "    src address and nexthop dev in same VRF"
2126 
2127         $IP addr del dev dummy4 2001:db8:101::12/64
2128         $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2129         log_test $? 1 "Prefsrc removed from VRF when source address deleted"
2130         $IP -6 route show | grep -q " src 2001:db8:101::12 "
2131         log_test $? 0 "Prefsrc in default VRF not removed"
2132 
2133         $IP addr add dev dummy4 2001:db8:101::12/64
2134         $IP route replace vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2135         $IP addr del dev dummy1 2001:db8:101::12/64
2136         $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2137         log_test $? 0 "Prefsrc not removed from VRF when source address exist"
2138         $IP -6 route show | grep -q " src 2001:db8:101::12 "
2139         log_test $? 1 "Prefsrc in default VRF removed"
2140 
2141         echo "    src address and nexthop device in different VRF"
2142 
2143         $IP addr del dev dummy4 2001:db8:101::13/64
2144         $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2145         log_test $? 0 "Prefsrc not removed from VRF when nexthop dev in diff VRF"
2146         $IP -6 route show | grep -q "src 2001:db8:101::13 "
2147         log_test $? 0 "Prefsrc not removed in default VRF"
2148 
2149         $IP addr add dev dummy4 2001:db8:101::13/64
2150         $IP addr del dev dummy1 2001:db8:101::13/64
2151         $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2152         log_test $? 1 "Prefsrc removed from VRF when nexthop dev in diff VRF"
2153         $IP -6 route show | grep -q "src 2001:db8:101::13 "
2154         log_test $? 1 "Prefsrc removed in default VRF"
2155 
2156         echo "    Table ID 0"
2157 
2158         $IP addr del dev dummy1 2001:db8:101::15/64
2159         $IP -6 route show | grep -q "src 2001:db8:101::15"
2160         log_test $? 1 "Prefsrc removed from default VRF when source address deleted"
2161 
2162         echo "    Link local source route"
2163         $IP addr del dev dummy1 fe80::1/128
2164         $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2165         log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2166         $IP addr del dev dummy2 fe80::1/128
2167         $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2168         log_test $? 1 "Prefsrc removed when delete ll addr"
2169         $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2170         log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2171         $IP addr add dev dummy1 fe80::1/128
2172         $IP addr del dev dummy3 fe80::1/128
2173         $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2174         log_test $? 1 "Prefsrc removed even ll addr still exist on other dev"
2175 
2176         for i in $(seq 6); do
2177                 $IP li del dummy${i}
2178         done
2179         cleanup
2180 }
2181 
2182 ipv4_route_v6_gw_test()
2183 {
2184         local rc
2185 
2186         echo
2187         echo "IPv4 route with IPv6 gateway tests"
2188 
2189         route_setup
2190         sleep 2
2191 
2192         #
2193         # single path route
2194         #
2195         run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
2196         rc=$?
2197         log_test $rc 0 "Single path route with IPv6 gateway"
2198         if [ $rc -eq 0 ]; then
2199                 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
2200         fi
2201 
2202         run_cmd "ip netns exec $ns1 ping -w1 -c1 172.16.104.1"
2203         log_test $rc 0 "Single path route with IPv6 gateway - ping"
2204 
2205         run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
2206         rc=$?
2207         log_test $rc 0 "Single path route delete"
2208         if [ $rc -eq 0 ]; then
2209                 check_route "172.16.112.0/24"
2210         fi
2211 
2212         #
2213         # multipath - v6 then v4
2214         #
2215         run_cmd "$IP ro add 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2216         rc=$?
2217         log_test $rc 0 "Multipath route add - v6 nexthop then v4"
2218         if [ $rc -eq 0 ]; then
2219                 check_route "172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
2220         fi
2221 
2222         run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2223         log_test $? 2 "    Multipath route delete - nexthops in wrong order"
2224 
2225         run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2226         log_test $? 0 "    Multipath route delete exact match"
2227 
2228         #
2229         # multipath - v4 then v6
2230         #
2231         run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2232         rc=$?
2233         log_test $rc 0 "Multipath route add - v4 nexthop then v6"
2234         if [ $rc -eq 0 ]; then
2235                 check_route "172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 weight 1 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1"
2236         fi
2237 
2238         run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2239         log_test $? 2 "    Multipath route delete - nexthops in wrong order"
2240 
2241         run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2242         log_test $? 0 "    Multipath route delete exact match"
2243 
2244         route_cleanup
2245 }
2246 
2247 socat_check()
2248 {
2249         if [ ! -x "$(command -v socat)" ]; then
2250                 echo "socat command not found. Skipping test"
2251                 return 1
2252         fi
2253 
2254         return 0
2255 }
2256 
2257 iptables_check()
2258 {
2259         iptables -t mangle -L OUTPUT &> /dev/null
2260         if [ $? -ne 0 ]; then
2261                 echo "iptables configuration not supported. Skipping test"
2262                 return 1
2263         fi
2264 
2265         return 0
2266 }
2267 
2268 ip6tables_check()
2269 {
2270         ip6tables -t mangle -L OUTPUT &> /dev/null
2271         if [ $? -ne 0 ]; then
2272                 echo "ip6tables configuration not supported. Skipping test"
2273                 return 1
2274         fi
2275 
2276         return 0
2277 }
2278 
2279 ipv4_mangle_test()
2280 {
2281         local rc
2282 
2283         echo
2284         echo "IPv4 mangling tests"
2285 
2286         socat_check || return 1
2287         iptables_check || return 1
2288 
2289         route_setup
2290         sleep 2
2291 
2292         local tmp_file=$(mktemp)
2293         ip netns exec $ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
2294 
2295         # Add a FIB rule and a route that will direct our connection to the
2296         # listening server.
2297         $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2298         $IP route add table 123 172.16.101.0/24 dev veth1
2299 
2300         # Add an unreachable route to the main table that will block our
2301         # connection in case the FIB rule is not hit.
2302         $IP route add unreachable 172.16.101.2/32
2303 
2304         run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2305         log_test $? 0 "    Connection with correct parameters"
2306 
2307         run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
2308         log_test $? 1 "    Connection with incorrect parameters"
2309 
2310         # Add a mangling rule and make sure connection is still successful.
2311         $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
2312 
2313         run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2314         log_test $? 0 "    Connection with correct parameters - mangling"
2315 
2316         # Delete the mangling rule and make sure connection is still
2317         # successful.
2318         $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
2319 
2320         run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2321         log_test $? 0 "    Connection with correct parameters - no mangling"
2322 
2323         # Verify connections were indeed successful on server side.
2324         [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2325         log_test $? 0 "    Connection check - server side"
2326 
2327         $IP route del unreachable 172.16.101.2/32
2328         $IP route del table 123 172.16.101.0/24 dev veth1
2329         $IP rule del pref 100
2330 
2331         { kill %% && wait %%; } 2>/dev/null
2332         rm $tmp_file
2333 
2334         route_cleanup
2335 }
2336 
2337 ipv6_mangle_test()
2338 {
2339         local rc
2340 
2341         echo
2342         echo "IPv6 mangling tests"
2343 
2344         socat_check || return 1
2345         ip6tables_check || return 1
2346 
2347         route_setup
2348         sleep 2
2349 
2350         local tmp_file=$(mktemp)
2351         ip netns exec $ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
2352 
2353         # Add a FIB rule and a route that will direct our connection to the
2354         # listening server.
2355         $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2356         $IP -6 route add table 123 2001:db8:101::/64 dev veth1
2357 
2358         # Add an unreachable route to the main table that will block our
2359         # connection in case the FIB rule is not hit.
2360         $IP -6 route add unreachable 2001:db8:101::2/128
2361 
2362         run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2363         log_test $? 0 "    Connection with correct parameters"
2364 
2365         run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
2366         log_test $? 1 "    Connection with incorrect parameters"
2367 
2368         # Add a mangling rule and make sure connection is still successful.
2369         $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
2370 
2371         run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2372         log_test $? 0 "    Connection with correct parameters - mangling"
2373 
2374         # Delete the mangling rule and make sure connection is still
2375         # successful.
2376         $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
2377 
2378         run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2379         log_test $? 0 "    Connection with correct parameters - no mangling"
2380 
2381         # Verify connections were indeed successful on server side.
2382         [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2383         log_test $? 0 "    Connection check - server side"
2384 
2385         $IP -6 route del unreachable 2001:db8:101::2/128
2386         $IP -6 route del table 123 2001:db8:101::/64 dev veth1
2387         $IP -6 rule del pref 100
2388 
2389         { kill %% && wait %%; } 2>/dev/null
2390         rm $tmp_file
2391 
2392         route_cleanup
2393 }
2394 
2395 ip_neigh_get_check()
2396 {
2397         ip neigh help 2>&1 | grep -q 'ip neigh get'
2398         if [ $? -ne 0 ]; then
2399                 echo "iproute2 command does not support neigh get. Skipping test"
2400                 return 1
2401         fi
2402 
2403         return 0
2404 }
2405 
2406 ipv4_bcast_neigh_test()
2407 {
2408         local rc
2409 
2410         echo
2411         echo "IPv4 broadcast neighbour tests"
2412 
2413         ip_neigh_get_check || return 1
2414 
2415         setup
2416 
2417         set -e
2418         run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2419         run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2420 
2421         run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2422         run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2423 
2424         run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2425 
2426         run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2427         run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2428 
2429         run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2430         run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2431 
2432         run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2433         set +e
2434 
2435         run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2436         log_test $? 0 "Resolved neighbour for broadcast address"
2437 
2438         run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2439         log_test $? 0 "Resolved neighbour for network broadcast address"
2440 
2441         run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2442         log_test $? 2 "Unresolved neighbour for broadcast address"
2443 
2444         run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2445         log_test $? 2 "Unresolved neighbour for network broadcast address"
2446 
2447         cleanup
2448 }
2449 
2450 mpath_dep_check()
2451 {
2452         if [ ! -x "$(command -v mausezahn)" ]; then
2453                 echo "mausezahn command not found. Skipping test"
2454                 return 1
2455         fi
2456 
2457         if [ ! -x "$(command -v jq)" ]; then
2458                 echo "jq command not found. Skipping test"
2459                 return 1
2460         fi
2461 
2462         if [ ! -x "$(command -v bc)" ]; then
2463                 echo "bc command not found. Skipping test"
2464                 return 1
2465         fi
2466 
2467         if [ ! -x "$(command -v perf)" ]; then
2468                 echo "perf command not found. Skipping test"
2469                 return 1
2470         fi
2471 
2472         perf list fib:* | grep -q fib_table_lookup
2473         if [ $? -ne 0 ]; then
2474                 echo "IPv4 FIB tracepoint not found. Skipping test"
2475                 return 1
2476         fi
2477 
2478         perf list fib6:* | grep -q fib6_table_lookup
2479         if [ $? -ne 0 ]; then
2480                 echo "IPv6 FIB tracepoint not found. Skipping test"
2481                 return 1
2482         fi
2483 
2484         return 0
2485 }
2486 
2487 link_stats_get()
2488 {
2489         local ns=$1; shift
2490         local dev=$1; shift
2491         local dir=$1; shift
2492         local stat=$1; shift
2493 
2494         ip -n $ns -j -s link show dev $dev \
2495                 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
2496 }
2497 
2498 list_rcv_eval()
2499 {
2500         local file=$1; shift
2501         local expected=$1; shift
2502 
2503         local count=$(tail -n 1 $file | jq '.["counter-value"] | tonumber | floor')
2504         local ratio=$(echo "scale=2; $count / $expected" | bc -l)
2505         local res=$(echo "$ratio >= 0.95" | bc)
2506         [[ $res -eq 1 ]]
2507         log_test $? 0 "Multipath route hit ratio ($ratio)"
2508 }
2509 
2510 ipv4_mpath_list_test()
2511 {
2512         echo
2513         echo "IPv4 multipath list receive tests"
2514 
2515         mpath_dep_check || return 1
2516 
2517         route_setup
2518 
2519         set -e
2520         run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2521 
2522         run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2523         run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2524         run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2525         run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2526         run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2527         run_cmd "ip -n $ns2 address add 172.16.201.1/24 dev nh1"
2528         run_cmd "ip -n $ns2 address add 172.16.202.1/24 dev nh2"
2529         run_cmd "ip -n $ns2 neigh add 172.16.201.2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2530         run_cmd "ip -n $ns2 neigh add 172.16.202.2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2531         run_cmd "ip -n $ns2 route add 203.0.113.0/24
2532                 nexthop via 172.16.201.2 nexthop via 172.16.202.2"
2533         run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.fib_multipath_hash_policy=1"
2534         run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.veth2.rp_filter=0"
2535         run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.rp_filter=0"
2536         run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.default.rp_filter=0"
2537         set +e
2538 
2539         local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2540         local tmp_file=$(mktemp)
2541         local cmd="ip netns exec $ns1 mausezahn veth1 -a own -b $dmac
2542                 -A 172.16.101.1 -B 203.0.113.1 -t udp 'sp=12345,dp=0-65535' -q"
2543 
2544         # Packets forwarded in a list using a multipath route must not reuse a
2545         # cached result so that a flow always hits the same nexthop. In other
2546         # words, the FIB lookup tracepoint needs to be triggered for every
2547         # packet.
2548         local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2549         run_cmd "perf stat -a -e fib:fib_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2550         local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2551         local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2552         list_rcv_eval $tmp_file $diff
2553 
2554         rm $tmp_file
2555         route_cleanup
2556 }
2557 
2558 ipv6_mpath_list_test()
2559 {
2560         echo
2561         echo "IPv6 multipath list receive tests"
2562 
2563         mpath_dep_check || return 1
2564 
2565         route_setup
2566 
2567         set -e
2568         run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2569 
2570         run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2571         run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2572         run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2573         run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2574         run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2575         run_cmd "ip -n $ns2 -6 address add 2001:db8:201::1/64 dev nh1"
2576         run_cmd "ip -n $ns2 -6 address add 2001:db8:202::1/64 dev nh2"
2577         run_cmd "ip -n $ns2 -6 neigh add 2001:db8:201::2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2578         run_cmd "ip -n $ns2 -6 neigh add 2001:db8:202::2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2579         run_cmd "ip -n $ns2 -6 route add 2001:db8:301::/64
2580                 nexthop via 2001:db8:201::2 nexthop via 2001:db8:202::2"
2581         run_cmd "ip netns exec $ns2 sysctl -qw net.ipv6.fib_multipath_hash_policy=1"
2582         set +e
2583 
2584         local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2585         local tmp_file=$(mktemp)
2586         local cmd="ip netns exec $ns1 mausezahn -6 veth1 -a own -b $dmac
2587                 -A 2001:db8:101::1 -B 2001:db8:301::1 -t udp 'sp=12345,dp=0-65535' -q"
2588 
2589         # Packets forwarded in a list using a multipath route must not reuse a
2590         # cached result so that a flow always hits the same nexthop. In other
2591         # words, the FIB lookup tracepoint needs to be triggered for every
2592         # packet.
2593         local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2594         run_cmd "perf stat -a -e fib6:fib6_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2595         local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2596         local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2597         list_rcv_eval $tmp_file $diff
2598 
2599         rm $tmp_file
2600         route_cleanup
2601 }
2602 
2603 ################################################################################
2604 # usage
2605 
2606 usage()
2607 {
2608         cat <<EOF
2609 usage: ${0##*/} OPTS
2610 
2611         -t <test>   Test(s) to run (default: all)
2612                     (options: $TESTS)
2613         -p          Pause on fail
2614         -P          Pause after each test before cleanup
2615         -v          verbose mode (show commands and output)
2616 EOF
2617 }
2618 
2619 ################################################################################
2620 # main
2621 
2622 trap cleanup EXIT
2623 
2624 while getopts :t:pPhv o
2625 do
2626         case $o in
2627                 t) TESTS=$OPTARG;;
2628                 p) PAUSE_ON_FAIL=yes;;
2629                 P) PAUSE=yes;;
2630                 v) VERBOSE=$(($VERBOSE + 1));;
2631                 h) usage; exit 0;;
2632                 *) usage; exit 1;;
2633         esac
2634 done
2635 
2636 PEER_CMD="ip netns exec ${PEER_NS}"
2637 
2638 # make sure we don't pause twice
2639 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2640 
2641 if [ "$(id -u)" -ne 0 ];then
2642         echo "SKIP: Need root privileges"
2643         exit $ksft_skip;
2644 fi
2645 
2646 if [ ! -x "$(command -v ip)" ]; then
2647         echo "SKIP: Could not run test without ip tool"
2648         exit $ksft_skip
2649 fi
2650 
2651 ip route help 2>&1 | grep -q fibmatch
2652 if [ $? -ne 0 ]; then
2653         echo "SKIP: iproute2 too old, missing fibmatch"
2654         exit $ksft_skip
2655 fi
2656 
2657 # start clean
2658 cleanup &> /dev/null
2659 
2660 for t in $TESTS
2661 do
2662         case $t in
2663         fib_unreg_test|unregister)      fib_unreg_test;;
2664         fib_down_test|down)             fib_down_test;;
2665         fib_carrier_test|carrier)       fib_carrier_test;;
2666         fib_rp_filter_test|rp_filter)   fib_rp_filter_test;;
2667         fib_nexthop_test|nexthop)       fib_nexthop_test;;
2668         fib_notify_test|ipv4_notify)    fib_notify_test;;
2669         fib6_notify_test|ipv6_notify)   fib6_notify_test;;
2670         fib_suppress_test|suppress)     fib_suppress_test;;
2671         ipv6_route_test|ipv6_rt)        ipv6_route_test;;
2672         ipv4_route_test|ipv4_rt)        ipv4_route_test;;
2673         ipv6_addr_metric)               ipv6_addr_metric_test;;
2674         ipv4_addr_metric)               ipv4_addr_metric_test;;
2675         ipv4_del_addr)                  ipv4_del_addr_test;;
2676         ipv6_del_addr)                  ipv6_del_addr_test;;
2677         ipv6_route_metrics)             ipv6_route_metrics_test;;
2678         ipv4_route_metrics)             ipv4_route_metrics_test;;
2679         ipv4_route_v6_gw)               ipv4_route_v6_gw_test;;
2680         ipv4_mangle)                    ipv4_mangle_test;;
2681         ipv6_mangle)                    ipv6_mangle_test;;
2682         ipv4_bcast_neigh)               ipv4_bcast_neigh_test;;
2683         fib6_gc_test|ipv6_gc)           fib6_gc_test;;
2684         ipv4_mpath_list)                ipv4_mpath_list_test;;
2685         ipv6_mpath_list)                ipv6_mpath_list_test;;
2686 
2687         help) echo "Test names: $TESTS"; exit 0;;
2688         esac
2689 done
2690 
2691 if [ "$TESTS" != "none" ]; then
2692         printf "\nTests passed: %3d\n" ${nsuccess}
2693         printf "Tests failed: %3d\n"   ${nfail}
2694 fi
2695 
2696 exit $ret

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php