1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# shellcheck disable=SC2329 4 5source ../lib.sh 6 7ALL_TESTS=" 8 test_clean_hsrv0 9 test_cut_link_hsrv0 10 test_packet_loss_hsrv0 11 test_high_packet_loss_hsrv0 12 test_reordering_hsrv0 13 14 test_clean_hsrv1 15 test_cut_link_hsrv1 16 test_packet_loss_hsrv1 17 test_high_packet_loss_hsrv1 18 test_reordering_hsrv1 19 20 test_clean_prp 21 test_cut_link_prp 22 test_packet_loss_prp 23 test_high_packet_loss_prp 24 test_reordering_prp 25" 26 27# The tests are running ping for 5sec with a relatively short interval in 28# different scenarios with faulty links (cut links, packet loss, delay, 29# reordering) that should be recoverable by HSR/PRP. The ping interval (10ms) 30# is short enough that the base delay (50ms) leads to a queue in the netem 31# qdiscs which is needed for reordering. 32 33setup_hsr_topo() 34{ 35 # Three HSR nodes in a ring, every node has a LAN A interface connected 36 # to the LAN B interface of the next node. 37 # 38 # node1 node2 39 # 40 # vethA -------- vethB 41 # hsr1 hsr2 42 # vethB vethA 43 # \ / 44 # vethA vethB 45 # hsr3 46 # 47 # node3 48 49 local ver="$1" 50 51 setup_ns node1 node2 node3 52 53 # veth links 54 # shellcheck disable=SC2154 # variables assigned by setup_ns 55 ip link add vethA netns "$node1" type veth peer name vethB netns "$node2" 56 # shellcheck disable=SC2154 # variables assigned by setup_ns 57 ip link add vethA netns "$node2" type veth peer name vethB netns "$node3" 58 ip link add vethA netns "$node3" type veth peer name vethB netns "$node1" 59 60 # MAC addresses (not needed for HSR operation, but helps with debugging) 61 ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA 62 ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB 63 64 ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA 65 ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB 66 67 ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA 68 ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB 69 70 # HSR interfaces 71 ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \ 72 slave1 vethA slave2 vethB supervision 45 73 ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \ 74 slave1 vethA slave2 vethB supervision 45 75 ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \ 76 slave1 vethA slave2 vethB supervision 45 77 78 # IP addresses 79 ip -net "$node1" addr add 100.64.0.1/24 dev hsr1 80 ip -net "$node2" addr add 100.64.0.2/24 dev hsr2 81 ip -net "$node3" addr add 100.64.0.3/24 dev hsr3 82 83 # Set all links up 84 ip -net "$node1" link set vethA up 85 ip -net "$node1" link set vethB up 86 ip -net "$node1" link set hsr1 up 87 88 ip -net "$node2" link set vethA up 89 ip -net "$node2" link set vethB up 90 ip -net "$node2" link set hsr2 up 91 92 ip -net "$node3" link set vethA up 93 ip -net "$node3" link set vethB up 94 ip -net "$node3" link set hsr3 up 95} 96 97setup_prp_topo() 98{ 99 # Two PRP nodes, connected by two links (treated as LAN A and LAN B). 100 # 101 # vethA ----- vethA 102 # prp1 prp2 103 # vethB ----- vethB 104 # 105 # node1 node2 106 107 setup_ns node1 node2 108 109 # veth links 110 ip link add vethA netns "$node1" type veth peer name vethA netns "$node2" 111 ip link add vethB netns "$node1" type veth peer name vethB netns "$node2" 112 113 # MAC addresses will be copied from LAN A interface 114 ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA 115 ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA 116 117 # PRP interfaces 118 ip -net "$node1" link add name prp1 type hsr \ 119 slave1 vethA slave2 vethB supervision 45 proto 1 120 ip -net "$node2" link add name prp2 type hsr \ 121 slave1 vethA slave2 vethB supervision 45 proto 1 122 123 # IP addresses 124 ip -net "$node1" addr add 100.64.0.1/24 dev prp1 125 ip -net "$node2" addr add 100.64.0.2/24 dev prp2 126 127 # All links up 128 ip -net "$node1" link set vethA up 129 ip -net "$node1" link set vethB up 130 ip -net "$node1" link set prp1 up 131 132 ip -net "$node2" link set vethA up 133 ip -net "$node2" link set vethB up 134 ip -net "$node2" link set prp2 up 135} 136 137wait_for_hsr_node_table() 138{ 139 log_info "Wait for node table entries to be merged." 140 WAIT=5 141 while [ "${WAIT}" -gt 0 ]; do 142 nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table) 143 144 # We need entries in the node tables, and they need to be merged 145 if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \ 146 ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then 147 return 148 fi 149 150 sleep 1 151 ((WAIT--)) 152 done 153 check_err 1 "Failed to wait for merged node table entries" 154} 155 156setup_topo() 157{ 158 local proto="$1" 159 160 if [ "$proto" = "HSRv0" ]; then 161 setup_hsr_topo 0 162 wait_for_hsr_node_table 163 elif [ "$proto" = "HSRv1" ]; then 164 setup_hsr_topo 1 165 wait_for_hsr_node_table 166 elif [ "$proto" = "PRP" ]; then 167 setup_prp_topo 168 else 169 check_err 1 "Unknown protocol (${proto})" 170 fi 171} 172 173check_ping() 174{ 175 local node="$1" 176 local dst="$2" 177 local accepted_dups="$3" 178 local ping_args="-q -i 0.01 -c 400" 179 180 log_info "Running ping $node -> $dst" 181 # shellcheck disable=SC2086 182 output=$(ip netns exec "$node" ping $ping_args "$dst" | \ 183 grep "packets transmitted") 184 log_info "$output" 185 186 dups=0 187 loss=0 188 189 if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then 190 dups="${BASH_REMATCH[1]}" 191 fi 192 if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then 193 loss="${BASH_REMATCH[1]}" 194 fi 195 196 if [ "$dups" -gt "$accepted_dups" ]; then 197 check_err 1 "Unexpected duplicate packets (${dups})" 198 fi 199 if [ "$loss" != "0%" ]; then 200 check_err 1 "Unexpected packet loss (${loss})" 201 fi 202} 203 204test_clean() 205{ 206 local proto="$1" 207 208 RET=0 209 tname="${FUNCNAME[0]} - ${proto}" 210 211 setup_topo "$proto" 212 if ((RET != ksft_pass)); then 213 log_test "${tname} setup" 214 return 215 fi 216 217 check_ping "$node1" "100.64.0.2" 0 218 219 log_test "${tname}" 220} 221 222test_clean_hsrv0() 223{ 224 test_clean "HSRv0" 225} 226 227test_clean_hsrv1() 228{ 229 test_clean "HSRv1" 230} 231 232test_clean_prp() 233{ 234 test_clean "PRP" 235} 236 237test_cut_link() 238{ 239 local proto="$1" 240 241 RET=0 242 tname="${FUNCNAME[0]} - ${proto}" 243 244 setup_topo "$proto" 245 if ((RET != ksft_pass)); then 246 log_test "${tname} setup" 247 return 248 fi 249 250 # Cutting link from subshell, so check_ping can run in the normal shell 251 # with access to global variables from the test harness. 252 ( 253 sleep 2 254 log_info "Cutting link" 255 ip -net "$node1" link set vethB down 256 ) & 257 check_ping "$node1" "100.64.0.2" 0 258 259 wait 260 log_test "${tname}" 261} 262 263 264test_cut_link_hsrv0() 265{ 266 test_cut_link "HSRv0" 267} 268 269test_cut_link_hsrv1() 270{ 271 test_cut_link "HSRv1" 272} 273 274test_cut_link_prp() 275{ 276 test_cut_link "PRP" 277} 278 279test_packet_loss() 280{ 281 local proto="$1" 282 local loss="$2" 283 284 RET=0 285 tname="${FUNCNAME[0]} - ${proto}, ${loss}" 286 287 setup_topo "$proto" 288 if ((RET != ksft_pass)); then 289 log_test "${tname} setup" 290 return 291 fi 292 293 # Packet loss with lower delay makes sure the packets on the lossy link 294 # arrive first. 295 tc -net "$node1" qdisc add dev vethA root netem delay 50ms 296 tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss" 297 298 check_ping "$node1" "100.64.0.2" 40 299 300 log_test "${tname}" 301} 302 303test_packet_loss_hsrv0() 304{ 305 test_packet_loss "HSRv0" "20%" 306} 307 308test_packet_loss_hsrv1() 309{ 310 test_packet_loss "HSRv1" "20%" 311} 312 313test_packet_loss_prp() 314{ 315 test_packet_loss "PRP" "20%" 316} 317 318test_high_packet_loss_hsrv0() 319{ 320 test_packet_loss "HSRv0" "80%" 321} 322 323test_high_packet_loss_hsrv1() 324{ 325 test_packet_loss "HSRv1" "80%" 326} 327 328test_high_packet_loss_prp() 329{ 330 test_packet_loss "PRP" "80%" 331} 332 333test_reordering() 334{ 335 local proto="$1" 336 337 RET=0 338 tname="${FUNCNAME[0]} - ${proto}" 339 340 setup_topo "$proto" 341 if ((RET != ksft_pass)); then 342 log_test "${tname} setup" 343 return 344 fi 345 346 tc -net "$node1" qdisc add dev vethA root netem delay 50ms 347 tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20% 348 349 check_ping "$node1" "100.64.0.2" 40 350 351 log_test "${tname}" 352} 353 354test_reordering_hsrv0() 355{ 356 test_reordering "HSRv0" 357} 358 359test_reordering_hsrv1() 360{ 361 test_reordering "HSRv1" 362} 363 364test_reordering_prp() 365{ 366 test_reordering "PRP" 367} 368 369cleanup() 370{ 371 cleanup_all_ns 372} 373 374trap cleanup EXIT 375 376tests_run 377 378exit $EXIT_STATUS 379