Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jaehee Park and committed by
Jakub Kicinski
0ea7b0a4 aaa5f515

+309
+1
tools/testing/selftests/net/Makefile
··· 38 38 TEST_PROGS += vrf_strict_mode_test.sh 39 39 TEST_PROGS += arp_ndisc_evict_nocarrier.sh 40 40 TEST_PROGS += ndisc_unsolicited_na_test.sh 41 + TEST_PROGS += arp_ndisc_untracked_subnets.sh 41 42 TEST_PROGS += stress_reuseport_listen.sh 42 43 TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh 43 44 TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh
+308
tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh
··· 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