Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 # This test is for the accept_untracked_na feature to
0005 # enable RFC9131 behaviour. The following is the test-matrix.
0006 # drop   accept  fwding                   behaviour
0007 # ----   ------  ------  ----------------------------------------------
0008 #    1        X       X  Don't update NC
0009 #    0        0       X  Don't update NC
0010 #    0        1       0  Don't update NC
0011 #    0        1       1  Add a STALE NC entry
0012 
0013 ret=0
0014 # Kselftest framework requirement - SKIP code is 4.
0015 ksft_skip=4
0016 
0017 PAUSE_ON_FAIL=no
0018 PAUSE=no
0019 
0020 HOST_NS="ns-host"
0021 ROUTER_NS="ns-router"
0022 
0023 HOST_INTF="veth-host"
0024 ROUTER_INTF="veth-router"
0025 
0026 ROUTER_ADDR="2000:20::1"
0027 HOST_ADDR="2000:20::2"
0028 SUBNET_WIDTH=64
0029 ROUTER_ADDR_WITH_MASK="${ROUTER_ADDR}/${SUBNET_WIDTH}"
0030 HOST_ADDR_WITH_MASK="${HOST_ADDR}/${SUBNET_WIDTH}"
0031 
0032 IP_HOST="ip -6 -netns ${HOST_NS}"
0033 IP_HOST_EXEC="ip netns exec ${HOST_NS}"
0034 IP_ROUTER="ip -6 -netns ${ROUTER_NS}"
0035 IP_ROUTER_EXEC="ip netns exec ${ROUTER_NS}"
0036 
0037 tcpdump_stdout=
0038 tcpdump_stderr=
0039 
0040 log_test()
0041 {
0042         local rc=$1
0043         local expected=$2
0044         local msg="$3"
0045 
0046         if [ ${rc} -eq ${expected} ]; then
0047                 printf "    TEST: %-60s  [ OK ]\n" "${msg}"
0048                 nsuccess=$((nsuccess+1))
0049         else
0050                 ret=1
0051                 nfail=$((nfail+1))
0052                 printf "    TEST: %-60s  [FAIL]\n" "${msg}"
0053                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0054                 echo
0055                         echo "hit enter to continue, 'q' to quit"
0056                         read a
0057                         [ "$a" = "q" ] && exit 1
0058                 fi
0059         fi
0060 
0061         if [ "${PAUSE}" = "yes" ]; then
0062                 echo
0063                 echo "hit enter to continue, 'q' to quit"
0064                 read a
0065                 [ "$a" = "q" ] && exit 1
0066         fi
0067 }
0068 
0069 setup()
0070 {
0071         set -e
0072 
0073         local drop_unsolicited_na=$1
0074         local accept_untracked_na=$2
0075         local forwarding=$3
0076 
0077         # Setup two namespaces and a veth tunnel across them.
0078         # On end of the tunnel is a router and the other end is a host.
0079         ip netns add ${HOST_NS}
0080         ip netns add ${ROUTER_NS}
0081         ${IP_ROUTER} link add ${ROUTER_INTF} type veth \
0082                 peer name ${HOST_INTF} netns ${HOST_NS}
0083 
0084         # Enable IPv6 on both router and host, and configure static addresses.
0085         # The router here is the DUT
0086         # Setup router configuration as specified by the arguments.
0087         # forwarding=0 case is to check that a non-router
0088         # doesn't add neighbour entries.
0089         ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
0090         ${IP_ROUTER_EXEC} sysctl -qw \
0091                 ${ROUTER_CONF}.forwarding=${forwarding}
0092         ${IP_ROUTER_EXEC} sysctl -qw \
0093                 ${ROUTER_CONF}.drop_unsolicited_na=${drop_unsolicited_na}
0094         ${IP_ROUTER_EXEC} sysctl -qw \
0095                 ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na}
0096         ${IP_ROUTER_EXEC} sysctl -qw ${ROUTER_CONF}.disable_ipv6=0
0097         ${IP_ROUTER} addr add ${ROUTER_ADDR_WITH_MASK} dev ${ROUTER_INTF}
0098 
0099         # Turn on ndisc_notify on host interface so that
0100         # the host sends unsolicited NAs.
0101         HOST_CONF=net.ipv6.conf.${HOST_INTF}
0102         ${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.ndisc_notify=1
0103         ${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.disable_ipv6=0
0104         ${IP_HOST} addr add ${HOST_ADDR_WITH_MASK} dev ${HOST_INTF}
0105 
0106         set +e
0107 }
0108 
0109 start_tcpdump() {
0110         set -e
0111         tcpdump_stdout=`mktemp`
0112         tcpdump_stderr=`mktemp`
0113         ${IP_ROUTER_EXEC} timeout 15s \
0114                 tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
0115                 "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR}" \
0116                 > ${tcpdump_stdout} 2> /dev/null
0117         set +e
0118 }
0119 
0120 cleanup_tcpdump()
0121 {
0122         set -e
0123         [[ ! -z  ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
0124         [[ ! -z  ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
0125         tcpdump_stdout=
0126         tcpdump_stderr=
0127         set +e
0128 }
0129 
0130 cleanup()
0131 {
0132         cleanup_tcpdump
0133         ip netns del ${HOST_NS}
0134         ip netns del ${ROUTER_NS}
0135 }
0136 
0137 link_up() {
0138         set -e
0139         ${IP_ROUTER} link set dev ${ROUTER_INTF} up
0140         ${IP_HOST} link set dev ${HOST_INTF} up
0141         set +e
0142 }
0143 
0144 verify_ndisc() {
0145         local drop_unsolicited_na=$1
0146         local accept_untracked_na=$2
0147         local forwarding=$3
0148 
0149         neigh_show_output=$(${IP_ROUTER} neigh show \
0150                 to ${HOST_ADDR} dev ${ROUTER_INTF} nud stale)
0151         if [ ${drop_unsolicited_na} -eq 0 ] && \
0152                         [ ${accept_untracked_na} -eq 1 ] && \
0153                         [ ${forwarding} -eq 1 ]; then
0154                 # Neighbour entry expected to be present for 011 case
0155                 [[ ${neigh_show_output} ]]
0156         else
0157                 # Neighbour entry expected to be absent for all other cases
0158                 [[ -z ${neigh_show_output} ]]
0159         fi
0160 }
0161 
0162 test_unsolicited_na_common()
0163 {
0164         # Setup the test bed, but keep links down
0165         setup $1 $2 $3
0166 
0167         # Bring the link up, wait for the NA,
0168         # and add a delay to ensure neighbour processing is done.
0169         link_up
0170         start_tcpdump
0171 
0172         # Verify the neighbour table
0173         verify_ndisc $1 $2 $3
0174 
0175 }
0176 
0177 test_unsolicited_na_combination() {
0178         test_unsolicited_na_common $1 $2 $3
0179         test_msg=("test_unsolicited_na: "
0180                 "drop_unsolicited_na=$1 "
0181                 "accept_untracked_na=$2 "
0182                 "forwarding=$3")
0183         log_test $? 0 "${test_msg[*]}"
0184         cleanup
0185 }
0186 
0187 test_unsolicited_na_combinations() {
0188         # Args: drop_unsolicited_na accept_untracked_na forwarding
0189 
0190         # Expect entry
0191         test_unsolicited_na_combination 0 1 1
0192 
0193         # Expect no entry
0194         test_unsolicited_na_combination 0 0 0
0195         test_unsolicited_na_combination 0 0 1
0196         test_unsolicited_na_combination 0 1 0
0197         test_unsolicited_na_combination 1 0 0
0198         test_unsolicited_na_combination 1 0 1
0199         test_unsolicited_na_combination 1 1 0
0200         test_unsolicited_na_combination 1 1 1
0201 }
0202 
0203 ###############################################################################
0204 # usage
0205 
0206 usage()
0207 {
0208         cat <<EOF
0209 usage: ${0##*/} OPTS
0210         -p          Pause on fail
0211         -P          Pause after each test before cleanup
0212 EOF
0213 }
0214 
0215 ###############################################################################
0216 # main
0217 
0218 while getopts :pPh o
0219 do
0220         case $o in
0221                 p) PAUSE_ON_FAIL=yes;;
0222                 P) PAUSE=yes;;
0223                 h) usage; exit 0;;
0224                 *) usage; exit 1;;
0225         esac
0226 done
0227 
0228 # make sure we don't pause twice
0229 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
0230 
0231 if [ "$(id -u)" -ne 0 ];then
0232         echo "SKIP: Need root privileges"
0233         exit $ksft_skip;
0234 fi
0235 
0236 if [ ! -x "$(command -v ip)" ]; then
0237         echo "SKIP: Could not run test without ip tool"
0238         exit $ksft_skip
0239 fi
0240 
0241 if [ ! -x "$(command -v tcpdump)" ]; then
0242         echo "SKIP: Could not run test without tcpdump tool"
0243         exit $ksft_skip
0244 fi
0245 
0246 # start clean
0247 cleanup &> /dev/null
0248 
0249 test_unsolicited_na_combinations
0250 
0251 printf "\nTests passed: %3d\n" ${nsuccess}
0252 printf "Tests failed: %3d\n"   ${nfail}
0253 
0254 exit $ret