1#!/bin/bash 2# 3# This tests the fib expression. 4# 5# Kselftest framework requirement - SKIP code is 4. 6ksft_skip=4 7ret=0 8 9sfx=$(mktemp -u "XXXXXXXX") 10ns1="ns1-$sfx" 11ns2="ns2-$sfx" 12nsrouter="nsrouter-$sfx" 13timeout=4 14 15log_netns=$(sysctl -n net.netfilter.nf_log_all_netns) 16 17cleanup() 18{ 19 ip netns del ${ns1} 20 ip netns del ${ns2} 21 ip netns del ${nsrouter} 22 23 [ $log_netns -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns 24} 25 26nft --version > /dev/null 2>&1 27if [ $? -ne 0 ];then 28 echo "SKIP: Could not run test without nft tool" 29 exit $ksft_skip 30fi 31 32ip -Version > /dev/null 2>&1 33if [ $? -ne 0 ];then 34 echo "SKIP: Could not run test without ip tool" 35 exit $ksft_skip 36fi 37 38ip netns add ${nsrouter} 39if [ $? -ne 0 ];then 40 echo "SKIP: Could not create net namespace" 41 exit $ksft_skip 42fi 43 44trap cleanup EXIT 45 46dmesg | grep -q ' nft_rpfilter: ' 47if [ $? -eq 0 ]; then 48 dmesg -c | grep ' nft_rpfilter: ' 49 echo "WARN: a previous test run has failed" 1>&2 50fi 51 52sysctl -q net.netfilter.nf_log_all_netns=1 53ip netns add ${ns1} 54ip netns add ${ns2} 55 56load_ruleset() { 57 local netns=$1 58 59ip netns exec ${netns} nft -f /dev/stdin <<EOF 60table inet filter { 61 chain prerouting { 62 type filter hook prerouting priority 0; policy accept; 63 fib saddr . iif oif missing counter log prefix "$netns nft_rpfilter: " drop 64 } 65} 66EOF 67} 68 69load_pbr_ruleset() { 70 local netns=$1 71 72ip netns exec ${netns} nft -f /dev/stdin <<EOF 73table inet filter { 74 chain forward { 75 type filter hook forward priority raw; 76 fib saddr . iif oif gt 0 accept 77 log drop 78 } 79} 80EOF 81} 82 83load_ruleset_count() { 84 local netns=$1 85 86ip netns exec ${netns} nft -f /dev/stdin <<EOF 87table inet filter { 88 chain prerouting { 89 type filter hook prerouting priority 0; policy accept; 90 ip daddr 1.1.1.1 fib saddr . iif oif missing counter drop 91 ip6 daddr 1c3::c01d fib saddr . iif oif missing counter drop 92 } 93} 94EOF 95} 96 97check_drops() { 98 dmesg | grep -q ' nft_rpfilter: ' 99 if [ $? -eq 0 ]; then 100 dmesg | grep ' nft_rpfilter: ' 101 echo "FAIL: rpfilter did drop packets" 102 return 1 103 fi 104 105 return 0 106} 107 108check_fib_counter() { 109 local want=$1 110 local ns=$2 111 local address=$3 112 113 line=$(ip netns exec ${ns} nft list table inet filter | grep 'fib saddr . iif' | grep $address | grep "packets $want" ) 114 ret=$? 115 116 if [ $ret -ne 0 ];then 117 echo "Netns $ns fib counter doesn't match expected packet count of $want for $address" 1>&2 118 ip netns exec ${ns} nft list table inet filter 119 return 1 120 fi 121 122 if [ $want -gt 0 ]; then 123 echo "PASS: fib expression did drop packets for $address" 124 fi 125 126 return 0 127} 128 129load_ruleset ${nsrouter} 130load_ruleset ${ns1} 131load_ruleset ${ns2} 132 133ip link add veth0 netns ${nsrouter} type veth peer name eth0 netns ${ns1} > /dev/null 2>&1 134if [ $? -ne 0 ];then 135 echo "SKIP: No virtual ethernet pair device support in kernel" 136 exit $ksft_skip 137fi 138ip link add veth1 netns ${nsrouter} type veth peer name eth0 netns ${ns2} 139 140ip -net ${nsrouter} link set lo up 141ip -net ${nsrouter} link set veth0 up 142ip -net ${nsrouter} addr add 10.0.1.1/24 dev veth0 143ip -net ${nsrouter} addr add dead:1::1/64 dev veth0 144 145ip -net ${nsrouter} link set veth1 up 146ip -net ${nsrouter} addr add 10.0.2.1/24 dev veth1 147ip -net ${nsrouter} addr add dead:2::1/64 dev veth1 148 149ip -net ${ns1} link set lo up 150ip -net ${ns1} link set eth0 up 151 152ip -net ${ns2} link set lo up 153ip -net ${ns2} link set eth0 up 154 155ip -net ${ns1} addr add 10.0.1.99/24 dev eth0 156ip -net ${ns1} addr add dead:1::99/64 dev eth0 157ip -net ${ns1} route add default via 10.0.1.1 158ip -net ${ns1} route add default via dead:1::1 159 160ip -net ${ns2} addr add 10.0.2.99/24 dev eth0 161ip -net ${ns2} addr add dead:2::99/64 dev eth0 162ip -net ${ns2} route add default via 10.0.2.1 163ip -net ${ns2} route add default via dead:2::1 164 165test_ping() { 166 local daddr4=$1 167 local daddr6=$2 168 169 ip netns exec ${ns1} ping -c 1 -q $daddr4 > /dev/null 170 ret=$? 171 if [ $ret -ne 0 ];then 172 check_drops 173 echo "FAIL: ${ns1} cannot reach $daddr4, ret $ret" 1>&2 174 return 1 175 fi 176 177 ip netns exec ${ns1} ping -c 3 -q $daddr6 > /dev/null 178 ret=$? 179 if [ $ret -ne 0 ];then 180 check_drops 181 echo "FAIL: ${ns1} cannot reach $daddr6, ret $ret" 1>&2 182 return 1 183 fi 184 185 return 0 186} 187 188ip netns exec ${nsrouter} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 189ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 190ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 191ip netns exec ${nsrouter} sysctl net.ipv4.conf.all.rp_filter=0 > /dev/null 192ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.rp_filter=0 > /dev/null 193 194sleep 3 195 196test_ping 10.0.2.1 dead:2::1 || exit 1 197check_drops || exit 1 198 199test_ping 10.0.2.99 dead:2::99 || exit 1 200check_drops || exit 1 201 202echo "PASS: fib expression did not cause unwanted packet drops" 203 204ip netns exec ${nsrouter} nft flush table inet filter 205 206ip -net ${ns1} route del default 207ip -net ${ns1} -6 route del default 208 209ip -net ${ns1} addr del 10.0.1.99/24 dev eth0 210ip -net ${ns1} addr del dead:1::99/64 dev eth0 211 212ip -net ${ns1} addr add 10.0.2.99/24 dev eth0 213ip -net ${ns1} addr add dead:2::99/64 dev eth0 214 215ip -net ${ns1} route add default via 10.0.2.1 216ip -net ${ns1} -6 route add default via dead:2::1 217 218ip -net ${nsrouter} addr add dead:2::1/64 dev veth0 219 220# switch to ruleset that doesn't log, this time 221# its expected that this does drop the packets. 222load_ruleset_count ${nsrouter} 223 224# ns1 has a default route, but nsrouter does not. 225# must not check return value, ping to 1.1.1.1 will 226# fail. 227check_fib_counter 0 ${nsrouter} 1.1.1.1 || exit 1 228check_fib_counter 0 ${nsrouter} 1c3::c01d || exit 1 229 230ip netns exec ${ns1} ping -c 1 -W 1 -q 1.1.1.1 > /dev/null 231check_fib_counter 1 ${nsrouter} 1.1.1.1 || exit 1 232 233sleep 2 234ip netns exec ${ns1} ping -c 3 -q 1c3::c01d > /dev/null 235check_fib_counter 3 ${nsrouter} 1c3::c01d || exit 1 236 237# delete all rules 238ip netns exec ${ns1} nft flush ruleset 239ip netns exec ${ns2} nft flush ruleset 240ip netns exec ${nsrouter} nft flush ruleset 241 242ip -net ${ns1} addr add 10.0.1.99/24 dev eth0 243ip -net ${ns1} addr add dead:1::99/64 dev eth0 244 245ip -net ${ns1} addr del 10.0.2.99/24 dev eth0 246ip -net ${ns1} addr del dead:2::99/64 dev eth0 247 248ip -net ${nsrouter} addr del dead:2::1/64 dev veth0 249 250# ... pbr ruleset for the router, check iif+oif. 251load_pbr_ruleset ${nsrouter} 252if [ $? -ne 0 ] ; then 253 echo "SKIP: Could not load fib forward ruleset" 254 exit $ksft_skip 255fi 256 257ip -net ${nsrouter} rule add from all table 128 258ip -net ${nsrouter} rule add from all iif veth0 table 129 259ip -net ${nsrouter} route add table 128 to 10.0.1.0/24 dev veth0 260ip -net ${nsrouter} route add table 129 to 10.0.2.0/24 dev veth1 261 262# drop main ipv4 table 263ip -net ${nsrouter} -4 rule delete table main 264 265test_ping 10.0.2.99 dead:2::99 266if [ $? -ne 0 ] ; then 267 ip -net ${nsrouter} nft list ruleset 268 echo "FAIL: fib mismatch in pbr setup" 269 exit 1 270fi 271 272echo "PASS: fib expression forward check with policy based routing" 273exit 0 274