2 # SPDX-License-Identifier: GPL-2.0
4 # This test is for checking IPv4 and IPv6 FIB rules API
6 # Kselftest framework requirement - SKIP code is 4.
11 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
13 IP_PEER="ip -netns peerns"
23 DEV_ADDR6=2001:db8:1::1
25 TESTS="fib_rule6 fib_rule4 fib_rule6_connect fib_rule4_connect"
35 if [ ${rc} -eq ${expected} ]; then
36 nsuccess=$((nsuccess+1))
37 printf "\n TEST: %-50s [ OK ]\n" "${msg}"
41 printf "\n TEST: %-50s [FAIL]\n" "${msg}"
42 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
44 echo "hit enter to continue, 'q' to quit"
46 [ "$a" = "q" ] && exit 1
54 echo "######################################################################"
55 echo "TEST SECTION: $*"
56 echo "######################################################################"
61 if which nettest > /dev/null 2>&1; then
65 # Add the selftest directory to PATH if not already done
66 if [ "${SELFTEST_PATH}" = "" ]; then
67 SELFTEST_PATH="$(dirname $0)"
68 PATH="${PATH}:${SELFTEST_PATH}"
70 # Now retry with the new path
71 if which nettest > /dev/null 2>&1; then
75 if [ "${ret}" -eq 0 ]; then
78 echo "nettest not found (try 'make -C ${SELFTEST_PATH} nettest')"
88 $IP link set dev lo up
90 $IP link add dummy0 type dummy
91 $IP link set dev dummy0 up
92 $IP address add $DEV_ADDR/24 dev dummy0
93 $IP -6 address add $DEV_ADDR6/64 dev dummy0
100 $IP link del dev dummy0 &> /dev/null
109 $IP_PEER link set dev lo up
111 ip link add name veth0 netns testns type veth \
112 peer name veth1 netns peerns
113 $IP link set dev veth0 up
114 $IP_PEER link set dev veth1 up
116 $IP address add 192.0.2.10 peer 192.0.2.11/32 dev veth0
117 $IP_PEER address add 192.0.2.11 peer 192.0.2.10/32 dev veth1
119 $IP address add 2001:db8::10 peer 2001:db8::11/128 dev veth0 nodad
120 $IP_PEER address add 2001:db8::11 peer 2001:db8::10/128 dev veth1 nodad
122 $IP_PEER address add 198.51.100.11/32 dev lo
123 $IP route add table $RTABLE_PEER 198.51.100.11/32 via 192.0.2.11
125 $IP_PEER address add 2001:db8::1:11/128 dev lo
126 $IP route add table $RTABLE_PEER 2001:db8::1:11/128 via 2001:db8::11
133 $IP link del dev veth0
137 fib_check_iproute_support()
139 ip rule help 2>&1 | grep -q $1
140 if [ $? -ne 0 ]; then
141 echo "SKIP: iproute2 iprule too old, missing $1 match"
145 ip route get help 2>&1 | grep -q $2
146 if [ $? -ne 0 ]; then
147 echo "SKIP: iproute2 get route too old, missing $2 match"
157 log_test $? 0 "rule6 del $1"
160 fib_rule6_del_by_pref()
162 pref=$($IP -6 rule show $1 table $RTABLE | cut -d ":" -f 1)
163 $IP -6 rule del pref $pref
166 fib_rule6_test_match_n_redirect()
170 local description="$3"
172 $IP -6 rule add $match table $RTABLE
173 $IP -6 route get $GW_IP6 $getmatch | grep -q "table $RTABLE"
174 log_test $? 0 "rule6 check: $description"
176 fib_rule6_del_by_pref "$match"
177 log_test $? 0 "rule6 del by pref: $description"
180 fib_rule6_test_reject()
185 $IP -6 rule add $match table $RTABLE 2>/dev/null
187 log_test $rc 2 "rule6 check: $match"
189 if [ $rc -eq 0 ]; then
190 $IP -6 rule del $match table $RTABLE
200 # setup the fib rule redirect route
201 $IP -6 route add table $RTABLE default via $GW_IP6 dev $DEV onlink
204 fib_rule6_test_match_n_redirect "$match" "$match" "oif redirect to table"
206 match="from $SRC_IP6 iif $DEV"
207 fib_rule6_test_match_n_redirect "$match" "$match" "iif redirect to table"
209 # Reject dsfield (tos) options which have ECN bits set
210 for cnt in $(seq 1 3); do
212 fib_rule6_test_reject "$match"
215 # Don't take ECN bits into account when matching on dsfield
217 for cnt in "0x10" "0x11" "0x12" "0x13"; do
218 # Using option 'tos' instead of 'dsfield' as old iproute2
219 # versions don't support 'dsfield' in ip rule show.
221 fib_rule6_test_match_n_redirect "$match" "$getmatch" \
222 "$getmatch redirect to table"
227 fib_rule6_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table"
229 fib_check_iproute_support "uidrange" "uid"
230 if [ $? -eq 0 ]; then
231 match="uidrange 100-100"
233 fib_rule6_test_match_n_redirect "$match" "$getmatch" "uid redirect to table"
236 fib_check_iproute_support "sport" "sport"
237 if [ $? -eq 0 ]; then
238 match="sport 666 dport 777"
239 fib_rule6_test_match_n_redirect "$match" "$match" "sport and dport redirect to table"
242 fib_check_iproute_support "ipproto" "ipproto"
243 if [ $? -eq 0 ]; then
245 fib_rule6_test_match_n_redirect "$match" "$match" "ipproto match"
248 fib_check_iproute_support "ipproto" "ipproto"
249 if [ $? -eq 0 ]; then
250 match="ipproto ipv6-icmp"
251 fib_rule6_test_match_n_redirect "$match" "$match" "ipproto ipv6-icmp match"
255 # Verify that the IPV6_TCLASS option of UDPv6 and TCPv6 sockets is properly
256 # taken into account when connecting the socket and when sending packets.
257 fib_rule6_connect_test()
261 if ! check_nettest; then
262 echo "SKIP: Could not run test without nettest tool"
267 $IP -6 rule add dsfield 0x04 table $RTABLE_PEER
269 # Combine the base DS Field value (0x04) with all possible ECN values
270 # (Not-ECT: 0, ECT(1): 1, ECT(0): 2, CE: 3).
271 # The ECN bits shouldn't influence the result of the test.
272 for dsfield in 0x04 0x05 0x06 0x07; do
273 nettest -q -6 -B -t 5 -N testns -O peerns -U -D \
274 -Q "${dsfield}" -l 2001:db8::1:11 -r 2001:db8::1:11
275 log_test $? 0 "rule6 dsfield udp connect (dsfield ${dsfield})"
277 nettest -q -6 -B -t 5 -N testns -O peerns -Q "${dsfield}" \
278 -l 2001:db8::1:11 -r 2001:db8::1:11
279 log_test $? 0 "rule6 dsfield tcp connect (dsfield ${dsfield})"
282 $IP -6 rule del dsfield 0x04 table $RTABLE_PEER
289 log_test $? 0 "del $1"
292 fib_rule4_del_by_pref()
294 pref=$($IP rule show $1 table $RTABLE | cut -d ":" -f 1)
295 $IP rule del pref $pref
298 fib_rule4_test_match_n_redirect()
302 local description="$3"
304 $IP rule add $match table $RTABLE
305 $IP route get $GW_IP4 $getmatch | grep -q "table $RTABLE"
306 log_test $? 0 "rule4 check: $description"
308 fib_rule4_del_by_pref "$match"
309 log_test $? 0 "rule4 del by pref: $description"
312 fib_rule4_test_reject()
317 $IP rule add $match table $RTABLE 2>/dev/null
319 log_test $rc 2 "rule4 check: $match"
321 if [ $rc -eq 0 ]; then
322 $IP rule del $match table $RTABLE
332 # setup the fib rule redirect route
333 $IP route add table $RTABLE default via $GW_IP4 dev $DEV onlink
336 fib_rule4_test_match_n_redirect "$match" "$match" "oif redirect to table"
338 # need enable forwarding and disable rp_filter temporarily as all the
339 # addresses are in the same subnet and egress device == ingress device.
340 ip netns exec testns sysctl -qw net.ipv4.ip_forward=1
341 ip netns exec testns sysctl -qw net.ipv4.conf.$DEV.rp_filter=0
342 match="from $SRC_IP iif $DEV"
343 fib_rule4_test_match_n_redirect "$match" "$match" "iif redirect to table"
344 ip netns exec testns sysctl -qw net.ipv4.ip_forward=0
346 # Reject dsfield (tos) options which have ECN bits set
347 for cnt in $(seq 1 3); do
349 fib_rule4_test_reject "$match"
352 # Don't take ECN bits into account when matching on dsfield
354 for cnt in "0x10" "0x11" "0x12" "0x13"; do
355 # Using option 'tos' instead of 'dsfield' as old iproute2
356 # versions don't support 'dsfield' in ip rule show.
358 fib_rule4_test_match_n_redirect "$match" "$getmatch" \
359 "$getmatch redirect to table"
364 fib_rule4_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table"
366 fib_check_iproute_support "uidrange" "uid"
367 if [ $? -eq 0 ]; then
368 match="uidrange 100-100"
370 fib_rule4_test_match_n_redirect "$match" "$getmatch" "uid redirect to table"
373 fib_check_iproute_support "sport" "sport"
374 if [ $? -eq 0 ]; then
375 match="sport 666 dport 777"
376 fib_rule4_test_match_n_redirect "$match" "$match" "sport and dport redirect to table"
379 fib_check_iproute_support "ipproto" "ipproto"
380 if [ $? -eq 0 ]; then
382 fib_rule4_test_match_n_redirect "$match" "$match" "ipproto tcp match"
385 fib_check_iproute_support "ipproto" "ipproto"
386 if [ $? -eq 0 ]; then
388 fib_rule4_test_match_n_redirect "$match" "$match" "ipproto icmp match"
392 # Verify that the IP_TOS option of UDPv4 and TCPv4 sockets is properly taken
393 # into account when connecting the socket and when sending packets.
394 fib_rule4_connect_test()
398 if ! check_nettest; then
399 echo "SKIP: Could not run test without nettest tool"
404 $IP -4 rule add dsfield 0x04 table $RTABLE_PEER
406 # Combine the base DS Field value (0x04) with all possible ECN values
407 # (Not-ECT: 0, ECT(1): 1, ECT(0): 2, CE: 3).
408 # The ECN bits shouldn't influence the result of the test.
409 for dsfield in 0x04 0x05 0x06 0x07; do
410 nettest -q -B -t 5 -N testns -O peerns -D -U -Q "${dsfield}" \
411 -l 198.51.100.11 -r 198.51.100.11
412 log_test $? 0 "rule4 dsfield udp connect (dsfield ${dsfield})"
414 nettest -q -B -t 5 -N testns -O peerns -Q "${dsfield}" \
415 -l 198.51.100.11 -r 198.51.100.11
416 log_test $? 0 "rule4 dsfield tcp connect (dsfield ${dsfield})"
419 $IP -4 rule del dsfield 0x04 table $RTABLE_PEER
425 log_section "IPv4 fib rule"
427 log_section "IPv6 fib rule"
430 ################################################################################
438 -t <test> Test(s) to run (default: all)
443 ################################################################################
446 while getopts ":t:h" opt; do
454 if [ "$(id -u)" -ne 0 ];then
455 echo "SKIP: Need root privileges"
459 if [ ! -x "$(command -v ip)" ]; then
460 echo "SKIP: Could not run test without ip tool"
470 fib_rule6_test|fib_rule6) fib_rule6_test;;
471 fib_rule4_test|fib_rule4) fib_rule4_test;;
472 fib_rule6_connect_test|fib_rule6_connect) fib_rule6_connect_test;;
473 fib_rule4_connect_test|fib_rule4_connect) fib_rule4_connect_test;;
475 help) echo "Test names: $TESTS"; exit 0;;
481 if [ "$TESTS" != "none" ]; then
482 printf "\nTests passed: %3d\n" ${nsuccess}
483 printf "Tests failed: %3d\n" ${nfail}