1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# This test is for checking IPv4 and IPv6 FIB rules API 5 6# Kselftest framework requirement - SKIP code is 4. 7ksft_skip=4 8 9ret=0 10 11PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 12IP="ip -netns testns" 13 14RTABLE=100 15GW_IP4=192.51.100.2 16SRC_IP=192.51.100.3 17GW_IP6=2001:db8:1::2 18SRC_IP6=2001:db8:1::3 19 20DEV_ADDR=192.51.100.1 21DEV_ADDR6=2001:db8:1::1 22DEV=dummy0 23TESTS="fib_rule6 fib_rule4" 24 25log_test() 26{ 27 local rc=$1 28 local expected=$2 29 local msg="$3" 30 31 if [ ${rc} -eq ${expected} ]; then 32 nsuccess=$((nsuccess+1)) 33 printf "\n TEST: %-50s [ OK ]\n" "${msg}" 34 else 35 ret=1 36 nfail=$((nfail+1)) 37 printf "\n TEST: %-50s [FAIL]\n" "${msg}" 38 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 39 echo 40 echo "hit enter to continue, 'q' to quit" 41 read a 42 [ "$a" = "q" ] && exit 1 43 fi 44 fi 45} 46 47log_section() 48{ 49 echo 50 echo "######################################################################" 51 echo "TEST SECTION: $*" 52 echo "######################################################################" 53} 54 55setup() 56{ 57 set -e 58 ip netns add testns 59 $IP link set dev lo up 60 61 $IP link add dummy0 type dummy 62 $IP link set dev dummy0 up 63 $IP address add $DEV_ADDR/24 dev dummy0 64 $IP -6 address add $DEV_ADDR6/64 dev dummy0 65 66 set +e 67} 68 69cleanup() 70{ 71 $IP link del dev dummy0 &> /dev/null 72 ip netns del testns 73} 74 75fib_check_iproute_support() 76{ 77 ip rule help 2>&1 | grep -q $1 78 if [ $? -ne 0 ]; then 79 echo "SKIP: iproute2 iprule too old, missing $1 match" 80 return 1 81 fi 82 83 ip route get help 2>&1 | grep -q $2 84 if [ $? -ne 0 ]; then 85 echo "SKIP: iproute2 get route too old, missing $2 match" 86 return 1 87 fi 88 89 return 0 90} 91 92fib_rule6_del() 93{ 94 $IP -6 rule del $1 95 log_test $? 0 "rule6 del $1" 96} 97 98fib_rule6_del_by_pref() 99{ 100 pref=$($IP -6 rule show $1 table $RTABLE | cut -d ":" -f 1) 101 $IP -6 rule del pref $pref 102} 103 104fib_rule6_test_match_n_redirect() 105{ 106 local match="$1" 107 local getmatch="$2" 108 local description="$3" 109 110 $IP -6 rule add $match table $RTABLE 111 $IP -6 route get $GW_IP6 $getmatch | grep -q "table $RTABLE" 112 log_test $? 0 "rule6 check: $description" 113 114 fib_rule6_del_by_pref "$match" 115 log_test $? 0 "rule6 del by pref: $description" 116} 117 118fib_rule6_test_reject() 119{ 120 local match="$1" 121 local rc 122 123 $IP -6 rule add $match table $RTABLE 2>/dev/null 124 rc=$? 125 log_test $rc 2 "rule6 check: $match" 126 127 if [ $rc -eq 0 ]; then 128 $IP -6 rule del $match table $RTABLE 129 fi 130} 131 132fib_rule6_test() 133{ 134 local getmatch 135 local match 136 local cnt 137 138 # setup the fib rule redirect route 139 $IP -6 route add table $RTABLE default via $GW_IP6 dev $DEV onlink 140 141 match="oif $DEV" 142 fib_rule6_test_match_n_redirect "$match" "$match" "oif redirect to table" 143 144 match="from $SRC_IP6 iif $DEV" 145 fib_rule6_test_match_n_redirect "$match" "$match" "iif redirect to table" 146 147 # Reject dsfield (tos) options which have ECN bits set 148 for cnt in $(seq 1 3); do 149 match="dsfield $cnt" 150 fib_rule6_test_reject "$match" 151 done 152 153 # Don't take ECN bits into account when matching on dsfield 154 match="tos 0x10" 155 for cnt in "0x10" "0x11" "0x12" "0x13"; do 156 # Using option 'tos' instead of 'dsfield' as old iproute2 157 # versions don't support 'dsfield' in ip rule show. 158 getmatch="tos $cnt" 159 fib_rule6_test_match_n_redirect "$match" "$getmatch" \ 160 "$getmatch redirect to table" 161 done 162 163 match="fwmark 0x64" 164 getmatch="mark 0x64" 165 fib_rule6_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table" 166 167 fib_check_iproute_support "uidrange" "uid" 168 if [ $? -eq 0 ]; then 169 match="uidrange 100-100" 170 getmatch="uid 100" 171 fib_rule6_test_match_n_redirect "$match" "$getmatch" "uid redirect to table" 172 fi 173 174 fib_check_iproute_support "sport" "sport" 175 if [ $? -eq 0 ]; then 176 match="sport 666 dport 777" 177 fib_rule6_test_match_n_redirect "$match" "$match" "sport and dport redirect to table" 178 fi 179 180 fib_check_iproute_support "ipproto" "ipproto" 181 if [ $? -eq 0 ]; then 182 match="ipproto tcp" 183 fib_rule6_test_match_n_redirect "$match" "$match" "ipproto match" 184 fi 185 186 fib_check_iproute_support "ipproto" "ipproto" 187 if [ $? -eq 0 ]; then 188 match="ipproto ipv6-icmp" 189 fib_rule6_test_match_n_redirect "$match" "$match" "ipproto ipv6-icmp match" 190 fi 191} 192 193fib_rule4_del() 194{ 195 $IP rule del $1 196 log_test $? 0 "del $1" 197} 198 199fib_rule4_del_by_pref() 200{ 201 pref=$($IP rule show $1 table $RTABLE | cut -d ":" -f 1) 202 $IP rule del pref $pref 203} 204 205fib_rule4_test_match_n_redirect() 206{ 207 local match="$1" 208 local getmatch="$2" 209 local description="$3" 210 211 $IP rule add $match table $RTABLE 212 $IP route get $GW_IP4 $getmatch | grep -q "table $RTABLE" 213 log_test $? 0 "rule4 check: $description" 214 215 fib_rule4_del_by_pref "$match" 216 log_test $? 0 "rule4 del by pref: $description" 217} 218 219fib_rule4_test_reject() 220{ 221 local match="$1" 222 local rc 223 224 $IP rule add $match table $RTABLE 2>/dev/null 225 rc=$? 226 log_test $rc 2 "rule4 check: $match" 227 228 if [ $rc -eq 0 ]; then 229 $IP rule del $match table $RTABLE 230 fi 231} 232 233fib_rule4_test() 234{ 235 local getmatch 236 local match 237 local cnt 238 239 # setup the fib rule redirect route 240 $IP route add table $RTABLE default via $GW_IP4 dev $DEV onlink 241 242 match="oif $DEV" 243 fib_rule4_test_match_n_redirect "$match" "$match" "oif redirect to table" 244 245 # need enable forwarding and disable rp_filter temporarily as all the 246 # addresses are in the same subnet and egress device == ingress device. 247 ip netns exec testns sysctl -qw net.ipv4.ip_forward=1 248 ip netns exec testns sysctl -qw net.ipv4.conf.$DEV.rp_filter=0 249 match="from $SRC_IP iif $DEV" 250 fib_rule4_test_match_n_redirect "$match" "$match" "iif redirect to table" 251 ip netns exec testns sysctl -qw net.ipv4.ip_forward=0 252 253 # Reject dsfield (tos) options which have ECN bits set 254 for cnt in $(seq 1 3); do 255 match="dsfield $cnt" 256 fib_rule4_test_reject "$match" 257 done 258 259 # Don't take ECN bits into account when matching on dsfield 260 match="tos 0x10" 261 for cnt in "0x10" "0x11" "0x12" "0x13"; do 262 # Using option 'tos' instead of 'dsfield' as old iproute2 263 # versions don't support 'dsfield' in ip rule show. 264 getmatch="tos $cnt" 265 fib_rule4_test_match_n_redirect "$match" "$getmatch" \ 266 "$getmatch redirect to table" 267 done 268 269 match="fwmark 0x64" 270 getmatch="mark 0x64" 271 fib_rule4_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table" 272 273 fib_check_iproute_support "uidrange" "uid" 274 if [ $? -eq 0 ]; then 275 match="uidrange 100-100" 276 getmatch="uid 100" 277 fib_rule4_test_match_n_redirect "$match" "$getmatch" "uid redirect to table" 278 fi 279 280 fib_check_iproute_support "sport" "sport" 281 if [ $? -eq 0 ]; then 282 match="sport 666 dport 777" 283 fib_rule4_test_match_n_redirect "$match" "$match" "sport and dport redirect to table" 284 fi 285 286 fib_check_iproute_support "ipproto" "ipproto" 287 if [ $? -eq 0 ]; then 288 match="ipproto tcp" 289 fib_rule4_test_match_n_redirect "$match" "$match" "ipproto tcp match" 290 fi 291 292 fib_check_iproute_support "ipproto" "ipproto" 293 if [ $? -eq 0 ]; then 294 match="ipproto icmp" 295 fib_rule4_test_match_n_redirect "$match" "$match" "ipproto icmp match" 296 fi 297} 298 299run_fibrule_tests() 300{ 301 log_section "IPv4 fib rule" 302 fib_rule4_test 303 log_section "IPv6 fib rule" 304 fib_rule6_test 305} 306 307if [ "$(id -u)" -ne 0 ];then 308 echo "SKIP: Need root privileges" 309 exit $ksft_skip 310fi 311 312if [ ! -x "$(command -v ip)" ]; then 313 echo "SKIP: Could not run test without ip tool" 314 exit $ksft_skip 315fi 316 317# start clean 318cleanup &> /dev/null 319setup 320for t in $TESTS 321do 322 case $t in 323 fib_rule6_test|fib_rule6) fib_rule6_test;; 324 fib_rule4_test|fib_rule4) fib_rule4_test;; 325 326 help) echo "Test names: $TESTS"; exit 0;; 327 328 esac 329done 330cleanup 331 332if [ "$TESTS" != "none" ]; then 333 printf "\nTests passed: %3d\n" ${nsuccess} 334 printf "Tests failed: %3d\n" ${nfail} 335fi 336 337exit $ret 338