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

selftests: Add a basic HSR test.

This test adds a basic HSRv0 network with 3 nodes. In its current shape
it sends and forwards packets, announcements and so merges nodes based
on MAC A/B information.
It is able to detect duplicate packets and packetloss should any occur.

Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Sebastian Andrzej Siewior and committed by
Jakub Kicinski
7d0455e9 20d3c1e9

+268
+1
tools/testing/selftests/Makefile
··· 48 48 TARGETS += net 49 49 TARGETS += net/af_unix 50 50 TARGETS += net/forwarding 51 + TARGETS += net/hsr 51 52 TARGETS += net/mptcp 52 53 TARGETS += net/openvswitch 53 54 TARGETS += netfilter
+7
tools/testing/selftests/net/hsr/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + top_srcdir = ../../../../.. 4 + 5 + TEST_PROGS := hsr_ping.sh 6 + 7 + include ../../lib.mk
+4
tools/testing/selftests/net/hsr/config
··· 1 + CONFIG_IPV6=y 2 + CONFIG_NET_SCH_NETEM=m 3 + CONFIG_HSR=y 4 + CONFIG_VETH=y
+256
tools/testing/selftests/net/hsr/hsr_ping.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + ret=0 5 + ksft_skip=4 6 + ipv6=true 7 + 8 + optstring="h4" 9 + usage() { 10 + echo "Usage: $0 [OPTION]" 11 + echo -e "\t-4: IPv4 only: disable IPv6 tests (default: test both IPv4 and IPv6)" 12 + } 13 + 14 + while getopts "$optstring" option;do 15 + case "$option" in 16 + "h") 17 + usage $0 18 + exit 0 19 + ;; 20 + "4") 21 + ipv6=false 22 + ;; 23 + "?") 24 + usage $0 25 + exit 1 26 + ;; 27 + esac 28 + done 29 + 30 + sec=$(date +%s) 31 + rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 32 + ns1="ns1-$rndh" 33 + ns2="ns2-$rndh" 34 + ns3="ns3-$rndh" 35 + 36 + cleanup() 37 + { 38 + local netns 39 + for netns in "$ns1" "$ns2" "$ns3" ;do 40 + ip netns del $netns 41 + done 42 + } 43 + 44 + ip -Version > /dev/null 2>&1 45 + if [ $? -ne 0 ];then 46 + echo "SKIP: Could not run test without ip tool" 47 + exit $ksft_skip 48 + fi 49 + 50 + trap cleanup EXIT 51 + 52 + for i in "$ns1" "$ns2" "$ns3" ;do 53 + ip netns add $i || exit $ksft_skip 54 + ip -net $i link set lo up 55 + done 56 + 57 + echo "INFO: preparing interfaces." 58 + # Three HSR nodes. Each node has one link to each of its neighbour, two links in total. 59 + # 60 + # ns1eth1 ----- ns2eth1 61 + # hsr1 hsr2 62 + # ns1eth2 ns2eth2 63 + # | | 64 + # ns3eth1 ns3eth2 65 + # \ / 66 + # hsr3 67 + # 68 + # Interfaces 69 + ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2" 70 + ip link add ns1eth2 netns "$ns1" type veth peer name ns3eth1 netns "$ns3" 71 + ip link add ns3eth2 netns "$ns3" type veth peer name ns2eth2 netns "$ns2" 72 + 73 + # HSRv0. 74 + ip -net "$ns1" link add name hsr1 type hsr slave1 ns1eth1 slave2 ns1eth2 supervision 45 version 0 proto 0 75 + ip -net "$ns2" link add name hsr2 type hsr slave1 ns2eth1 slave2 ns2eth2 supervision 45 version 0 proto 0 76 + ip -net "$ns3" link add name hsr3 type hsr slave1 ns3eth1 slave2 ns3eth2 supervision 45 version 0 proto 0 77 + 78 + # IP for HSR 79 + ip -net "$ns1" addr add 100.64.0.1/24 dev hsr1 80 + ip -net "$ns1" addr add dead:beef:1::1/64 dev hsr1 nodad 81 + ip -net "$ns2" addr add 100.64.0.2/24 dev hsr2 82 + ip -net "$ns2" addr add dead:beef:1::2/64 dev hsr2 nodad 83 + ip -net "$ns3" addr add 100.64.0.3/24 dev hsr3 84 + ip -net "$ns3" addr add dead:beef:1::3/64 dev hsr3 nodad 85 + 86 + # All Links up 87 + ip -net "$ns1" link set ns1eth1 up 88 + ip -net "$ns1" link set ns1eth2 up 89 + ip -net "$ns1" link set hsr1 up 90 + 91 + ip -net "$ns2" link set ns2eth1 up 92 + ip -net "$ns2" link set ns2eth2 up 93 + ip -net "$ns2" link set hsr2 up 94 + 95 + ip -net "$ns3" link set ns3eth1 up 96 + ip -net "$ns3" link set ns3eth2 up 97 + ip -net "$ns3" link set hsr3 up 98 + 99 + # $1: IP address 100 + is_v6() 101 + { 102 + [ -z "${1##*:*}" ] 103 + } 104 + 105 + do_ping() 106 + { 107 + local netns="$1" 108 + local connect_addr="$2" 109 + local ping_args="-q -c 2" 110 + 111 + if is_v6 "${connect_addr}"; then 112 + $ipv6 || return 0 113 + ping_args="${ping_args} -6" 114 + fi 115 + 116 + ip netns exec ${netns} ping ${ping_args} $connect_addr >/dev/null 117 + if [ $? -ne 0 ] ; then 118 + echo "$netns -> $connect_addr connectivity [ FAIL ]" 1>&2 119 + ret=1 120 + return 1 121 + fi 122 + 123 + return 0 124 + } 125 + 126 + do_ping_long() 127 + { 128 + local netns="$1" 129 + local connect_addr="$2" 130 + local ping_args="-q -c 10" 131 + 132 + if is_v6 "${connect_addr}"; then 133 + $ipv6 || return 0 134 + ping_args="${ping_args} -6" 135 + fi 136 + 137 + OUT="$(LANG=C ip netns exec ${netns} ping ${ping_args} $connect_addr | grep received)" 138 + if [ $? -ne 0 ] ; then 139 + echo "$netns -> $connect_addr ping [ FAIL ]" 1>&2 140 + ret=1 141 + return 1 142 + fi 143 + 144 + VAL="$(echo $OUT | cut -d' ' -f1-8)" 145 + if [ "$VAL" != "10 packets transmitted, 10 received, 0% packet loss," ] 146 + then 147 + echo "$netns -> $connect_addr ping TEST [ FAIL ]" 148 + echo "Expect to send and receive 10 packets and no duplicates." 149 + echo "Full message: ${OUT}." 150 + ret=1 151 + return 1 152 + fi 153 + 154 + return 0 155 + } 156 + 157 + stop_if_error() 158 + { 159 + local msg="$1" 160 + 161 + if [ ${ret} -ne 0 ]; then 162 + echo "FAIL: ${msg}" 1>&2 163 + exit ${ret} 164 + fi 165 + } 166 + 167 + 168 + echo "INFO: Initial validation ping." 169 + # Each node has to be able each one. 170 + do_ping "$ns1" 100.64.0.2 171 + do_ping "$ns2" 100.64.0.1 172 + do_ping "$ns3" 100.64.0.1 173 + stop_if_error "Initial validation failed." 174 + 175 + do_ping "$ns1" 100.64.0.3 176 + do_ping "$ns2" 100.64.0.3 177 + do_ping "$ns3" 100.64.0.2 178 + 179 + do_ping "$ns1" dead:beef:1::2 180 + do_ping "$ns1" dead:beef:1::3 181 + do_ping "$ns2" dead:beef:1::1 182 + do_ping "$ns2" dead:beef:1::2 183 + do_ping "$ns3" dead:beef:1::1 184 + do_ping "$ns3" dead:beef:1::2 185 + 186 + stop_if_error "Initial validation failed." 187 + 188 + # Wait until supervisor all supervision frames have been processed and the node 189 + # entries have been merged. Otherwise duplicate frames will be observed which is 190 + # valid at this stage. 191 + WAIT=5 192 + while [ ${WAIT} -gt 0 ] 193 + do 194 + grep 00:00:00:00:00:00 /sys/kernel/debug/hsr/hsr*/node_table 195 + if [ $? -ne 0 ] 196 + then 197 + break 198 + fi 199 + sleep 1 200 + let WAIT = WAIT - 1 201 + done 202 + 203 + # Just a safety delay in case the above check didn't handle it. 204 + sleep 1 205 + 206 + echo "INFO: Longer ping test." 207 + do_ping_long "$ns1" 100.64.0.2 208 + do_ping_long "$ns1" dead:beef:1::2 209 + do_ping_long "$ns1" 100.64.0.3 210 + do_ping_long "$ns1" dead:beef:1::3 211 + 212 + stop_if_error "Longer ping test failed." 213 + 214 + do_ping_long "$ns2" 100.64.0.1 215 + do_ping_long "$ns2" dead:beef:1::1 216 + do_ping_long "$ns2" 100.64.0.3 217 + do_ping_long "$ns2" dead:beef:1::2 218 + stop_if_error "Longer ping test failed." 219 + 220 + do_ping_long "$ns3" 100.64.0.1 221 + do_ping_long "$ns3" dead:beef:1::1 222 + do_ping_long "$ns3" 100.64.0.2 223 + do_ping_long "$ns3" dead:beef:1::2 224 + stop_if_error "Longer ping test failed." 225 + 226 + echo "INFO: Cutting one link." 227 + do_ping_long "$ns1" 100.64.0.3 & 228 + 229 + sleep 3 230 + ip -net "$ns3" link set ns3eth1 down 231 + wait 232 + 233 + ip -net "$ns3" link set ns3eth1 up 234 + 235 + stop_if_error "Failed with one link down." 236 + 237 + echo "INFO: Delay the link and drop a few packages." 238 + tc -net "$ns3" qdisc add dev ns3eth1 root netem delay 50ms 239 + tc -net "$ns2" qdisc add dev ns2eth1 root netem delay 5ms loss 25% 240 + 241 + do_ping_long "$ns1" 100.64.0.2 242 + do_ping_long "$ns1" 100.64.0.3 243 + 244 + stop_if_error "Failed with delay and packetloss." 245 + 246 + do_ping_long "$ns2" 100.64.0.1 247 + do_ping_long "$ns2" 100.64.0.3 248 + 249 + stop_if_error "Failed with delay and packetloss." 250 + 251 + do_ping_long "$ns3" 100.64.0.1 252 + do_ping_long "$ns3" 100.64.0.2 253 + stop_if_error "Failed with delay and packetloss." 254 + 255 + echo "INFO: All good." 256 + exit $ret