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