1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# This test is for checking IPv4 and IPv6 FIB rules API
5
6ret=0
7
8PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
9IP="ip -netns testns"
10
11RTABLE=100
12GW_IP4=192.51.100.2
13SRC_IP=192.51.100.3
14GW_IP6=2001:db8:1::2
15SRC_IP6=2001:db8:1::3
16
17DEV_ADDR=192.51.100.1
18DEV=dummy0
19
20log_test()
21{
22	local rc=$1
23	local expected=$2
24	local msg="$3"
25
26	if [ ${rc} -eq ${expected} ]; then
27		nsuccess=$((nsuccess+1))
28		printf "\n    TEST: %-50s  [ OK ]\n" "${msg}"
29	else
30		ret=1
31		nfail=$((nfail+1))
32		printf "\n    TEST: %-50s  [FAIL]\n" "${msg}"
33		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
34			echo
35			echo "hit enter to continue, 'q' to quit"
36			read a
37			[ "$a" = "q" ] && exit 1
38		fi
39	fi
40}
41
42log_section()
43{
44	echo
45	echo "######################################################################"
46	echo "TEST SECTION: $*"
47	echo "######################################################################"
48}
49
50setup()
51{
52	set -e
53	ip netns add testns
54	$IP link set dev lo up
55
56	$IP link add dummy0 type dummy
57	$IP link set dev dummy0 up
58	$IP address add 198.51.100.1/24 dev dummy0
59	$IP -6 address add 2001:db8:1::1/64 dev dummy0
60
61	set +e
62}
63
64cleanup()
65{
66	$IP link del dev dummy0 &> /dev/null
67	ip netns del testns
68}
69
70fib_check_iproute_support()
71{
72	ip rule help 2>&1 | grep -q $1
73	if [ $? -ne 0 ]; then
74		echo "SKIP: iproute2 iprule too old, missing $1 match"
75		return 1
76	fi
77
78	ip route get help 2>&1 | grep -q $2
79	if [ $? -ne 0 ]; then
80		echo "SKIP: iproute2 get route too old, missing $2 match"
81		return 1
82	fi
83
84	return 0
85}
86
87fib_rule6_del()
88{
89	$IP -6 rule del $1
90	log_test $? 0 "rule6 del $1"
91}
92
93fib_rule6_del_by_pref()
94{
95	pref=$($IP -6 rule show | grep "$1 lookup $TABLE" | cut -d ":" -f 1)
96	$IP -6 rule del pref $pref
97}
98
99fib_rule6_test_match_n_redirect()
100{
101	local match="$1"
102	local getmatch="$2"
103
104	$IP -6 rule add $match table $RTABLE
105	$IP -6 route get $GW_IP6 $getmatch | grep -q "table $RTABLE"
106	log_test $? 0 "rule6 check: $1"
107
108	fib_rule6_del_by_pref "$match"
109	log_test $? 0 "rule6 del by pref: $match"
110}
111
112fib_rule6_test()
113{
114	# setup the fib rule redirect route
115	$IP -6 route add table $RTABLE default via $GW_IP6 dev $DEV onlink
116
117	match="oif $DEV"
118	fib_rule6_test_match_n_redirect "$match" "$match" "oif redirect to table"
119
120	match="from $SRC_IP6 iif $DEV"
121	fib_rule6_test_match_n_redirect "$match" "$match" "iif redirect to table"
122
123	match="tos 0x10"
124	fib_rule6_test_match_n_redirect "$match" "$match" "tos redirect to table"
125
126	match="fwmark 0x64"
127	getmatch="mark 0x64"
128	fib_rule6_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table"
129
130	fib_check_iproute_support "uidrange" "uid"
131	if [ $? -eq 0 ]; then
132		match="uidrange 100-100"
133		getmatch="uid 100"
134		fib_rule6_test_match_n_redirect "$match" "$getmatch" "uid redirect to table"
135	fi
136
137	fib_check_iproute_support "sport" "sport"
138	if [ $? -eq 0 ]; then
139		match="sport 666 dport 777"
140		fib_rule6_test_match_n_redirect "$match" "$match" "sport and dport redirect to table"
141	fi
142
143	fib_check_iproute_support "ipproto" "ipproto"
144	if [ $? -eq 0 ]; then
145		match="ipproto tcp"
146		fib_rule6_test_match_n_redirect "$match" "$match" "ipproto match"
147	fi
148
149	fib_check_iproute_support "ipproto" "ipproto"
150	if [ $? -eq 0 ]; then
151		match="ipproto ipv6-icmp"
152		fib_rule6_test_match_n_redirect "$match" "$match" "ipproto ipv6-icmp match"
153	fi
154}
155
156fib_rule4_del()
157{
158	$IP rule del $1
159	log_test $? 0 "del $1"
160}
161
162fib_rule4_del_by_pref()
163{
164	pref=$($IP rule show | grep "$1 lookup $TABLE" | cut -d ":" -f 1)
165	$IP rule del pref $pref
166}
167
168fib_rule4_test_match_n_redirect()
169{
170	local match="$1"
171	local getmatch="$2"
172
173	$IP rule add $match table $RTABLE
174	$IP route get $GW_IP4 $getmatch | grep -q "table $RTABLE"
175	log_test $? 0 "rule4 check: $1"
176
177	fib_rule4_del_by_pref "$match"
178	log_test $? 0 "rule4 del by pref: $match"
179}
180
181fib_rule4_test()
182{
183	# setup the fib rule redirect route
184	$IP route add table $RTABLE default via $GW_IP4 dev $DEV onlink
185
186	match="oif $DEV"
187	fib_rule4_test_match_n_redirect "$match" "$match" "oif redirect to table"
188
189	match="from $SRC_IP iif $DEV"
190	fib_rule4_test_match_n_redirect "$match" "$match" "iif redirect to table"
191
192	match="tos 0x10"
193	fib_rule4_test_match_n_redirect "$match" "$match" "tos redirect to table"
194
195	match="fwmark 0x64"
196	getmatch="mark 0x64"
197	fib_rule4_test_match_n_redirect "$match" "$getmatch" "fwmark redirect to table"
198
199	fib_check_iproute_support "uidrange" "uid"
200	if [ $? -eq 0 ]; then
201		match="uidrange 100-100"
202		getmatch="uid 100"
203		fib_rule4_test_match_n_redirect "$match" "$getmatch" "uid redirect to table"
204	fi
205
206	fib_check_iproute_support "sport" "sport"
207	if [ $? -eq 0 ]; then
208		match="sport 666 dport 777"
209		fib_rule4_test_match_n_redirect "$match" "$match" "sport and dport redirect to table"
210	fi
211
212	fib_check_iproute_support "ipproto" "ipproto"
213	if [ $? -eq 0 ]; then
214		match="ipproto tcp"
215		fib_rule4_test_match_n_redirect "$match" "$match" "ipproto tcp match"
216	fi
217
218	fib_check_iproute_support "ipproto" "ipproto"
219	if [ $? -eq 0 ]; then
220		match="ipproto icmp"
221		fib_rule4_test_match_n_redirect "$match" "$match" "ipproto icmp match"
222	fi
223}
224
225run_fibrule_tests()
226{
227	log_section "IPv4 fib rule"
228	fib_rule4_test
229	log_section "IPv6 fib rule"
230	fib_rule6_test
231}
232
233if [ "$(id -u)" -ne 0 ];then
234	echo "SKIP: Need root privileges"
235	exit 0
236fi
237
238if [ ! -x "$(command -v ip)" ]; then
239	echo "SKIP: Could not run test without ip tool"
240	exit 0
241fi
242
243# start clean
244cleanup &> /dev/null
245setup
246run_fibrule_tests
247cleanup
248
249if [ "$TESTS" != "none" ]; then
250	printf "\nTests passed: %3d\n" ${nsuccess}
251	printf "Tests failed: %3d\n"   ${nfail}
252fi
253
254exit $ret
255