ipv4: Reject routes specifying ECN bits in rtm_tos
[linux-2.6-microblaze.git] / tools / testing / selftests / net / fib_rule_tests.sh
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.
7 ksft_skip=4
8
9 ret=0
10
11 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
12 IP="ip -netns testns"
13
14 RTABLE=100
15 GW_IP4=192.51.100.2
16 SRC_IP=192.51.100.3
17 GW_IP6=2001:db8:1::2
18 SRC_IP6=2001:db8:1::3
19
20 DEV_ADDR=192.51.100.1
21 DEV_ADDR6=2001:db8:1::1
22 DEV=dummy0
23
24 log_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
46 log_section()
47 {
48         echo
49         echo "######################################################################"
50         echo "TEST SECTION: $*"
51         echo "######################################################################"
52 }
53
54 setup()
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
68 cleanup()
69 {
70         $IP link del dev dummy0 &> /dev/null
71         ip netns del testns
72 }
73
74 fib_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
91 fib_rule6_del()
92 {
93         $IP -6 rule del $1
94         log_test $? 0 "rule6 del $1"
95 }
96
97 fib_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
103 fib_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
117 fib_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
131 fib_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
192 fib_rule4_del()
193 {
194         $IP rule del $1
195         log_test $? 0 "del $1"
196 }
197
198 fib_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
204 fib_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
218 fib_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
232 fib_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
298 run_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
306 if [ "$(id -u)" -ne 0 ];then
307         echo "SKIP: Need root privileges"
308         exit $ksft_skip
309 fi
310
311 if [ ! -x "$(command -v ip)" ]; then
312         echo "SKIP: Could not run test without ip tool"
313         exit $ksft_skip
314 fi
315
316 # start clean
317 cleanup &> /dev/null
318 setup
319 run_fibrule_tests
320 cleanup
321
322 if [ "$TESTS" != "none" ]; then
323         printf "\nTests passed: %3d\n" ${nsuccess}
324         printf "Tests failed: %3d\n"   ${nfail}
325 fi
326
327 exit $ret