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