33# This tests the fib expression.
44#
55# Kselftest framework requirement - SKIP code is 4.
6+ #
7+ # 10.0.1.99 10.0.1.1 10.0.2.1 10.0.2.99
8+ # dead:1::99 dead:1::1 dead:2::1 dead:2::99
9+ # ns1 <-------> [ veth0 ] nsrouter [veth1] <-------> ns2
610
711source lib.sh
812
@@ -72,6 +76,89 @@ table inet filter {
7276EOF
7377}
7478
79+ load_type_ruleset () {
80+ local netns=$1
81+
82+ for family in ip ip6; do
83+ ip netns exec " $netns " nft -f /dev/stdin << EOF
84+ table $family filter {
85+ chain type_match_in {
86+ fib daddr type local counter comment "daddr configured on other iface"
87+ fib daddr . iif type local counter comment "daddr configured on iif"
88+ fib daddr type unicast counter comment "daddr not local"
89+ fib daddr . iif type unicast counter comment "daddr not configured on iif"
90+ }
91+
92+ chain type_match_out {
93+ fib daddr type unicast counter
94+ fib daddr . oif type unicast counter
95+ fib daddr type local counter
96+ fib daddr . oif type local counter
97+ }
98+
99+ chain prerouting {
100+ type filter hook prerouting priority 0;
101+ icmp type echo-request counter jump type_match_in
102+ icmpv6 type echo-request counter jump type_match_in
103+ }
104+
105+ chain input {
106+ type filter hook input priority 0;
107+ icmp type echo-request counter jump type_match_in
108+ icmpv6 type echo-request counter jump type_match_in
109+ }
110+
111+ chain forward {
112+ type filter hook forward priority 0;
113+ icmp type echo-request counter jump type_match_in
114+ icmpv6 type echo-request counter jump type_match_in
115+ }
116+
117+ chain output {
118+ type filter hook output priority 0;
119+ icmp type echo-request counter jump type_match_out
120+ icmpv6 type echo-request counter jump type_match_out
121+ }
122+
123+ chain postrouting {
124+ type filter hook postrouting priority 0;
125+ icmp type echo-request counter jump type_match_out
126+ icmpv6 type echo-request counter jump type_match_out
127+ }
128+ }
129+ EOF
130+ done
131+ }
132+
133+ reload_type_ruleset () {
134+ ip netns exec " $1 " nft flush table ip filter
135+ ip netns exec " $1 " nft flush table ip6 filter
136+ load_type_ruleset " $1 "
137+ }
138+
139+ check_fib_type_counter_family () {
140+ local family=" $1 "
141+ local want=" $2 "
142+ local ns=" $3 "
143+ local chain=" $4 "
144+ local what=" $5 "
145+ local errmsg=" $6 "
146+
147+ if ! ip netns exec " $ns " nft list chain " $family " filter " $chain " | grep " $what " | grep -q " packets $want " ; then
148+ echo " Netns $ns $family fib type counter doesn't match expected packet count of $want for $what $errmsg " 1>&2
149+ ip netns exec " $ns " nft list chain " $family " filter " $chain "
150+ ret=1
151+ return 1
152+ fi
153+
154+ return 0
155+ }
156+
157+ check_fib_type_counter () {
158+ check_fib_type_counter_family " ip" " $@ " || return 1
159+ check_fib_type_counter_family " ip6" " $@ " || return 1
160+ }
161+
75162load_ruleset_count () {
76163 local netns=$1
77164
@@ -90,6 +177,7 @@ check_drops() {
90177 if dmesg | grep -q ' nft_rpfilter: ' ; then
91178 dmesg | grep ' nft_rpfilter: '
92179 echo " FAIL: rpfilter did drop packets"
180+ ret=1
93181 return 1
94182 fi
95183
@@ -164,17 +252,70 @@ test_ping() {
164252 return 0
165253}
166254
255+ test_fib_type () {
256+ local notice=" $1 "
257+ local errmsg=" addr-on-if"
258+ local lret=0
259+
260+ if ! load_type_ruleset " $nsrouter " ; then
261+ echo " SKIP: Could not load fib type ruleset"
262+ [ $ret -eq 0 ] && ret=$ksft_skip
263+ return
264+ fi
265+
266+ # makes router receive packet for addresses configured on incoming
267+ # interface.
268+ test_ping 10.0.1.1 dead:1::1 || return 1
269+
270+ # expectation: triggers all 'local' in prerouting/input.
271+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr type local" " $errmsg " || lret=1
272+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr . iif type local" " $errmsg " || lret=1
273+
274+ reload_type_ruleset " $nsrouter "
275+ # makes router receive packet for address configured on a different (but local)
276+ # interface.
277+ test_ping 10.0.2.1 dead:2::1 || return 1
278+
279+ # expectation: triggers 'unicast' in prerouting/input for daddr . iif and local for 'daddr'.
280+ errmsg=" addr-on-host"
281+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr type local" " $errmsg " || lret=1
282+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr . iif type unicast" " $errmsg " || lret=1
283+
284+ reload_type_ruleset " $nsrouter "
285+ test_ping 10.0.2.99 dead:2::99 || return 1
286+ errmsg=" addr-on-otherhost"
287+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr type unicast" " $errmsg " || lret=1
288+ check_fib_type_counter 2 " $nsrouter " " type_match_in" " fib daddr . iif type unicast" " $errmsg " || lret=1
289+
290+ if [ $lret -eq 0 ]; then
291+ echo " PASS: fib expression address types match ($notice )"
292+ else
293+ echo " FAIL: fib expression address types match ($notice )"
294+ ret=1
295+ fi
296+ }
297+
167298ip netns exec " $nsrouter " sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
168299ip netns exec " $nsrouter " sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
169300ip netns exec " $nsrouter " sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
170301
171302test_ping 10.0.2.1 dead:2::1 || exit 1
172- check_drops || exit 1
303+ check_drops
173304
174305test_ping 10.0.2.99 dead:2::99 || exit 1
175- check_drops || exit 1
306+ check_drops
176307
177- echo " PASS: fib expression did not cause unwanted packet drops"
308+ [ $ret -eq 0 ] && echo " PASS: fib expression did not cause unwanted packet drops"
309+
310+ load_input_ruleset " $ns1 "
311+
312+ test_ping 127.0.0.1 ::1
313+ check_drops
314+
315+ test_ping 10.0.1.99 dead:1::99
316+ check_drops
317+
318+ [ $ret -eq 0 ] && echo " PASS: fib expression did not discard loopback packets"
178319
179320load_input_ruleset " $ns1 "
180321
@@ -234,7 +375,7 @@ ip -net "$nsrouter" addr del dead:2::1/64 dev veth0
234375# ... pbr ruleset for the router, check iif+oif.
235376if ! load_pbr_ruleset " $nsrouter " ; then
236377 echo " SKIP: Could not load fib forward ruleset"
237- exit $ksft_skip
378+ [ " $ret " -eq 0 ] && ret= $ksft_skip
238379fi
239380
240381ip -net " $nsrouter " rule add from all table 128
@@ -245,11 +386,34 @@ ip -net "$nsrouter" route add table 129 to 10.0.2.0/24 dev veth1
245386# drop main ipv4 table
246387ip -net " $nsrouter " -4 rule delete table main
247388
248- if ! test_ping 10.0.2.99 dead:2::99; then
249- ip -net " $nsrouter " nft list ruleset
250- echo " FAIL: fib mismatch in pbr setup"
251- exit 1
389+ if test_ping 10.0.2.99 dead:2::99; then
390+ echo " PASS: fib expression forward check with policy based routing"
391+ else
392+ echo " FAIL: fib expression forward check with policy based routing"
393+ ret=1
252394fi
253395
254- echo " PASS: fib expression forward check with policy based routing"
255- exit 0
396+ test_fib_type " policy routing"
397+ ip netns exec " $nsrouter " nft delete table ip filter
398+ ip netns exec " $nsrouter " nft delete table ip6 filter
399+
400+ # Un-do policy routing changes
401+ ip -net " $nsrouter " rule del from all table 128
402+ ip -net " $nsrouter " rule del from all iif veth0 table 129
403+
404+ ip -net " $nsrouter " route del table 128 to 10.0.1.0/24 dev veth0
405+ ip -net " $nsrouter " route del table 129 to 10.0.2.0/24 dev veth1
406+
407+ ip -net " $ns1 " -4 route del default
408+ ip -net " $ns1 " -6 route del default
409+
410+ ip -net " $ns1 " -4 route add default via 10.0.1.1
411+ ip -net " $ns1 " -6 route add default via dead:1::1
412+
413+ ip -net " $nsrouter " -4 rule add from all table main priority 32766
414+
415+ test_fib_type " default table"
416+ ip netns exec " $nsrouter " nft delete table ip filter
417+ ip netns exec " $nsrouter " nft delete table ip6 filter
418+
419+ exit $ret
0 commit comments