xref: /linux/tools/testing/selftests/net/ndisc_unsolicited_na_test.sh (revision 06d07429858317ded2db7986113a9e0129cd599b)
1f9a2fb73SArun Ajith S#!/bin/bash
2f9a2fb73SArun Ajith S# SPDX-License-Identifier: GPL-2.0
3f9a2fb73SArun Ajith S
43e0b8f52SArun Ajith S# This test is for the accept_untracked_na feature to
5f9a2fb73SArun Ajith S# enable RFC9131 behaviour. The following is the test-matrix.
6f9a2fb73SArun Ajith S# drop   accept  fwding                   behaviour
7f9a2fb73SArun Ajith S# ----   ------  ------  ----------------------------------------------
83e0b8f52SArun Ajith S#    1        X       X  Don't update NC
93e0b8f52SArun Ajith S#    0        0       X  Don't update NC
103e0b8f52SArun Ajith S#    0        1       0  Don't update NC
113e0b8f52SArun Ajith S#    0        1       1  Add a STALE NC entry
12f9a2fb73SArun Ajith S
13*3e05fc0cSHangbin Liusource lib.sh
14f9a2fb73SArun Ajith Sret=0
15f9a2fb73SArun Ajith S
16f9a2fb73SArun Ajith SPAUSE_ON_FAIL=no
17f9a2fb73SArun Ajith SPAUSE=no
18f9a2fb73SArun Ajith S
19f9a2fb73SArun Ajith SHOST_INTF="veth-host"
20f9a2fb73SArun Ajith SROUTER_INTF="veth-router"
21f9a2fb73SArun Ajith S
22f9a2fb73SArun Ajith SROUTER_ADDR="2000:20::1"
23f9a2fb73SArun Ajith SHOST_ADDR="2000:20::2"
24f9a2fb73SArun Ajith SSUBNET_WIDTH=64
25f9a2fb73SArun Ajith SROUTER_ADDR_WITH_MASK="${ROUTER_ADDR}/${SUBNET_WIDTH}"
26f9a2fb73SArun Ajith SHOST_ADDR_WITH_MASK="${HOST_ADDR}/${SUBNET_WIDTH}"
27f9a2fb73SArun Ajith S
28f9a2fb73SArun Ajith Stcpdump_stdout=
29f9a2fb73SArun Ajith Stcpdump_stderr=
30f9a2fb73SArun Ajith S
31f9a2fb73SArun Ajith Slog_test()
32f9a2fb73SArun Ajith S{
33f9a2fb73SArun Ajith S	local rc=$1
34f9a2fb73SArun Ajith S	local expected=$2
35f9a2fb73SArun Ajith S	local msg="$3"
36f9a2fb73SArun Ajith S
37f9a2fb73SArun Ajith S	if [ ${rc} -eq ${expected} ]; then
38f9a2fb73SArun Ajith S		printf "    TEST: %-60s  [ OK ]\n" "${msg}"
39f9a2fb73SArun Ajith S		nsuccess=$((nsuccess+1))
40f9a2fb73SArun Ajith S	else
41f9a2fb73SArun Ajith S		ret=1
42f9a2fb73SArun Ajith S		nfail=$((nfail+1))
43f9a2fb73SArun Ajith S		printf "    TEST: %-60s  [FAIL]\n" "${msg}"
44f9a2fb73SArun Ajith S		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
45f9a2fb73SArun Ajith S		echo
46f9a2fb73SArun Ajith S			echo "hit enter to continue, 'q' to quit"
47f9a2fb73SArun Ajith S			read a
48f9a2fb73SArun Ajith S			[ "$a" = "q" ] && exit 1
49f9a2fb73SArun Ajith S		fi
50f9a2fb73SArun Ajith S	fi
51f9a2fb73SArun Ajith S
52f9a2fb73SArun Ajith S	if [ "${PAUSE}" = "yes" ]; then
53f9a2fb73SArun Ajith S		echo
54f9a2fb73SArun Ajith S		echo "hit enter to continue, 'q' to quit"
55f9a2fb73SArun Ajith S		read a
56f9a2fb73SArun Ajith S		[ "$a" = "q" ] && exit 1
57f9a2fb73SArun Ajith S	fi
58f9a2fb73SArun Ajith S}
59f9a2fb73SArun Ajith S
60f9a2fb73SArun Ajith Ssetup()
61f9a2fb73SArun Ajith S{
62f9a2fb73SArun Ajith S	set -e
63f9a2fb73SArun Ajith S
64f9a2fb73SArun Ajith S	local drop_unsolicited_na=$1
653e0b8f52SArun Ajith S	local accept_untracked_na=$2
66f9a2fb73SArun Ajith S	local forwarding=$3
67f9a2fb73SArun Ajith S
68f9a2fb73SArun Ajith S	# Setup two namespaces and a veth tunnel across them.
69f9a2fb73SArun Ajith S	# On end of the tunnel is a router and the other end is a host.
70*3e05fc0cSHangbin Liu	setup_ns HOST_NS ROUTER_NS
71*3e05fc0cSHangbin Liu	IP_HOST="ip -6 -netns ${HOST_NS}"
72*3e05fc0cSHangbin Liu	IP_HOST_EXEC="ip netns exec ${HOST_NS}"
73*3e05fc0cSHangbin Liu	IP_ROUTER="ip -6 -netns ${ROUTER_NS}"
74*3e05fc0cSHangbin Liu	IP_ROUTER_EXEC="ip netns exec ${ROUTER_NS}"
75*3e05fc0cSHangbin Liu
76f9a2fb73SArun Ajith S	${IP_ROUTER} link add ${ROUTER_INTF} type veth \
77f9a2fb73SArun Ajith S                peer name ${HOST_INTF} netns ${HOST_NS}
78f9a2fb73SArun Ajith S
79f9a2fb73SArun Ajith S	# Enable IPv6 on both router and host, and configure static addresses.
80f9a2fb73SArun Ajith S	# The router here is the DUT
81f9a2fb73SArun Ajith S	# Setup router configuration as specified by the arguments.
82f9a2fb73SArun Ajith S	# forwarding=0 case is to check that a non-router
83f9a2fb73SArun Ajith S	# doesn't add neighbour entries.
84f9a2fb73SArun Ajith S        ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
85f9a2fb73SArun Ajith S	${IP_ROUTER_EXEC} sysctl -qw \
86f9a2fb73SArun Ajith S                ${ROUTER_CONF}.forwarding=${forwarding}
87f9a2fb73SArun Ajith S	${IP_ROUTER_EXEC} sysctl -qw \
88f9a2fb73SArun Ajith S                ${ROUTER_CONF}.drop_unsolicited_na=${drop_unsolicited_na}
89f9a2fb73SArun Ajith S	${IP_ROUTER_EXEC} sysctl -qw \
903e0b8f52SArun Ajith S                ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na}
91f9a2fb73SArun Ajith S	${IP_ROUTER_EXEC} sysctl -qw ${ROUTER_CONF}.disable_ipv6=0
92f9a2fb73SArun Ajith S	${IP_ROUTER} addr add ${ROUTER_ADDR_WITH_MASK} dev ${ROUTER_INTF}
93f9a2fb73SArun Ajith S
94f9a2fb73SArun Ajith S	# Turn on ndisc_notify on host interface so that
95f9a2fb73SArun Ajith S	# the host sends unsolicited NAs.
96f9a2fb73SArun Ajith S	HOST_CONF=net.ipv6.conf.${HOST_INTF}
97f9a2fb73SArun Ajith S	${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.ndisc_notify=1
98f9a2fb73SArun Ajith S	${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.disable_ipv6=0
99f9a2fb73SArun Ajith S	${IP_HOST} addr add ${HOST_ADDR_WITH_MASK} dev ${HOST_INTF}
100f9a2fb73SArun Ajith S
101f9a2fb73SArun Ajith S	set +e
102f9a2fb73SArun Ajith S}
103f9a2fb73SArun Ajith S
104f9a2fb73SArun Ajith Sstart_tcpdump() {
105f9a2fb73SArun Ajith S	set -e
106f9a2fb73SArun Ajith S	tcpdump_stdout=`mktemp`
107f9a2fb73SArun Ajith S	tcpdump_stderr=`mktemp`
108f9a2fb73SArun Ajith S	${IP_ROUTER_EXEC} timeout 15s \
109f9a2fb73SArun Ajith S                tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
110f9a2fb73SArun Ajith S                "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR}" \
111f9a2fb73SArun Ajith S                > ${tcpdump_stdout} 2> /dev/null
112f9a2fb73SArun Ajith S	set +e
113f9a2fb73SArun Ajith S}
114f9a2fb73SArun Ajith S
115f9a2fb73SArun Ajith Scleanup_tcpdump()
116f9a2fb73SArun Ajith S{
117f9a2fb73SArun Ajith S	set -e
118f9a2fb73SArun Ajith S	[[ ! -z  ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
119f9a2fb73SArun Ajith S	[[ ! -z  ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
120f9a2fb73SArun Ajith S	tcpdump_stdout=
121f9a2fb73SArun Ajith S	tcpdump_stderr=
122f9a2fb73SArun Ajith S	set +e
123f9a2fb73SArun Ajith S}
124f9a2fb73SArun Ajith S
125f9a2fb73SArun Ajith Scleanup()
126f9a2fb73SArun Ajith S{
127f9a2fb73SArun Ajith S	cleanup_tcpdump
128f9a2fb73SArun Ajith S	ip netns del ${HOST_NS}
129f9a2fb73SArun Ajith S	ip netns del ${ROUTER_NS}
130f9a2fb73SArun Ajith S}
131f9a2fb73SArun Ajith S
132f9a2fb73SArun Ajith Slink_up() {
133f9a2fb73SArun Ajith S	set -e
134f9a2fb73SArun Ajith S	${IP_ROUTER} link set dev ${ROUTER_INTF} up
135f9a2fb73SArun Ajith S	${IP_HOST} link set dev ${HOST_INTF} up
136f9a2fb73SArun Ajith S	set +e
137f9a2fb73SArun Ajith S}
138f9a2fb73SArun Ajith S
139f9a2fb73SArun Ajith Sverify_ndisc() {
140f9a2fb73SArun Ajith S	local drop_unsolicited_na=$1
1413e0b8f52SArun Ajith S	local accept_untracked_na=$2
142f9a2fb73SArun Ajith S	local forwarding=$3
143f9a2fb73SArun Ajith S
144f9a2fb73SArun Ajith S	neigh_show_output=$(${IP_ROUTER} neigh show \
145f9a2fb73SArun Ajith S                to ${HOST_ADDR} dev ${ROUTER_INTF} nud stale)
146f9a2fb73SArun Ajith S	if [ ${drop_unsolicited_na} -eq 0 ] && \
1473e0b8f52SArun Ajith S			[ ${accept_untracked_na} -eq 1 ] && \
148f9a2fb73SArun Ajith S			[ ${forwarding} -eq 1 ]; then
149f9a2fb73SArun Ajith S		# Neighbour entry expected to be present for 011 case
150f9a2fb73SArun Ajith S		[[ ${neigh_show_output} ]]
151f9a2fb73SArun Ajith S	else
152f9a2fb73SArun Ajith S		# Neighbour entry expected to be absent for all other cases
153f9a2fb73SArun Ajith S		[[ -z ${neigh_show_output} ]]
154f9a2fb73SArun Ajith S	fi
155f9a2fb73SArun Ajith S}
156f9a2fb73SArun Ajith S
157f9a2fb73SArun Ajith Stest_unsolicited_na_common()
158f9a2fb73SArun Ajith S{
159f9a2fb73SArun Ajith S	# Setup the test bed, but keep links down
160f9a2fb73SArun Ajith S	setup $1 $2 $3
161f9a2fb73SArun Ajith S
162f9a2fb73SArun Ajith S	# Bring the link up, wait for the NA,
163f9a2fb73SArun Ajith S	# and add a delay to ensure neighbour processing is done.
164f9a2fb73SArun Ajith S	link_up
165f9a2fb73SArun Ajith S	start_tcpdump
166f9a2fb73SArun Ajith S
167f9a2fb73SArun Ajith S	# Verify the neighbour table
168f9a2fb73SArun Ajith S	verify_ndisc $1 $2 $3
169f9a2fb73SArun Ajith S
170f9a2fb73SArun Ajith S}
171f9a2fb73SArun Ajith S
172f9a2fb73SArun Ajith Stest_unsolicited_na_combination() {
173f9a2fb73SArun Ajith S	test_unsolicited_na_common $1 $2 $3
174f9a2fb73SArun Ajith S	test_msg=("test_unsolicited_na: "
175f9a2fb73SArun Ajith S		"drop_unsolicited_na=$1 "
1763e0b8f52SArun Ajith S		"accept_untracked_na=$2 "
177f9a2fb73SArun Ajith S		"forwarding=$3")
178f9a2fb73SArun Ajith S	log_test $? 0 "${test_msg[*]}"
179f9a2fb73SArun Ajith S	cleanup
180f9a2fb73SArun Ajith S}
181f9a2fb73SArun Ajith S
182f9a2fb73SArun Ajith Stest_unsolicited_na_combinations() {
1833e0b8f52SArun Ajith S	# Args: drop_unsolicited_na accept_untracked_na forwarding
184f9a2fb73SArun Ajith S
185f9a2fb73SArun Ajith S	# Expect entry
186f9a2fb73SArun Ajith S	test_unsolicited_na_combination 0 1 1
187f9a2fb73SArun Ajith S
188f9a2fb73SArun Ajith S	# Expect no entry
189f9a2fb73SArun Ajith S	test_unsolicited_na_combination 0 0 0
190f9a2fb73SArun Ajith S	test_unsolicited_na_combination 0 0 1
191f9a2fb73SArun Ajith S	test_unsolicited_na_combination 0 1 0
192f9a2fb73SArun Ajith S	test_unsolicited_na_combination 1 0 0
193f9a2fb73SArun Ajith S	test_unsolicited_na_combination 1 0 1
194f9a2fb73SArun Ajith S	test_unsolicited_na_combination 1 1 0
195f9a2fb73SArun Ajith S	test_unsolicited_na_combination 1 1 1
196f9a2fb73SArun Ajith S}
197f9a2fb73SArun Ajith S
198f9a2fb73SArun Ajith S###############################################################################
199f9a2fb73SArun Ajith S# usage
200f9a2fb73SArun Ajith S
201f9a2fb73SArun Ajith Susage()
202f9a2fb73SArun Ajith S{
203f9a2fb73SArun Ajith S	cat <<EOF
204f9a2fb73SArun Ajith Susage: ${0##*/} OPTS
205f9a2fb73SArun Ajith S        -p          Pause on fail
206f9a2fb73SArun Ajith S        -P          Pause after each test before cleanup
207f9a2fb73SArun Ajith SEOF
208f9a2fb73SArun Ajith S}
209f9a2fb73SArun Ajith S
210f9a2fb73SArun Ajith S###############################################################################
211f9a2fb73SArun Ajith S# main
212f9a2fb73SArun Ajith S
213f9a2fb73SArun Ajith Swhile getopts :pPh o
214f9a2fb73SArun Ajith Sdo
215f9a2fb73SArun Ajith S	case $o in
216f9a2fb73SArun Ajith S		p) PAUSE_ON_FAIL=yes;;
217f9a2fb73SArun Ajith S		P) PAUSE=yes;;
218f9a2fb73SArun Ajith S		h) usage; exit 0;;
219f9a2fb73SArun Ajith S		*) usage; exit 1;;
220f9a2fb73SArun Ajith S	esac
221f9a2fb73SArun Ajith Sdone
222f9a2fb73SArun Ajith S
223f9a2fb73SArun Ajith S# make sure we don't pause twice
224f9a2fb73SArun Ajith S[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
225f9a2fb73SArun Ajith S
226f9a2fb73SArun Ajith Sif [ "$(id -u)" -ne 0 ];then
227f9a2fb73SArun Ajith S	echo "SKIP: Need root privileges"
228f9a2fb73SArun Ajith S	exit $ksft_skip;
229f9a2fb73SArun Ajith Sfi
230f9a2fb73SArun Ajith S
231f9a2fb73SArun Ajith Sif [ ! -x "$(command -v ip)" ]; then
232f9a2fb73SArun Ajith S	echo "SKIP: Could not run test without ip tool"
233f9a2fb73SArun Ajith S	exit $ksft_skip
234f9a2fb73SArun Ajith Sfi
235f9a2fb73SArun Ajith S
236f9a2fb73SArun Ajith Sif [ ! -x "$(command -v tcpdump)" ]; then
237f9a2fb73SArun Ajith S	echo "SKIP: Could not run test without tcpdump tool"
238f9a2fb73SArun Ajith S	exit $ksft_skip
239f9a2fb73SArun Ajith Sfi
240f9a2fb73SArun Ajith S
241f9a2fb73SArun Ajith S# start clean
242f9a2fb73SArun Ajith Scleanup &> /dev/null
243f9a2fb73SArun Ajith S
244f9a2fb73SArun Ajith Stest_unsolicited_na_combinations
245f9a2fb73SArun Ajith S
246f9a2fb73SArun Ajith Sprintf "\nTests passed: %3d\n" ${nsuccess}
247f9a2fb73SArun Ajith Sprintf "Tests failed: %3d\n"   ${nfail}
248f9a2fb73SArun Ajith S
249f9a2fb73SArun Ajith Sexit $ret
250