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