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