Skip to content

Commit 0ea7b0a

Browse files
jhpark1013kuba-moo
authored andcommitted
selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na
ipv4 arp_accept has a new option '2' to create new neighbor entries only if the src ip is in the same subnet as an address configured on the interface that received the garp message. This selftest tests all options in arp_accept. ipv6 has a sysctl endpoint, accept_untracked_na, that defines the behavior for accepting untracked neighbor advertisements. A new option similar to that of arp_accept for learning only from the same subnet is added to accept_untracked_na. This selftest tests this new feature. Signed-off-by: Jaehee Park <jhpark1013@gmail.com> Suggested-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent aaa5f51 commit 0ea7b0a

File tree

2 files changed

+309
-0
lines changed

2 files changed

+309
-0
lines changed

tools/testing/selftests/net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ TEST_PROGS += srv6_end_dt6_l3vpn_test.sh
3838
TEST_PROGS += vrf_strict_mode_test.sh
3939
TEST_PROGS += arp_ndisc_evict_nocarrier.sh
4040
TEST_PROGS += ndisc_unsolicited_na_test.sh
41+
TEST_PROGS += arp_ndisc_untracked_subnets.sh
4142
TEST_PROGS += stress_reuseport_listen.sh
4243
TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh
4344
TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
#
4+
# 2 namespaces: one host and one router. Use arping from the host to send a
5+
# garp to the router. Router accepts or ignores based on its arp_accept
6+
# or accept_untracked_na configuration.
7+
8+
TESTS="arp ndisc"
9+
10+
ROUTER_NS="ns-router"
11+
ROUTER_NS_V6="ns-router-v6"
12+
ROUTER_INTF="veth-router"
13+
ROUTER_ADDR="10.0.10.1"
14+
ROUTER_ADDR_V6="2001:db8:abcd:0012::1"
15+
16+
HOST_NS="ns-host"
17+
HOST_NS_V6="ns-host-v6"
18+
HOST_INTF="veth-host"
19+
HOST_ADDR="10.0.10.2"
20+
HOST_ADDR_V6="2001:db8:abcd:0012::2"
21+
22+
SUBNET_WIDTH=24
23+
PREFIX_WIDTH_V6=64
24+
25+
cleanup() {
26+
ip netns del ${HOST_NS}
27+
ip netns del ${ROUTER_NS}
28+
}
29+
30+
cleanup_v6() {
31+
ip netns del ${HOST_NS_V6}
32+
ip netns del ${ROUTER_NS_V6}
33+
}
34+
35+
setup() {
36+
set -e
37+
local arp_accept=$1
38+
39+
# Set up two namespaces
40+
ip netns add ${ROUTER_NS}
41+
ip netns add ${HOST_NS}
42+
43+
# Set up interfaces veth0 and veth1, which are pairs in separate
44+
# namespaces. veth0 is veth-router, veth1 is veth-host.
45+
# first, set up the inteface's link to the namespace
46+
# then, set the interface "up"
47+
ip netns exec ${ROUTER_NS} ip link add name ${ROUTER_INTF} \
48+
type veth peer name ${HOST_INTF}
49+
50+
ip netns exec ${ROUTER_NS} ip link set dev ${ROUTER_INTF} up
51+
ip netns exec ${ROUTER_NS} ip link set dev ${HOST_INTF} netns ${HOST_NS}
52+
53+
ip netns exec ${HOST_NS} ip link set dev ${HOST_INTF} up
54+
ip netns exec ${ROUTER_NS} ip addr add ${ROUTER_ADDR}/${SUBNET_WIDTH} \
55+
dev ${ROUTER_INTF}
56+
57+
ip netns exec ${HOST_NS} ip addr add ${HOST_ADDR}/${SUBNET_WIDTH} \
58+
dev ${HOST_INTF}
59+
ip netns exec ${HOST_NS} ip route add default via ${HOST_ADDR} \
60+
dev ${HOST_INTF}
61+
ip netns exec ${ROUTER_NS} ip route add default via ${ROUTER_ADDR} \
62+
dev ${ROUTER_INTF}
63+
64+
ROUTER_CONF=net.ipv4.conf.${ROUTER_INTF}
65+
ip netns exec ${ROUTER_NS} sysctl -w \
66+
${ROUTER_CONF}.arp_accept=${arp_accept} >/dev/null 2>&1
67+
set +e
68+
}
69+
70+
setup_v6() {
71+
set -e
72+
local accept_untracked_na=$1
73+
74+
# Set up two namespaces
75+
ip netns add ${ROUTER_NS_V6}
76+
ip netns add ${HOST_NS_V6}
77+
78+
# Set up interfaces veth0 and veth1, which are pairs in separate
79+
# namespaces. veth0 is veth-router, veth1 is veth-host.
80+
# first, set up the inteface's link to the namespace
81+
# then, set the interface "up"
82+
ip -6 -netns ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \
83+
type veth peer name ${HOST_INTF}
84+
85+
ip -6 -netns ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up
86+
ip -6 -netns ${ROUTER_NS_V6} link set dev ${HOST_INTF} netns \
87+
${HOST_NS_V6}
88+
89+
ip -6 -netns ${HOST_NS_V6} link set dev ${HOST_INTF} up
90+
ip -6 -netns ${ROUTER_NS_V6} addr add \
91+
${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} dev ${ROUTER_INTF} nodad
92+
93+
HOST_CONF=net.ipv6.conf.${HOST_INTF}
94+
ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1
95+
ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0
96+
ip -6 -netns ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \
97+
dev ${HOST_INTF}
98+
99+
ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
100+
101+
ip netns exec ${ROUTER_NS_V6} sysctl -w \
102+
${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1
103+
ip netns exec ${ROUTER_NS_V6} sysctl -w \
104+
${ROUTER_CONF}.drop_unsolicited_na=0 >/dev/null 2>&1
105+
ip netns exec ${ROUTER_NS_V6} sysctl -w \
106+
${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \
107+
>/dev/null 2>&1
108+
set +e
109+
}
110+
111+
verify_arp() {
112+
local arp_accept=$1
113+
local same_subnet=$2
114+
115+
neigh_show_output=$(ip netns exec ${ROUTER_NS} ip neigh get \
116+
${HOST_ADDR} dev ${ROUTER_INTF} 2>/dev/null)
117+
118+
if [ ${arp_accept} -eq 1 ]; then
119+
# Neighbor entries expected
120+
[[ ${neigh_show_output} ]]
121+
elif [ ${arp_accept} -eq 2 ]; then
122+
if [ ${same_subnet} -eq 1 ]; then
123+
# Neighbor entries expected
124+
[[ ${neigh_show_output} ]]
125+
else
126+
[[ -z "${neigh_show_output}" ]]
127+
fi
128+
else
129+
[[ -z "${neigh_show_output}" ]]
130+
fi
131+
}
132+
133+
arp_test_gratuitous() {
134+
set -e
135+
local arp_accept=$1
136+
local same_subnet=$2
137+
138+
if [ ${arp_accept} -eq 2 ]; then
139+
test_msg=("test_arp: "
140+
"accept_arp=$1 "
141+
"same_subnet=$2")
142+
if [ ${same_subnet} -eq 0 ]; then
143+
HOST_ADDR=10.0.11.3
144+
else
145+
HOST_ADDR=10.0.10.3
146+
fi
147+
else
148+
test_msg=("test_arp: "
149+
"accept_arp=$1")
150+
fi
151+
# Supply arp_accept option to set up which sets it in sysctl
152+
setup ${arp_accept}
153+
ip netns exec ${HOST_NS} arping -A -U ${HOST_ADDR} -c1 2>&1 >/dev/null
154+
155+
if verify_arp $1 $2; then
156+
printf " TEST: %-60s [ OK ]\n" "${test_msg[*]}"
157+
else
158+
printf " TEST: %-60s [FAIL]\n" "${test_msg[*]}"
159+
fi
160+
cleanup
161+
set +e
162+
}
163+
164+
arp_test_gratuitous_combinations() {
165+
arp_test_gratuitous 0
166+
arp_test_gratuitous 1
167+
arp_test_gratuitous 2 0 # Second entry indicates subnet or not
168+
arp_test_gratuitous 2 1
169+
}
170+
171+
cleanup_tcpdump() {
172+
set -e
173+
[[ ! -z ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
174+
[[ ! -z ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
175+
tcpdump_stdout=
176+
tcpdump_stderr=
177+
set +e
178+
}
179+
180+
start_tcpdump() {
181+
set -e
182+
tcpdump_stdout=`mktemp`
183+
tcpdump_stderr=`mktemp`
184+
ip netns exec ${ROUTER_NS_V6} timeout 15s \
185+
tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
186+
"icmp6 && icmp6[0] == 136 && src ${HOST_ADDR_V6}" \
187+
> ${tcpdump_stdout} 2> /dev/null
188+
set +e
189+
}
190+
191+
verify_ndisc() {
192+
local accept_untracked_na=$1
193+
local same_subnet=$2
194+
195+
neigh_show_output=$(ip -6 -netns ${ROUTER_NS_V6} neigh show \
196+
to ${HOST_ADDR_V6} dev ${ROUTER_INTF} nud stale)
197+
198+
if [ ${accept_untracked_na} -eq 1 ]; then
199+
# Neighbour entry expected to be present
200+
[[ ${neigh_show_output} ]]
201+
elif [ ${accept_untracked_na} -eq 2 ]; then
202+
if [ ${same_subnet} -eq 1 ]; then
203+
[[ ${neigh_show_output} ]]
204+
else
205+
[[ -z "${neigh_show_output}" ]]
206+
fi
207+
else
208+
# Neighbour entry expected to be absent for all other cases
209+
[[ -z "${neigh_show_output}" ]]
210+
fi
211+
}
212+
213+
ndisc_test_untracked_advertisements() {
214+
set -e
215+
test_msg=("test_ndisc: "
216+
"accept_untracked_na=$1")
217+
218+
local accept_untracked_na=$1
219+
local same_subnet=$2
220+
if [ ${accept_untracked_na} -eq 2 ]; then
221+
test_msg=("test_ndisc: "
222+
"accept_untracked_na=$1 "
223+
"same_subnet=$2")
224+
if [ ${same_subnet} -eq 0 ]; then
225+
# Not same subnet
226+
HOST_ADDR_V6=2000:db8:abcd:0013::4
227+
else
228+
HOST_ADDR_V6=2001:db8:abcd:0012::3
229+
fi
230+
fi
231+
setup_v6 $1 $2
232+
start_tcpdump
233+
234+
if verify_ndisc $1 $2; then
235+
printf " TEST: %-60s [ OK ]\n" "${test_msg[*]}"
236+
else
237+
printf " TEST: %-60s [FAIL]\n" "${test_msg[*]}"
238+
fi
239+
240+
cleanup_tcpdump
241+
cleanup_v6
242+
set +e
243+
}
244+
245+
ndisc_test_untracked_combinations() {
246+
ndisc_test_untracked_advertisements 0
247+
ndisc_test_untracked_advertisements 1
248+
ndisc_test_untracked_advertisements 2 0
249+
ndisc_test_untracked_advertisements 2 1
250+
}
251+
252+
################################################################################
253+
# usage
254+
255+
usage()
256+
{
257+
cat <<EOF
258+
usage: ${0##*/} OPTS
259+
260+
-t <test> Test(s) to run (default: all)
261+
(options: $TESTS)
262+
EOF
263+
}
264+
265+
################################################################################
266+
# main
267+
268+
while getopts ":t:h" opt; do
269+
case $opt in
270+
t) TESTS=$OPTARG;;
271+
h) usage; exit 0;;
272+
*) usage; exit 1;;
273+
esac
274+
done
275+
276+
if [ "$(id -u)" -ne 0 ];then
277+
echo "SKIP: Need root privileges"
278+
exit $ksft_skip;
279+
fi
280+
281+
if [ ! -x "$(command -v ip)" ]; then
282+
echo "SKIP: Could not run test without ip tool"
283+
exit $ksft_skip
284+
fi
285+
286+
if [ ! -x "$(command -v tcpdump)" ]; then
287+
echo "SKIP: Could not run test without tcpdump tool"
288+
exit $ksft_skip
289+
fi
290+
291+
if [ ! -x "$(command -v arping)" ]; then
292+
echo "SKIP: Could not run test without arping tool"
293+
exit $ksft_skip
294+
fi
295+
296+
# start clean
297+
cleanup &> /dev/null
298+
cleanup_v6 &> /dev/null
299+
300+
for t in $TESTS
301+
do
302+
case $t in
303+
arp_test_gratuitous_combinations|arp) arp_test_gratuitous_combinations;;
304+
ndisc_test_untracked_combinations|ndisc) \
305+
ndisc_test_untracked_combinations;;
306+
help) echo "Test names: $TESTS"; exit 0;;
307+
esac
308+
done

0 commit comments

Comments
 (0)