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