13f189349SFlorian Westphal#!/bin/bash
23f189349SFlorian Westphal#
33f189349SFlorian Westphal# This tests the fib expression.
43f189349SFlorian Westphal#
53f189349SFlorian Westphal# Kselftest framework requirement - SKIP code is 4.
66bc0709bSFlorian Westphal
76bc0709bSFlorian Westphalsource lib.sh
86bc0709bSFlorian Westphal
93f189349SFlorian Westphalret=0
103f189349SFlorian Westphal
113f189349SFlorian Westphaltimeout=4
123f189349SFlorian Westphal
133f189349SFlorian Westphallog_netns=$(sysctl -n net.netfilter.nf_log_all_netns)
143f189349SFlorian Westphal
153f189349SFlorian Westphalcleanup()
163f189349SFlorian Westphal{
176bc0709bSFlorian Westphal	cleanup_all_ns
183f189349SFlorian Westphal
19*9b443c76SFlorian Westphal	[ "$log_netns" -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns
203f189349SFlorian Westphal}
213f189349SFlorian Westphal
226bc0709bSFlorian Westphalchecktool "nft --version" "run test without nft"
233f189349SFlorian Westphal
246bc0709bSFlorian Westphalsetup_ns nsrouter ns1 ns2
253f189349SFlorian Westphal
263f189349SFlorian Westphaltrap cleanup EXIT
273f189349SFlorian Westphal
28*9b443c76SFlorian Westphalif dmesg | grep -q ' nft_rpfilter: ';then
293f189349SFlorian Westphal	dmesg -c | grep ' nft_rpfilter: '
303f189349SFlorian Westphal	echo "WARN: a previous test run has failed" 1>&2
313f189349SFlorian Westphalfi
323f189349SFlorian Westphal
333f189349SFlorian Westphalsysctl -q net.netfilter.nf_log_all_netns=1
343f189349SFlorian Westphal
353f189349SFlorian Westphalload_ruleset() {
363f189349SFlorian Westphal	local netns=$1
373f189349SFlorian Westphal
38*9b443c76SFlorian Westphalip netns exec "$netns" nft -f /dev/stdin <<EOF
393f189349SFlorian Westphaltable inet filter {
403f189349SFlorian Westphal	chain prerouting {
413f189349SFlorian Westphal		type filter hook prerouting priority 0; policy accept;
423f189349SFlorian Westphal	        fib saddr . iif oif missing counter log prefix "$netns nft_rpfilter: " drop
433f189349SFlorian Westphal	}
443f189349SFlorian Westphal}
453f189349SFlorian WestphalEOF
463f189349SFlorian Westphal}
473f189349SFlorian Westphal
483f189349SFlorian Westphalload_pbr_ruleset() {
493f189349SFlorian Westphal	local netns=$1
503f189349SFlorian Westphal
51*9b443c76SFlorian Westphalip netns exec "$netns" nft -f /dev/stdin <<EOF
523f189349SFlorian Westphaltable inet filter {
533f189349SFlorian Westphal	chain forward {
543f189349SFlorian Westphal		type filter hook forward priority raw;
553f189349SFlorian Westphal		fib saddr . iif oif gt 0 accept
563f189349SFlorian Westphal		log drop
573f189349SFlorian Westphal	}
583f189349SFlorian Westphal}
593f189349SFlorian WestphalEOF
603f189349SFlorian Westphal}
613f189349SFlorian Westphal
623f189349SFlorian Westphalload_ruleset_count() {
633f189349SFlorian Westphal	local netns=$1
643f189349SFlorian Westphal
65*9b443c76SFlorian Westphalip netns exec "$netns" nft -f /dev/stdin <<EOF
663f189349SFlorian Westphaltable inet filter {
673f189349SFlorian Westphal	chain prerouting {
683f189349SFlorian Westphal		type filter hook prerouting priority 0; policy accept;
693f189349SFlorian Westphal		ip daddr 1.1.1.1 fib saddr . iif oif missing counter drop
703f189349SFlorian Westphal		ip6 daddr 1c3::c01d fib saddr . iif oif missing counter drop
713f189349SFlorian Westphal	}
723f189349SFlorian Westphal}
733f189349SFlorian WestphalEOF
743f189349SFlorian Westphal}
753f189349SFlorian Westphal
763f189349SFlorian Westphalcheck_drops() {
776bc0709bSFlorian Westphal	if dmesg | grep -q ' nft_rpfilter: ';then
783f189349SFlorian Westphal		dmesg | grep ' nft_rpfilter: '
793f189349SFlorian Westphal		echo "FAIL: rpfilter did drop packets"
803f189349SFlorian Westphal		return 1
813f189349SFlorian Westphal	fi
823f189349SFlorian Westphal
833f189349SFlorian Westphal	return 0
843f189349SFlorian Westphal}
853f189349SFlorian Westphal
863f189349SFlorian Westphalcheck_fib_counter() {
873f189349SFlorian Westphal	local want=$1
883f189349SFlorian Westphal	local ns=$2
893f189349SFlorian Westphal	local address=$3
903f189349SFlorian Westphal
91*9b443c76SFlorian Westphal	if ! ip netns exec "$ns" nft list table inet filter | grep 'fib saddr . iif' | grep "$address" | grep -q "packets $want";then
923f189349SFlorian Westphal		echo "Netns $ns fib counter doesn't match expected packet count of $want for $address" 1>&2
93*9b443c76SFlorian Westphal		ip netns exec "$ns" nft list table inet filter
943f189349SFlorian Westphal		return 1
953f189349SFlorian Westphal	fi
963f189349SFlorian Westphal
97*9b443c76SFlorian Westphal	if [ "$want" -gt 0 ]; then
983f189349SFlorian Westphal		echo "PASS: fib expression did drop packets for $address"
993f189349SFlorian Westphal	fi
1003f189349SFlorian Westphal
1013f189349SFlorian Westphal	return 0
1023f189349SFlorian Westphal}
1033f189349SFlorian Westphal
104*9b443c76SFlorian Westphalload_ruleset "$nsrouter"
105*9b443c76SFlorian Westphalload_ruleset "$ns1"
106*9b443c76SFlorian Westphalload_ruleset "$ns2"
1073f189349SFlorian Westphal
1086bc0709bSFlorian Westphalif ! ip link add veth0 netns "$nsrouter" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1; then
1093f189349SFlorian Westphal    echo "SKIP: No virtual ethernet pair device support in kernel"
1103f189349SFlorian Westphal    exit $ksft_skip
1113f189349SFlorian Westphalfi
112*9b443c76SFlorian Westphalip link add veth1 netns "$nsrouter" type veth peer name eth0 netns "$ns2"
1133f189349SFlorian Westphal
114*9b443c76SFlorian Westphalip -net "$nsrouter" link set veth0 up
115*9b443c76SFlorian Westphalip -net "$nsrouter" addr add 10.0.1.1/24 dev veth0
116*9b443c76SFlorian Westphalip -net "$nsrouter" addr add dead:1::1/64 dev veth0 nodad
1173f189349SFlorian Westphal
118*9b443c76SFlorian Westphalip -net "$nsrouter" link set veth1 up
119*9b443c76SFlorian Westphalip -net "$nsrouter" addr add 10.0.2.1/24 dev veth1
120*9b443c76SFlorian Westphalip -net "$nsrouter" addr add dead:2::1/64 dev veth1 nodad
1213f189349SFlorian Westphal
122*9b443c76SFlorian Westphalip -net "$ns1" link set eth0 up
123*9b443c76SFlorian Westphalip -net "$ns2" link set eth0 up
1243f189349SFlorian Westphal
125*9b443c76SFlorian Westphalip -net "$ns1" addr add 10.0.1.99/24 dev eth0
126*9b443c76SFlorian Westphalip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad
127*9b443c76SFlorian Westphalip -net "$ns1" route add default via 10.0.1.1
128*9b443c76SFlorian Westphalip -net "$ns1" route add default via dead:1::1
1293f189349SFlorian Westphal
130*9b443c76SFlorian Westphalip -net "$ns2" addr add 10.0.2.99/24 dev eth0
131*9b443c76SFlorian Westphalip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad
132*9b443c76SFlorian Westphalip -net "$ns2" route add default via 10.0.2.1
133*9b443c76SFlorian Westphalip -net "$ns2" route add default via dead:2::1
1343f189349SFlorian Westphal
1353f189349SFlorian Westphaltest_ping() {
1363f189349SFlorian Westphal  local daddr4=$1
1373f189349SFlorian Westphal  local daddr6=$2
1383f189349SFlorian Westphal
1396bc0709bSFlorian Westphal  if ! ip netns exec "$ns1" ping -c 1 -q "$daddr4" > /dev/null; then
1403f189349SFlorian Westphal	check_drops
1413f189349SFlorian Westphal	echo "FAIL: ${ns1} cannot reach $daddr4, ret $ret" 1>&2
1423f189349SFlorian Westphal	return 1
1433f189349SFlorian Westphal  fi
1443f189349SFlorian Westphal
1456bc0709bSFlorian Westphal  if ! ip netns exec "$ns1" ping -c 1 -q "$daddr6" > /dev/null; then
1463f189349SFlorian Westphal	check_drops
1473f189349SFlorian Westphal	echo "FAIL: ${ns1} cannot reach $daddr6, ret $ret" 1>&2
1483f189349SFlorian Westphal	return 1
1493f189349SFlorian Westphal  fi
1503f189349SFlorian Westphal
1513f189349SFlorian Westphal  return 0
1523f189349SFlorian Westphal}
1533f189349SFlorian Westphal
154*9b443c76SFlorian Westphalip netns exec "$nsrouter" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
155*9b443c76SFlorian Westphalip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
156*9b443c76SFlorian Westphalip netns exec "$nsrouter" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
157*9b443c76SFlorian Westphalip netns exec "$nsrouter" sysctl net.ipv4.conf.all.rp_filter=0 > /dev/null
158*9b443c76SFlorian Westphalip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.rp_filter=0 > /dev/null
1593f189349SFlorian Westphal
1603f189349SFlorian Westphaltest_ping 10.0.2.1 dead:2::1 || exit 1
1613f189349SFlorian Westphalcheck_drops || exit 1
1623f189349SFlorian Westphal
1633f189349SFlorian Westphaltest_ping 10.0.2.99 dead:2::99 || exit 1
1643f189349SFlorian Westphalcheck_drops || exit 1
1653f189349SFlorian Westphal
1663f189349SFlorian Westphalecho "PASS: fib expression did not cause unwanted packet drops"
1673f189349SFlorian Westphal
168*9b443c76SFlorian Westphalip netns exec "$nsrouter" nft flush table inet filter
1693f189349SFlorian Westphal
170*9b443c76SFlorian Westphalip -net "$ns1" route del default
171*9b443c76SFlorian Westphalip -net "$ns1" -6 route del default
1723f189349SFlorian Westphal
173*9b443c76SFlorian Westphalip -net "$ns1" addr del 10.0.1.99/24 dev eth0
174*9b443c76SFlorian Westphalip -net "$ns1" addr del dead:1::99/64 dev eth0
1753f189349SFlorian Westphal
176*9b443c76SFlorian Westphalip -net "$ns1" addr add 10.0.2.99/24 dev eth0
1776bc0709bSFlorian Westphalip -net "$ns1" addr add dead:2::99/64 dev eth0 nodad
1783f189349SFlorian Westphal
179*9b443c76SFlorian Westphalip -net "$ns1" route add default via 10.0.2.1
180*9b443c76SFlorian Westphalip -net "$ns1" -6 route add default via dead:2::1
1813f189349SFlorian Westphal
1826bc0709bSFlorian Westphalip -net "$nsrouter" addr add dead:2::1/64 dev veth0 nodad
1833f189349SFlorian Westphal
1843f189349SFlorian Westphal# switch to ruleset that doesn't log, this time
1853f189349SFlorian Westphal# its expected that this does drop the packets.
186*9b443c76SFlorian Westphalload_ruleset_count "$nsrouter"
1873f189349SFlorian Westphal
1883f189349SFlorian Westphal# ns1 has a default route, but nsrouter does not.
1893f189349SFlorian Westphal# must not check return value, ping to 1.1.1.1 will
1903f189349SFlorian Westphal# fail.
191*9b443c76SFlorian Westphalcheck_fib_counter 0 "$nsrouter" 1.1.1.1 || exit 1
192*9b443c76SFlorian Westphalcheck_fib_counter 0 "$nsrouter" 1c3::c01d || exit 1
1933f189349SFlorian Westphal
1946bc0709bSFlorian Westphalip netns exec "$ns1" ping -W 0.5 -c 1 -q 1.1.1.1 > /dev/null
195*9b443c76SFlorian Westphalcheck_fib_counter 1 "$nsrouter" 1.1.1.1 || exit 1
1963f189349SFlorian Westphal
1976bc0709bSFlorian Westphalip netns exec "$ns1" ping -W 0.5 -i 0.1 -c 3 -q 1c3::c01d > /dev/null
198*9b443c76SFlorian Westphalcheck_fib_counter 3 "$nsrouter" 1c3::c01d || exit 1
1993f189349SFlorian Westphal
2003f189349SFlorian Westphal# delete all rules
201*9b443c76SFlorian Westphalip netns exec "$ns1" nft flush ruleset
202*9b443c76SFlorian Westphalip netns exec "$ns2" nft flush ruleset
203*9b443c76SFlorian Westphalip netns exec "$nsrouter" nft flush ruleset
2043f189349SFlorian Westphal
205*9b443c76SFlorian Westphalip -net "$ns1" addr add 10.0.1.99/24 dev eth0
2066bc0709bSFlorian Westphalip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad
2073f189349SFlorian Westphal
208*9b443c76SFlorian Westphalip -net "$ns1" addr del 10.0.2.99/24 dev eth0
209*9b443c76SFlorian Westphalip -net "$ns1" addr del dead:2::99/64 dev eth0
2103f189349SFlorian Westphal
211*9b443c76SFlorian Westphalip -net "$nsrouter" addr del dead:2::1/64 dev veth0
2123f189349SFlorian Westphal
2133f189349SFlorian Westphal# ... pbr ruleset for the router, check iif+oif.
214*9b443c76SFlorian Westphalif ! load_pbr_ruleset "$nsrouter";then
2153f189349SFlorian Westphal	echo "SKIP: Could not load fib forward ruleset"
2163f189349SFlorian Westphal	exit $ksft_skip
2173f189349SFlorian Westphalfi
2183f189349SFlorian Westphal
219*9b443c76SFlorian Westphalip -net "$nsrouter" rule add from all table 128
220*9b443c76SFlorian Westphalip -net "$nsrouter" rule add from all iif veth0 table 129
221*9b443c76SFlorian Westphalip -net "$nsrouter" route add table 128 to 10.0.1.0/24 dev veth0
222*9b443c76SFlorian Westphalip -net "$nsrouter" route add table 129 to 10.0.2.0/24 dev veth1
2233f189349SFlorian Westphal
2243f189349SFlorian Westphal# drop main ipv4 table
225*9b443c76SFlorian Westphalip -net "$nsrouter" -4 rule delete table main
2263f189349SFlorian Westphal
227*9b443c76SFlorian Westphalif ! test_ping 10.0.2.99 dead:2::99;then
228*9b443c76SFlorian Westphal	ip -net "$nsrouter" nft list ruleset
2293f189349SFlorian Westphal	echo "FAIL: fib mismatch in pbr setup"
2303f189349SFlorian Westphal	exit 1
2313f189349SFlorian Westphalfi
2323f189349SFlorian Westphal
2333f189349SFlorian Westphalecho "PASS: fib expression forward check with policy based routing"
2343f189349SFlorian Westphalexit 0
235