1#!/bin/sh
2#
3# This test is for checking rtnetlink callpaths, and get as much coverage as possible.
4#
5# set -e
6
7devdummy="test-dummy0"
8ret=0
9
10# set global exit status, but never reset nonzero one.
11check_err()
12{
13	if [ $ret -eq 0 ]; then
14		ret=$1
15	fi
16}
17
18kci_add_dummy()
19{
20	ip link add name "$devdummy" type dummy
21	check_err $?
22	ip link set "$devdummy" up
23	check_err $?
24}
25
26kci_del_dummy()
27{
28	ip link del dev "$devdummy"
29	check_err $?
30}
31
32# add a bridge with vlans on top
33kci_test_bridge()
34{
35	devbr="test-br0"
36	vlandev="testbr-vlan1"
37
38	ret=0
39	ip link add name "$devbr" type bridge
40	check_err $?
41
42	ip link set dev "$devdummy" master "$devbr"
43	check_err $?
44
45	ip link set "$devbr" up
46	check_err $?
47
48	ip link add link "$devbr" name "$vlandev" type vlan id 1
49	check_err $?
50	ip addr add dev "$vlandev" 10.200.7.23/30
51	check_err $?
52	ip -6 addr add dev "$vlandev" dead:42::1234/64
53	check_err $?
54	ip -d link > /dev/null
55	check_err $?
56	ip r s t all > /dev/null
57	check_err $?
58	ip -6 addr del dev "$vlandev" dead:42::1234/64
59	check_err $?
60
61	ip link del dev "$vlandev"
62	check_err $?
63	ip link del dev "$devbr"
64	check_err $?
65
66	if [ $ret -ne 0 ];then
67		echo "FAIL: bridge setup"
68		return 1
69	fi
70	echo "PASS: bridge setup"
71
72}
73
74kci_test_gre()
75{
76	gredev=neta
77	rem=10.42.42.1
78	loc=10.0.0.1
79
80	ret=0
81	ip tunnel add $gredev mode gre remote $rem local $loc ttl 1
82	check_err $?
83	ip link set $gredev up
84	check_err $?
85	ip addr add 10.23.7.10 dev $gredev
86	check_err $?
87	ip route add 10.23.8.0/30 dev $gredev
88	check_err $?
89	ip addr add dev "$devdummy" 10.23.7.11/24
90	check_err $?
91	ip link > /dev/null
92	check_err $?
93	ip addr > /dev/null
94	check_err $?
95	ip addr del dev "$devdummy" 10.23.7.11/24
96	check_err $?
97
98	ip link del $gredev
99	check_err $?
100
101	if [ $ret -ne 0 ];then
102		echo "FAIL: gre tunnel endpoint"
103		return 1
104	fi
105	echo "PASS: gre tunnel endpoint"
106}
107
108# tc uses rtnetlink too, for full tc testing
109# please see tools/testing/selftests/tc-testing.
110kci_test_tc()
111{
112	dev=lo
113	ret=0
114
115	tc qdisc add dev "$dev" root handle 1: htb
116	check_err $?
117	tc class add dev "$dev" parent 1: classid 1:10 htb rate 1mbit
118	check_err $?
119	tc filter add dev "$dev" parent 1:0 prio 5 handle ffe: protocol ip u32 divisor 256
120	check_err $?
121	tc filter add dev "$dev" parent 1:0 prio 5 handle ffd: protocol ip u32 divisor 256
122	check_err $?
123	tc filter add dev "$dev" parent 1:0 prio 5 handle ffc: protocol ip u32 divisor 256
124	check_err $?
125	tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32 ht ffe:2: match ip src 10.0.0.3 flowid 1:10
126	check_err $?
127	tc filter add dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:2 u32 ht ffe:2: match ip src 10.0.0.2 flowid 1:10
128	check_err $?
129	tc filter show dev "$dev" parent  1:0 > /dev/null
130	check_err $?
131	tc filter del dev "$dev" protocol ip parent 1: prio 5 handle ffe:2:3 u32
132	check_err $?
133	tc filter show dev "$dev" parent  1:0 > /dev/null
134	check_err $?
135	tc qdisc del dev "$dev" root handle 1: htb
136	check_err $?
137
138	if [ $ret -ne 0 ];then
139		echo "FAIL: tc htb hierarchy"
140		return 1
141	fi
142	echo "PASS: tc htb hierarchy"
143
144}
145
146kci_test_polrouting()
147{
148	ret=0
149	ip rule add fwmark 1 lookup 100
150	check_err $?
151	ip route add local 0.0.0.0/0 dev lo table 100
152	check_err $?
153	ip r s t all > /dev/null
154	check_err $?
155	ip rule del fwmark 1 lookup 100
156	check_err $?
157	ip route del local 0.0.0.0/0 dev lo table 100
158	check_err $?
159
160	if [ $ret -ne 0 ];then
161		echo "FAIL: policy route test"
162		return 1
163	fi
164	echo "PASS: policy routing"
165}
166
167kci_test_route_get()
168{
169	ret=0
170
171	ip route get 127.0.0.1 > /dev/null
172	check_err $?
173	ip route get 127.0.0.1 dev "$devdummy" > /dev/null
174	check_err $?
175	ip route get ::1 > /dev/null
176	check_err $?
177	ip route get fe80::1 dev "$devdummy" > /dev/null
178	check_err $?
179	ip route get 127.0.0.1 from 127.0.0.1 oif lo tos 0x1 mark 0x1 > /dev/null
180	check_err $?
181	ip route get ::1 from ::1 iif lo oif lo tos 0x1 mark 0x1 > /dev/null
182	check_err $?
183	ip addr add dev "$devdummy" 10.23.7.11/24
184	check_err $?
185	ip route get 10.23.7.11 from 10.23.7.12 iif "$devdummy" > /dev/null
186	check_err $?
187	ip addr del dev "$devdummy" 10.23.7.11/24
188	check_err $?
189
190	if [ $ret -ne 0 ];then
191		echo "FAIL: route get"
192		return 1
193	fi
194
195	echo "PASS: route get"
196}
197
198kci_test_addrlabel()
199{
200	ret=0
201
202	ip addrlabel add prefix dead::/64 dev lo label 1
203	check_err $?
204
205	ip addrlabel list |grep -q "prefix dead::/64 dev lo label 1"
206	check_err $?
207
208	ip addrlabel del prefix dead::/64 dev lo label 1 2> /dev/null
209	check_err $?
210
211	ip addrlabel add prefix dead::/64 label 1 2> /dev/null
212	check_err $?
213
214	ip addrlabel del prefix dead::/64 label 1 2> /dev/null
215	check_err $?
216
217	# concurrent add/delete
218	for i in $(seq 1 1000); do
219		ip addrlabel add prefix 1c3::/64 label 12345 2>/dev/null
220	done &
221
222	for i in $(seq 1 1000); do
223		ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
224	done
225
226	wait
227
228	ip addrlabel del prefix 1c3::/64 label 12345 2>/dev/null
229
230	if [ $ret -ne 0 ];then
231		echo "FAIL: ipv6 addrlabel"
232		return 1
233	fi
234
235	echo "PASS: ipv6 addrlabel"
236}
237
238kci_test_rtnl()
239{
240	kci_add_dummy
241	if [ $ret -ne 0 ];then
242		echo "FAIL: cannot add dummy interface"
243		return 1
244	fi
245
246	kci_test_polrouting
247	kci_test_route_get
248	kci_test_tc
249	kci_test_gre
250	kci_test_bridge
251	kci_test_addrlabel
252
253	kci_del_dummy
254}
255
256#check for needed privileges
257if [ "$(id -u)" -ne 0 ];then
258	echo "SKIP: Need root privileges"
259	exit 0
260fi
261
262for x in ip tc;do
263	$x -Version 2>/dev/null >/dev/null
264	if [ $? -ne 0 ];then
265		echo "SKIP: Could not run test without the $x tool"
266		exit 0
267	fi
268done
269
270kci_test_rtnl
271
272exit $ret
273