xref: /openbmc/linux/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh (revision 1188f7f111c61394ec56beb8e30322305a8220b6)
10ea7b0a4SJaehee Park#!/bin/bash
20ea7b0a4SJaehee Park# SPDX-License-Identifier: GPL-2.0
30ea7b0a4SJaehee Park#
40ea7b0a4SJaehee Park# 2 namespaces: one host and one router. Use arping from the host to send a
50ea7b0a4SJaehee Park# garp to the router. Router accepts or ignores based on its arp_accept
60ea7b0a4SJaehee Park# or accept_untracked_na configuration.
70ea7b0a4SJaehee Park
80ea7b0a4SJaehee ParkTESTS="arp ndisc"
90ea7b0a4SJaehee Park
100ea7b0a4SJaehee ParkROUTER_NS="ns-router"
110ea7b0a4SJaehee ParkROUTER_NS_V6="ns-router-v6"
120ea7b0a4SJaehee ParkROUTER_INTF="veth-router"
130ea7b0a4SJaehee ParkROUTER_ADDR="10.0.10.1"
140ea7b0a4SJaehee ParkROUTER_ADDR_V6="2001:db8:abcd:0012::1"
150ea7b0a4SJaehee Park
160ea7b0a4SJaehee ParkHOST_NS="ns-host"
170ea7b0a4SJaehee ParkHOST_NS_V6="ns-host-v6"
180ea7b0a4SJaehee ParkHOST_INTF="veth-host"
190ea7b0a4SJaehee ParkHOST_ADDR="10.0.10.2"
200ea7b0a4SJaehee ParkHOST_ADDR_V6="2001:db8:abcd:0012::2"
210ea7b0a4SJaehee Park
220ea7b0a4SJaehee ParkSUBNET_WIDTH=24
230ea7b0a4SJaehee ParkPREFIX_WIDTH_V6=64
240ea7b0a4SJaehee Park
250ea7b0a4SJaehee Parkcleanup() {
260ea7b0a4SJaehee Park	ip netns del ${HOST_NS}
270ea7b0a4SJaehee Park	ip netns del ${ROUTER_NS}
280ea7b0a4SJaehee Park}
290ea7b0a4SJaehee Park
300ea7b0a4SJaehee Parkcleanup_v6() {
310ea7b0a4SJaehee Park	ip netns del ${HOST_NS_V6}
320ea7b0a4SJaehee Park	ip netns del ${ROUTER_NS_V6}
330ea7b0a4SJaehee Park}
340ea7b0a4SJaehee Park
350ea7b0a4SJaehee Parksetup() {
360ea7b0a4SJaehee Park	set -e
370ea7b0a4SJaehee Park	local arp_accept=$1
380ea7b0a4SJaehee Park
390ea7b0a4SJaehee Park	# Set up two namespaces
400ea7b0a4SJaehee Park	ip netns add ${ROUTER_NS}
410ea7b0a4SJaehee Park	ip netns add ${HOST_NS}
420ea7b0a4SJaehee Park
430ea7b0a4SJaehee Park	# Set up interfaces veth0 and veth1, which are pairs in separate
440ea7b0a4SJaehee Park	# namespaces. veth0 is veth-router, veth1 is veth-host.
450ea7b0a4SJaehee Park	# first, set up the inteface's link to the namespace
460ea7b0a4SJaehee Park	# then, set the interface "up"
470ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} ip link add name ${ROUTER_INTF} \
480ea7b0a4SJaehee Park		type veth peer name ${HOST_INTF}
490ea7b0a4SJaehee Park
500ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} ip link set dev ${ROUTER_INTF} up
510ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} ip link set dev ${HOST_INTF} netns ${HOST_NS}
520ea7b0a4SJaehee Park
530ea7b0a4SJaehee Park	ip netns exec ${HOST_NS} ip link set dev ${HOST_INTF} up
540ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} ip addr add ${ROUTER_ADDR}/${SUBNET_WIDTH} \
550ea7b0a4SJaehee Park		dev ${ROUTER_INTF}
560ea7b0a4SJaehee Park
570ea7b0a4SJaehee Park	ip netns exec ${HOST_NS} ip addr add ${HOST_ADDR}/${SUBNET_WIDTH} \
580ea7b0a4SJaehee Park		dev ${HOST_INTF}
590ea7b0a4SJaehee Park	ip netns exec ${HOST_NS} ip route add default via ${HOST_ADDR} \
600ea7b0a4SJaehee Park		dev ${HOST_INTF}
610ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} ip route add default via ${ROUTER_ADDR} \
620ea7b0a4SJaehee Park		dev ${ROUTER_INTF}
630ea7b0a4SJaehee Park
640ea7b0a4SJaehee Park	ROUTER_CONF=net.ipv4.conf.${ROUTER_INTF}
650ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS} sysctl -w \
660ea7b0a4SJaehee Park		${ROUTER_CONF}.arp_accept=${arp_accept} >/dev/null 2>&1
670ea7b0a4SJaehee Park	set +e
680ea7b0a4SJaehee Park}
690ea7b0a4SJaehee Park
700ea7b0a4SJaehee Parksetup_v6() {
710ea7b0a4SJaehee Park	set -e
720ea7b0a4SJaehee Park	local accept_untracked_na=$1
730ea7b0a4SJaehee Park
740ea7b0a4SJaehee Park	# Set up two namespaces
750ea7b0a4SJaehee Park	ip netns add ${ROUTER_NS_V6}
760ea7b0a4SJaehee Park	ip netns add ${HOST_NS_V6}
770ea7b0a4SJaehee Park
780ea7b0a4SJaehee Park	# Set up interfaces veth0 and veth1, which are pairs in separate
790ea7b0a4SJaehee Park	# namespaces. veth0 is veth-router, veth1 is veth-host.
800ea7b0a4SJaehee Park	# first, set up the inteface's link to the namespace
810ea7b0a4SJaehee Park	# then, set the interface "up"
820ea7b0a4SJaehee Park	ip -6 -netns ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \
830ea7b0a4SJaehee Park		type veth peer name ${HOST_INTF}
840ea7b0a4SJaehee Park
850ea7b0a4SJaehee Park	ip -6 -netns ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up
860ea7b0a4SJaehee Park	ip -6 -netns ${ROUTER_NS_V6} link set dev ${HOST_INTF} netns \
870ea7b0a4SJaehee Park		${HOST_NS_V6}
880ea7b0a4SJaehee Park
890ea7b0a4SJaehee Park	ip -6 -netns ${HOST_NS_V6} link set dev ${HOST_INTF} up
900ea7b0a4SJaehee Park	ip -6 -netns ${ROUTER_NS_V6} addr add \
910ea7b0a4SJaehee Park		${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} dev ${ROUTER_INTF} nodad
920ea7b0a4SJaehee Park
930ea7b0a4SJaehee Park	HOST_CONF=net.ipv6.conf.${HOST_INTF}
940ea7b0a4SJaehee Park	ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1
950ea7b0a4SJaehee Park	ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0
960ea7b0a4SJaehee Park	ip -6 -netns ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \
970ea7b0a4SJaehee Park		dev ${HOST_INTF}
980ea7b0a4SJaehee Park
990ea7b0a4SJaehee Park	ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
1000ea7b0a4SJaehee Park
1010ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS_V6} sysctl -w \
1020ea7b0a4SJaehee Park		${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1
1030ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS_V6} sysctl -w \
1040ea7b0a4SJaehee Park		${ROUTER_CONF}.drop_unsolicited_na=0 >/dev/null 2>&1
1050ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS_V6} sysctl -w \
1060ea7b0a4SJaehee Park		${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \
1070ea7b0a4SJaehee Park		>/dev/null 2>&1
1080ea7b0a4SJaehee Park	set +e
1090ea7b0a4SJaehee Park}
1100ea7b0a4SJaehee Park
1110ea7b0a4SJaehee Parkverify_arp() {
1120ea7b0a4SJaehee Park	local arp_accept=$1
1130ea7b0a4SJaehee Park	local same_subnet=$2
1140ea7b0a4SJaehee Park
1150ea7b0a4SJaehee Park	neigh_show_output=$(ip netns exec ${ROUTER_NS} ip neigh get \
1160ea7b0a4SJaehee Park		${HOST_ADDR} dev ${ROUTER_INTF} 2>/dev/null)
1170ea7b0a4SJaehee Park
1180ea7b0a4SJaehee Park	if [ ${arp_accept} -eq 1 ]; then
1190ea7b0a4SJaehee Park		# Neighbor entries expected
1200ea7b0a4SJaehee Park		[[ ${neigh_show_output} ]]
1210ea7b0a4SJaehee Park	elif [ ${arp_accept} -eq 2 ]; then
1220ea7b0a4SJaehee Park		if [ ${same_subnet} -eq 1 ]; then
1230ea7b0a4SJaehee Park			# Neighbor entries expected
1240ea7b0a4SJaehee Park			[[ ${neigh_show_output} ]]
1250ea7b0a4SJaehee Park		else
1260ea7b0a4SJaehee Park			[[ -z "${neigh_show_output}" ]]
1270ea7b0a4SJaehee Park		fi
1280ea7b0a4SJaehee Park	else
1290ea7b0a4SJaehee Park		[[ -z "${neigh_show_output}" ]]
1300ea7b0a4SJaehee Park	fi
1310ea7b0a4SJaehee Park }
1320ea7b0a4SJaehee Park
1330ea7b0a4SJaehee Parkarp_test_gratuitous() {
1340ea7b0a4SJaehee Park	set -e
1350ea7b0a4SJaehee Park	local arp_accept=$1
1360ea7b0a4SJaehee Park	local same_subnet=$2
1370ea7b0a4SJaehee Park
1380ea7b0a4SJaehee Park	if [ ${arp_accept} -eq 2 ]; then
1390ea7b0a4SJaehee Park		test_msg=("test_arp: "
1400ea7b0a4SJaehee Park			  "accept_arp=$1 "
1410ea7b0a4SJaehee Park			  "same_subnet=$2")
1420ea7b0a4SJaehee Park		if [ ${same_subnet} -eq 0 ]; then
1430ea7b0a4SJaehee Park			HOST_ADDR=10.0.11.3
1440ea7b0a4SJaehee Park		else
1450ea7b0a4SJaehee Park			HOST_ADDR=10.0.10.3
1460ea7b0a4SJaehee Park		fi
1470ea7b0a4SJaehee Park	else
1480ea7b0a4SJaehee Park		test_msg=("test_arp: "
1490ea7b0a4SJaehee Park			  "accept_arp=$1")
1500ea7b0a4SJaehee Park	fi
1510ea7b0a4SJaehee Park	# Supply arp_accept option to set up which sets it in sysctl
1520ea7b0a4SJaehee Park	setup ${arp_accept}
153*25a17a26SHangbin Liu	ip netns exec ${HOST_NS} arping -A -I ${HOST_INTF} -U ${HOST_ADDR} -c1 2>&1 >/dev/null
1540ea7b0a4SJaehee Park
1550ea7b0a4SJaehee Park	if verify_arp $1 $2; then
1560ea7b0a4SJaehee Park		printf "    TEST: %-60s  [ OK ]\n" "${test_msg[*]}"
1570ea7b0a4SJaehee Park	else
1580ea7b0a4SJaehee Park		printf "    TEST: %-60s  [FAIL]\n" "${test_msg[*]}"
1590ea7b0a4SJaehee Park	fi
1600ea7b0a4SJaehee Park	cleanup
1610ea7b0a4SJaehee Park	set +e
1620ea7b0a4SJaehee Park}
1630ea7b0a4SJaehee Park
1640ea7b0a4SJaehee Parkarp_test_gratuitous_combinations() {
1650ea7b0a4SJaehee Park	arp_test_gratuitous 0
1660ea7b0a4SJaehee Park	arp_test_gratuitous 1
1670ea7b0a4SJaehee Park	arp_test_gratuitous 2 0 # Second entry indicates subnet or not
1680ea7b0a4SJaehee Park	arp_test_gratuitous 2 1
1690ea7b0a4SJaehee Park}
1700ea7b0a4SJaehee Park
1710ea7b0a4SJaehee Parkcleanup_tcpdump() {
1720ea7b0a4SJaehee Park	set -e
1730ea7b0a4SJaehee Park	[[ ! -z  ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
1740ea7b0a4SJaehee Park	[[ ! -z  ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
1750ea7b0a4SJaehee Park	tcpdump_stdout=
1760ea7b0a4SJaehee Park	tcpdump_stderr=
1770ea7b0a4SJaehee Park	set +e
1780ea7b0a4SJaehee Park}
1790ea7b0a4SJaehee Park
1800ea7b0a4SJaehee Parkstart_tcpdump() {
1810ea7b0a4SJaehee Park	set -e
1820ea7b0a4SJaehee Park	tcpdump_stdout=`mktemp`
1830ea7b0a4SJaehee Park	tcpdump_stderr=`mktemp`
1840ea7b0a4SJaehee Park	ip netns exec ${ROUTER_NS_V6} timeout 15s \
1850ea7b0a4SJaehee Park		tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
1860ea7b0a4SJaehee Park		"icmp6 && icmp6[0] == 136 && src ${HOST_ADDR_V6}" \
1870ea7b0a4SJaehee Park		> ${tcpdump_stdout} 2> /dev/null
1880ea7b0a4SJaehee Park	set +e
1890ea7b0a4SJaehee Park}
1900ea7b0a4SJaehee Park
1910ea7b0a4SJaehee Parkverify_ndisc() {
1920ea7b0a4SJaehee Park	local accept_untracked_na=$1
1930ea7b0a4SJaehee Park	local same_subnet=$2
1940ea7b0a4SJaehee Park
1950ea7b0a4SJaehee Park	neigh_show_output=$(ip -6 -netns ${ROUTER_NS_V6} neigh show \
1960ea7b0a4SJaehee Park		to ${HOST_ADDR_V6} dev ${ROUTER_INTF} nud stale)
1970ea7b0a4SJaehee Park
1980ea7b0a4SJaehee Park	if [ ${accept_untracked_na} -eq 1 ]; then
1990ea7b0a4SJaehee Park		# Neighbour entry expected to be present
2000ea7b0a4SJaehee Park		[[ ${neigh_show_output} ]]
2010ea7b0a4SJaehee Park	elif [ ${accept_untracked_na} -eq 2 ]; then
2020ea7b0a4SJaehee Park		if [ ${same_subnet} -eq 1 ]; then
2030ea7b0a4SJaehee Park			[[ ${neigh_show_output} ]]
2040ea7b0a4SJaehee Park		else
2050ea7b0a4SJaehee Park			[[ -z "${neigh_show_output}" ]]
2060ea7b0a4SJaehee Park		fi
2070ea7b0a4SJaehee Park	else
2080ea7b0a4SJaehee Park		# Neighbour entry expected to be absent for all other cases
2090ea7b0a4SJaehee Park		[[ -z "${neigh_show_output}" ]]
2100ea7b0a4SJaehee Park	fi
2110ea7b0a4SJaehee Park}
2120ea7b0a4SJaehee Park
2130ea7b0a4SJaehee Parkndisc_test_untracked_advertisements() {
2140ea7b0a4SJaehee Park	set -e
2150ea7b0a4SJaehee Park	test_msg=("test_ndisc: "
2160ea7b0a4SJaehee Park		  "accept_untracked_na=$1")
2170ea7b0a4SJaehee Park
2180ea7b0a4SJaehee Park	local accept_untracked_na=$1
2190ea7b0a4SJaehee Park	local same_subnet=$2
2200ea7b0a4SJaehee Park	if [ ${accept_untracked_na} -eq 2 ]; then
2210ea7b0a4SJaehee Park		test_msg=("test_ndisc: "
2220ea7b0a4SJaehee Park			  "accept_untracked_na=$1 "
2230ea7b0a4SJaehee Park			  "same_subnet=$2")
2240ea7b0a4SJaehee Park		if [ ${same_subnet} -eq 0 ]; then
2250ea7b0a4SJaehee Park			# Not same subnet
2260ea7b0a4SJaehee Park			HOST_ADDR_V6=2000:db8:abcd:0013::4
2270ea7b0a4SJaehee Park		else
2280ea7b0a4SJaehee Park			HOST_ADDR_V6=2001:db8:abcd:0012::3
2290ea7b0a4SJaehee Park		fi
2300ea7b0a4SJaehee Park	fi
2310ea7b0a4SJaehee Park	setup_v6 $1 $2
2320ea7b0a4SJaehee Park	start_tcpdump
2330ea7b0a4SJaehee Park
2340ea7b0a4SJaehee Park	if verify_ndisc $1 $2; then
2350ea7b0a4SJaehee Park		printf "    TEST: %-60s  [ OK ]\n" "${test_msg[*]}"
2360ea7b0a4SJaehee Park	else
2370ea7b0a4SJaehee Park		printf "    TEST: %-60s  [FAIL]\n" "${test_msg[*]}"
2380ea7b0a4SJaehee Park	fi
2390ea7b0a4SJaehee Park
2400ea7b0a4SJaehee Park	cleanup_tcpdump
2410ea7b0a4SJaehee Park	cleanup_v6
2420ea7b0a4SJaehee Park	set +e
2430ea7b0a4SJaehee Park}
2440ea7b0a4SJaehee Park
2450ea7b0a4SJaehee Parkndisc_test_untracked_combinations() {
2460ea7b0a4SJaehee Park	ndisc_test_untracked_advertisements 0
2470ea7b0a4SJaehee Park	ndisc_test_untracked_advertisements 1
2480ea7b0a4SJaehee Park	ndisc_test_untracked_advertisements 2 0
2490ea7b0a4SJaehee Park	ndisc_test_untracked_advertisements 2 1
2500ea7b0a4SJaehee Park}
2510ea7b0a4SJaehee Park
2520ea7b0a4SJaehee Park################################################################################
2530ea7b0a4SJaehee Park# usage
2540ea7b0a4SJaehee Park
2550ea7b0a4SJaehee Parkusage()
2560ea7b0a4SJaehee Park{
2570ea7b0a4SJaehee Park	cat <<EOF
2580ea7b0a4SJaehee Parkusage: ${0##*/} OPTS
2590ea7b0a4SJaehee Park
2600ea7b0a4SJaehee Park	-t <test>       Test(s) to run (default: all)
2610ea7b0a4SJaehee Park			(options: $TESTS)
2620ea7b0a4SJaehee ParkEOF
2630ea7b0a4SJaehee Park}
2640ea7b0a4SJaehee Park
2650ea7b0a4SJaehee Park################################################################################
2660ea7b0a4SJaehee Park# main
2670ea7b0a4SJaehee Park
2680ea7b0a4SJaehee Parkwhile getopts ":t:h" opt; do
2690ea7b0a4SJaehee Park	case $opt in
2700ea7b0a4SJaehee Park		t) TESTS=$OPTARG;;
2710ea7b0a4SJaehee Park		h) usage; exit 0;;
2720ea7b0a4SJaehee Park		*) usage; exit 1;;
2730ea7b0a4SJaehee Park	esac
2740ea7b0a4SJaehee Parkdone
2750ea7b0a4SJaehee Park
2760ea7b0a4SJaehee Parkif [ "$(id -u)" -ne 0 ];then
2770ea7b0a4SJaehee Park	echo "SKIP: Need root privileges"
2780ea7b0a4SJaehee Park	exit $ksft_skip;
2790ea7b0a4SJaehee Parkfi
2800ea7b0a4SJaehee Park
2810ea7b0a4SJaehee Parkif [ ! -x "$(command -v ip)" ]; then
2820ea7b0a4SJaehee Park	echo "SKIP: Could not run test without ip tool"
2830ea7b0a4SJaehee Park	exit $ksft_skip
2840ea7b0a4SJaehee Parkfi
2850ea7b0a4SJaehee Park
2860ea7b0a4SJaehee Parkif [ ! -x "$(command -v tcpdump)" ]; then
2870ea7b0a4SJaehee Park	echo "SKIP: Could not run test without tcpdump tool"
2880ea7b0a4SJaehee Park	exit $ksft_skip
2890ea7b0a4SJaehee Parkfi
2900ea7b0a4SJaehee Park
2910ea7b0a4SJaehee Parkif [ ! -x "$(command -v arping)" ]; then
2920ea7b0a4SJaehee Park	echo "SKIP: Could not run test without arping tool"
2930ea7b0a4SJaehee Park	exit $ksft_skip
2940ea7b0a4SJaehee Parkfi
2950ea7b0a4SJaehee Park
2960ea7b0a4SJaehee Park# start clean
2970ea7b0a4SJaehee Parkcleanup &> /dev/null
2980ea7b0a4SJaehee Parkcleanup_v6 &> /dev/null
2990ea7b0a4SJaehee Park
3000ea7b0a4SJaehee Parkfor t in $TESTS
3010ea7b0a4SJaehee Parkdo
3020ea7b0a4SJaehee Park	case $t in
3030ea7b0a4SJaehee Park	arp_test_gratuitous_combinations|arp) arp_test_gratuitous_combinations;;
3040ea7b0a4SJaehee Park	ndisc_test_untracked_combinations|ndisc) \
3050ea7b0a4SJaehee Park		ndisc_test_untracked_combinations;;
3060ea7b0a4SJaehee Park	help) echo "Test names: $TESTS"; exit 0;;
3070ea7b0a4SJaehee Parkesac
3080ea7b0a4SJaehee Parkdone
309