1ca4a09a9SFelix Maurer#!/bin/bash 2ca4a09a9SFelix Maurer# SPDX-License-Identifier: GPL-2.0 3ca4a09a9SFelix Maurer# shellcheck disable=SC2329 4ca4a09a9SFelix Maurer 5ca4a09a9SFelix Maurersource ../lib.sh 6ca4a09a9SFelix Maurer 7ca4a09a9SFelix MaurerALL_TESTS=" 8ca4a09a9SFelix Maurer test_clean_hsrv0 9ca4a09a9SFelix Maurer test_cut_link_hsrv0 10*bbbd531fSFelix Maurer test_packet_loss_hsrv0 11*bbbd531fSFelix Maurer test_high_packet_loss_hsrv0 12*bbbd531fSFelix Maurer test_reordering_hsrv0 13*bbbd531fSFelix Maurer 14ca4a09a9SFelix Maurer test_clean_hsrv1 15ca4a09a9SFelix Maurer test_cut_link_hsrv1 16*bbbd531fSFelix Maurer test_packet_loss_hsrv1 17*bbbd531fSFelix Maurer test_high_packet_loss_hsrv1 18*bbbd531fSFelix Maurer test_reordering_hsrv1 19*bbbd531fSFelix Maurer 20ca4a09a9SFelix Maurer test_clean_prp 21ca4a09a9SFelix Maurer test_cut_link_prp 228908c3c8SFelix Maurer test_packet_loss_prp 238908c3c8SFelix Maurer test_high_packet_loss_prp 248908c3c8SFelix Maurer test_reordering_prp 25ca4a09a9SFelix Maurer" 26ca4a09a9SFelix Maurer 278908c3c8SFelix Maurer# The tests are running ping for 5sec with a relatively short interval in 288908c3c8SFelix Maurer# different scenarios with faulty links (cut links, packet loss, delay, 298908c3c8SFelix Maurer# reordering) that should be recoverable by HSR/PRP. The ping interval (10ms) 308908c3c8SFelix Maurer# is short enough that the base delay (50ms) leads to a queue in the netem 318908c3c8SFelix Maurer# qdiscs which is needed for reordering. 32ca4a09a9SFelix Maurer 33ca4a09a9SFelix Maurersetup_hsr_topo() 34ca4a09a9SFelix Maurer{ 35ca4a09a9SFelix Maurer # Three HSR nodes in a ring, every node has a LAN A interface connected 36ca4a09a9SFelix Maurer # to the LAN B interface of the next node. 37ca4a09a9SFelix Maurer # 38ca4a09a9SFelix Maurer # node1 node2 39ca4a09a9SFelix Maurer # 40ca4a09a9SFelix Maurer # vethA -------- vethB 41ca4a09a9SFelix Maurer # hsr1 hsr2 42ca4a09a9SFelix Maurer # vethB vethA 43ca4a09a9SFelix Maurer # \ / 44ca4a09a9SFelix Maurer # vethA vethB 45ca4a09a9SFelix Maurer # hsr3 46ca4a09a9SFelix Maurer # 47ca4a09a9SFelix Maurer # node3 48ca4a09a9SFelix Maurer 49ca4a09a9SFelix Maurer local ver="$1" 50ca4a09a9SFelix Maurer 51ca4a09a9SFelix Maurer setup_ns node1 node2 node3 52ca4a09a9SFelix Maurer 53ca4a09a9SFelix Maurer # veth links 54ca4a09a9SFelix Maurer # shellcheck disable=SC2154 # variables assigned by setup_ns 55ca4a09a9SFelix Maurer ip link add vethA netns "$node1" type veth peer name vethB netns "$node2" 56ca4a09a9SFelix Maurer # shellcheck disable=SC2154 # variables assigned by setup_ns 57ca4a09a9SFelix Maurer ip link add vethA netns "$node2" type veth peer name vethB netns "$node3" 58ca4a09a9SFelix Maurer ip link add vethA netns "$node3" type veth peer name vethB netns "$node1" 59ca4a09a9SFelix Maurer 60ca4a09a9SFelix Maurer # MAC addresses (not needed for HSR operation, but helps with debugging) 61ca4a09a9SFelix Maurer ip -net "$node1" link set address 00:11:22:00:01:01 dev vethA 62ca4a09a9SFelix Maurer ip -net "$node1" link set address 00:11:22:00:01:02 dev vethB 63ca4a09a9SFelix Maurer 64ca4a09a9SFelix Maurer ip -net "$node2" link set address 00:11:22:00:02:01 dev vethA 65ca4a09a9SFelix Maurer ip -net "$node2" link set address 00:11:22:00:02:02 dev vethB 66ca4a09a9SFelix Maurer 67ca4a09a9SFelix Maurer ip -net "$node3" link set address 00:11:22:00:03:01 dev vethA 68ca4a09a9SFelix Maurer ip -net "$node3" link set address 00:11:22:00:03:02 dev vethB 69ca4a09a9SFelix Maurer 70ca4a09a9SFelix Maurer # HSR interfaces 71ca4a09a9SFelix Maurer ip -net "$node1" link add name hsr1 type hsr proto 0 version "$ver" \ 72ca4a09a9SFelix Maurer slave1 vethA slave2 vethB supervision 45 73ca4a09a9SFelix Maurer ip -net "$node2" link add name hsr2 type hsr proto 0 version "$ver" \ 74ca4a09a9SFelix Maurer slave1 vethA slave2 vethB supervision 45 75ca4a09a9SFelix Maurer ip -net "$node3" link add name hsr3 type hsr proto 0 version "$ver" \ 76ca4a09a9SFelix Maurer slave1 vethA slave2 vethB supervision 45 77ca4a09a9SFelix Maurer 78ca4a09a9SFelix Maurer # IP addresses 79ca4a09a9SFelix Maurer ip -net "$node1" addr add 100.64.0.1/24 dev hsr1 80ca4a09a9SFelix Maurer ip -net "$node2" addr add 100.64.0.2/24 dev hsr2 81ca4a09a9SFelix Maurer ip -net "$node3" addr add 100.64.0.3/24 dev hsr3 82ca4a09a9SFelix Maurer 83ca4a09a9SFelix Maurer # Set all links up 84ca4a09a9SFelix Maurer ip -net "$node1" link set vethA up 85ca4a09a9SFelix Maurer ip -net "$node1" link set vethB up 86ca4a09a9SFelix Maurer ip -net "$node1" link set hsr1 up 87ca4a09a9SFelix Maurer 88ca4a09a9SFelix Maurer ip -net "$node2" link set vethA up 89ca4a09a9SFelix Maurer ip -net "$node2" link set vethB up 90ca4a09a9SFelix Maurer ip -net "$node2" link set hsr2 up 91ca4a09a9SFelix Maurer 92ca4a09a9SFelix Maurer ip -net "$node3" link set vethA up 93ca4a09a9SFelix Maurer ip -net "$node3" link set vethB up 94ca4a09a9SFelix Maurer ip -net "$node3" link set hsr3 up 95ca4a09a9SFelix Maurer} 96ca4a09a9SFelix Maurer 97ca4a09a9SFelix Maurersetup_prp_topo() 98ca4a09a9SFelix Maurer{ 99ca4a09a9SFelix Maurer # Two PRP nodes, connected by two links (treated as LAN A and LAN B). 100ca4a09a9SFelix Maurer # 101ca4a09a9SFelix Maurer # vethA ----- vethA 102ca4a09a9SFelix Maurer # prp1 prp2 103ca4a09a9SFelix Maurer # vethB ----- vethB 104ca4a09a9SFelix Maurer # 105ca4a09a9SFelix Maurer # node1 node2 106ca4a09a9SFelix Maurer 107ca4a09a9SFelix Maurer setup_ns node1 node2 108ca4a09a9SFelix Maurer 109ca4a09a9SFelix Maurer # veth links 110ca4a09a9SFelix Maurer ip link add vethA netns "$node1" type veth peer name vethA netns "$node2" 111ca4a09a9SFelix Maurer ip link add vethB netns "$node1" type veth peer name vethB netns "$node2" 112ca4a09a9SFelix Maurer 113ca4a09a9SFelix Maurer # MAC addresses will be copied from LAN A interface 114ca4a09a9SFelix Maurer ip -net "$node1" link set address 00:11:22:00:00:01 dev vethA 115ca4a09a9SFelix Maurer ip -net "$node2" link set address 00:11:22:00:00:02 dev vethA 116ca4a09a9SFelix Maurer 117ca4a09a9SFelix Maurer # PRP interfaces 118ca4a09a9SFelix Maurer ip -net "$node1" link add name prp1 type hsr \ 119ca4a09a9SFelix Maurer slave1 vethA slave2 vethB supervision 45 proto 1 120ca4a09a9SFelix Maurer ip -net "$node2" link add name prp2 type hsr \ 121ca4a09a9SFelix Maurer slave1 vethA slave2 vethB supervision 45 proto 1 122ca4a09a9SFelix Maurer 123ca4a09a9SFelix Maurer # IP addresses 124ca4a09a9SFelix Maurer ip -net "$node1" addr add 100.64.0.1/24 dev prp1 125ca4a09a9SFelix Maurer ip -net "$node2" addr add 100.64.0.2/24 dev prp2 126ca4a09a9SFelix Maurer 127ca4a09a9SFelix Maurer # All links up 128ca4a09a9SFelix Maurer ip -net "$node1" link set vethA up 129ca4a09a9SFelix Maurer ip -net "$node1" link set vethB up 130ca4a09a9SFelix Maurer ip -net "$node1" link set prp1 up 131ca4a09a9SFelix Maurer 132ca4a09a9SFelix Maurer ip -net "$node2" link set vethA up 133ca4a09a9SFelix Maurer ip -net "$node2" link set vethB up 134ca4a09a9SFelix Maurer ip -net "$node2" link set prp2 up 135ca4a09a9SFelix Maurer} 136ca4a09a9SFelix Maurer 137ca4a09a9SFelix Maurerwait_for_hsr_node_table() 138ca4a09a9SFelix Maurer{ 139ca4a09a9SFelix Maurer log_info "Wait for node table entries to be merged." 140ca4a09a9SFelix Maurer WAIT=5 141ca4a09a9SFelix Maurer while [ "${WAIT}" -gt 0 ]; do 142ca4a09a9SFelix Maurer nts=$(cat /sys/kernel/debug/hsr/hsr*/node_table) 143ca4a09a9SFelix Maurer 144ca4a09a9SFelix Maurer # We need entries in the node tables, and they need to be merged 145ca4a09a9SFelix Maurer if (echo "$nts" | grep -qE "^([0-9a-f]{2}:){5}") && \ 146ca4a09a9SFelix Maurer ! (echo "$nts" | grep -q "00:00:00:00:00:00"); then 147ca4a09a9SFelix Maurer return 148ca4a09a9SFelix Maurer fi 149ca4a09a9SFelix Maurer 150ca4a09a9SFelix Maurer sleep 1 151ca4a09a9SFelix Maurer ((WAIT--)) 152ca4a09a9SFelix Maurer done 153ca4a09a9SFelix Maurer check_err 1 "Failed to wait for merged node table entries" 154ca4a09a9SFelix Maurer} 155ca4a09a9SFelix Maurer 156ca4a09a9SFelix Maurersetup_topo() 157ca4a09a9SFelix Maurer{ 158ca4a09a9SFelix Maurer local proto="$1" 159ca4a09a9SFelix Maurer 160ca4a09a9SFelix Maurer if [ "$proto" = "HSRv0" ]; then 161ca4a09a9SFelix Maurer setup_hsr_topo 0 162ca4a09a9SFelix Maurer wait_for_hsr_node_table 163ca4a09a9SFelix Maurer elif [ "$proto" = "HSRv1" ]; then 164ca4a09a9SFelix Maurer setup_hsr_topo 1 165ca4a09a9SFelix Maurer wait_for_hsr_node_table 166ca4a09a9SFelix Maurer elif [ "$proto" = "PRP" ]; then 167ca4a09a9SFelix Maurer setup_prp_topo 168ca4a09a9SFelix Maurer else 169ca4a09a9SFelix Maurer check_err 1 "Unknown protocol (${proto})" 170ca4a09a9SFelix Maurer fi 171ca4a09a9SFelix Maurer} 172ca4a09a9SFelix Maurer 173ca4a09a9SFelix Maurercheck_ping() 174ca4a09a9SFelix Maurer{ 175ca4a09a9SFelix Maurer local node="$1" 176ca4a09a9SFelix Maurer local dst="$2" 1778908c3c8SFelix Maurer local accepted_dups="$3" 178ca4a09a9SFelix Maurer local ping_args="-q -i 0.01 -c 400" 179ca4a09a9SFelix Maurer 180ca4a09a9SFelix Maurer log_info "Running ping $node -> $dst" 181ca4a09a9SFelix Maurer # shellcheck disable=SC2086 182ca4a09a9SFelix Maurer output=$(ip netns exec "$node" ping $ping_args "$dst" | \ 183ca4a09a9SFelix Maurer grep "packets transmitted") 184ca4a09a9SFelix Maurer log_info "$output" 185ca4a09a9SFelix Maurer 186ca4a09a9SFelix Maurer dups=0 187ca4a09a9SFelix Maurer loss=0 188ca4a09a9SFelix Maurer 189ca4a09a9SFelix Maurer if [[ "$output" =~ \+([0-9]+)" duplicates" ]]; then 190ca4a09a9SFelix Maurer dups="${BASH_REMATCH[1]}" 191ca4a09a9SFelix Maurer fi 192ca4a09a9SFelix Maurer if [[ "$output" =~ ([0-9\.]+\%)" packet loss" ]]; then 193ca4a09a9SFelix Maurer loss="${BASH_REMATCH[1]}" 194ca4a09a9SFelix Maurer fi 195ca4a09a9SFelix Maurer 1968908c3c8SFelix Maurer if [ "$dups" -gt "$accepted_dups" ]; then 1978908c3c8SFelix Maurer check_err 1 "Unexpected duplicate packets (${dups})" 1988908c3c8SFelix Maurer fi 199ca4a09a9SFelix Maurer if [ "$loss" != "0%" ]; then 200ca4a09a9SFelix Maurer check_err 1 "Unexpected packet loss (${loss})" 201ca4a09a9SFelix Maurer fi 202ca4a09a9SFelix Maurer} 203ca4a09a9SFelix Maurer 204ca4a09a9SFelix Maurertest_clean() 205ca4a09a9SFelix Maurer{ 206ca4a09a9SFelix Maurer local proto="$1" 207ca4a09a9SFelix Maurer 208ca4a09a9SFelix Maurer RET=0 209ca4a09a9SFelix Maurer tname="${FUNCNAME[0]} - ${proto}" 210ca4a09a9SFelix Maurer 211ca4a09a9SFelix Maurer setup_topo "$proto" 212ca4a09a9SFelix Maurer if ((RET != ksft_pass)); then 213ca4a09a9SFelix Maurer log_test "${tname} setup" 214ca4a09a9SFelix Maurer return 215ca4a09a9SFelix Maurer fi 216ca4a09a9SFelix Maurer 2178908c3c8SFelix Maurer check_ping "$node1" "100.64.0.2" 0 218ca4a09a9SFelix Maurer 219ca4a09a9SFelix Maurer log_test "${tname}" 220ca4a09a9SFelix Maurer} 221ca4a09a9SFelix Maurer 222ca4a09a9SFelix Maurertest_clean_hsrv0() 223ca4a09a9SFelix Maurer{ 224ca4a09a9SFelix Maurer test_clean "HSRv0" 225ca4a09a9SFelix Maurer} 226ca4a09a9SFelix Maurer 227ca4a09a9SFelix Maurertest_clean_hsrv1() 228ca4a09a9SFelix Maurer{ 229ca4a09a9SFelix Maurer test_clean "HSRv1" 230ca4a09a9SFelix Maurer} 231ca4a09a9SFelix Maurer 232ca4a09a9SFelix Maurertest_clean_prp() 233ca4a09a9SFelix Maurer{ 234ca4a09a9SFelix Maurer test_clean "PRP" 235ca4a09a9SFelix Maurer} 236ca4a09a9SFelix Maurer 237ca4a09a9SFelix Maurertest_cut_link() 238ca4a09a9SFelix Maurer{ 239ca4a09a9SFelix Maurer local proto="$1" 240ca4a09a9SFelix Maurer 241ca4a09a9SFelix Maurer RET=0 242ca4a09a9SFelix Maurer tname="${FUNCNAME[0]} - ${proto}" 243ca4a09a9SFelix Maurer 244ca4a09a9SFelix Maurer setup_topo "$proto" 245ca4a09a9SFelix Maurer if ((RET != ksft_pass)); then 246ca4a09a9SFelix Maurer log_test "${tname} setup" 247ca4a09a9SFelix Maurer return 248ca4a09a9SFelix Maurer fi 249ca4a09a9SFelix Maurer 250ca4a09a9SFelix Maurer # Cutting link from subshell, so check_ping can run in the normal shell 251ca4a09a9SFelix Maurer # with access to global variables from the test harness. 252ca4a09a9SFelix Maurer ( 253ca4a09a9SFelix Maurer sleep 2 254ca4a09a9SFelix Maurer log_info "Cutting link" 255ca4a09a9SFelix Maurer ip -net "$node1" link set vethB down 256ca4a09a9SFelix Maurer ) & 2578908c3c8SFelix Maurer check_ping "$node1" "100.64.0.2" 0 258ca4a09a9SFelix Maurer 259ca4a09a9SFelix Maurer wait 260ca4a09a9SFelix Maurer log_test "${tname}" 261ca4a09a9SFelix Maurer} 262ca4a09a9SFelix Maurer 263ca4a09a9SFelix Maurer 264ca4a09a9SFelix Maurertest_cut_link_hsrv0() 265ca4a09a9SFelix Maurer{ 266ca4a09a9SFelix Maurer test_cut_link "HSRv0" 267ca4a09a9SFelix Maurer} 268ca4a09a9SFelix Maurer 269ca4a09a9SFelix Maurertest_cut_link_hsrv1() 270ca4a09a9SFelix Maurer{ 271ca4a09a9SFelix Maurer test_cut_link "HSRv1" 272ca4a09a9SFelix Maurer} 273ca4a09a9SFelix Maurer 274ca4a09a9SFelix Maurertest_cut_link_prp() 275ca4a09a9SFelix Maurer{ 276ca4a09a9SFelix Maurer test_cut_link "PRP" 277ca4a09a9SFelix Maurer} 278ca4a09a9SFelix Maurer 2798908c3c8SFelix Maurertest_packet_loss() 2808908c3c8SFelix Maurer{ 2818908c3c8SFelix Maurer local proto="$1" 2828908c3c8SFelix Maurer local loss="$2" 2838908c3c8SFelix Maurer 2848908c3c8SFelix Maurer RET=0 2858908c3c8SFelix Maurer tname="${FUNCNAME[0]} - ${proto}, ${loss}" 2868908c3c8SFelix Maurer 2878908c3c8SFelix Maurer setup_topo "$proto" 2888908c3c8SFelix Maurer if ((RET != ksft_pass)); then 2898908c3c8SFelix Maurer log_test "${tname} setup" 2908908c3c8SFelix Maurer return 2918908c3c8SFelix Maurer fi 2928908c3c8SFelix Maurer 2938908c3c8SFelix Maurer # Packet loss with lower delay makes sure the packets on the lossy link 2948908c3c8SFelix Maurer # arrive first. 2958908c3c8SFelix Maurer tc -net "$node1" qdisc add dev vethA root netem delay 50ms 2968908c3c8SFelix Maurer tc -net "$node1" qdisc add dev vethB root netem delay 20ms loss "$loss" 2978908c3c8SFelix Maurer 2988908c3c8SFelix Maurer check_ping "$node1" "100.64.0.2" 40 2998908c3c8SFelix Maurer 3008908c3c8SFelix Maurer log_test "${tname}" 3018908c3c8SFelix Maurer} 3028908c3c8SFelix Maurer 303*bbbd531fSFelix Maurertest_packet_loss_hsrv0() 304*bbbd531fSFelix Maurer{ 305*bbbd531fSFelix Maurer test_packet_loss "HSRv0" "20%" 306*bbbd531fSFelix Maurer} 307*bbbd531fSFelix Maurer 308*bbbd531fSFelix Maurertest_packet_loss_hsrv1() 309*bbbd531fSFelix Maurer{ 310*bbbd531fSFelix Maurer test_packet_loss "HSRv1" "20%" 311*bbbd531fSFelix Maurer} 312*bbbd531fSFelix Maurer 3138908c3c8SFelix Maurertest_packet_loss_prp() 3148908c3c8SFelix Maurer{ 3158908c3c8SFelix Maurer test_packet_loss "PRP" "20%" 3168908c3c8SFelix Maurer} 3178908c3c8SFelix Maurer 318*bbbd531fSFelix Maurertest_high_packet_loss_hsrv0() 319*bbbd531fSFelix Maurer{ 320*bbbd531fSFelix Maurer test_packet_loss "HSRv0" "80%" 321*bbbd531fSFelix Maurer} 322*bbbd531fSFelix Maurer 323*bbbd531fSFelix Maurertest_high_packet_loss_hsrv1() 324*bbbd531fSFelix Maurer{ 325*bbbd531fSFelix Maurer test_packet_loss "HSRv1" "80%" 326*bbbd531fSFelix Maurer} 327*bbbd531fSFelix Maurer 3288908c3c8SFelix Maurertest_high_packet_loss_prp() 3298908c3c8SFelix Maurer{ 3308908c3c8SFelix Maurer test_packet_loss "PRP" "80%" 3318908c3c8SFelix Maurer} 3328908c3c8SFelix Maurer 3338908c3c8SFelix Maurertest_reordering() 3348908c3c8SFelix Maurer{ 3358908c3c8SFelix Maurer local proto="$1" 3368908c3c8SFelix Maurer 3378908c3c8SFelix Maurer RET=0 3388908c3c8SFelix Maurer tname="${FUNCNAME[0]} - ${proto}" 3398908c3c8SFelix Maurer 3408908c3c8SFelix Maurer setup_topo "$proto" 3418908c3c8SFelix Maurer if ((RET != ksft_pass)); then 3428908c3c8SFelix Maurer log_test "${tname} setup" 3438908c3c8SFelix Maurer return 3448908c3c8SFelix Maurer fi 3458908c3c8SFelix Maurer 3468908c3c8SFelix Maurer tc -net "$node1" qdisc add dev vethA root netem delay 50ms 3478908c3c8SFelix Maurer tc -net "$node1" qdisc add dev vethB root netem delay 50ms reorder 20% 3488908c3c8SFelix Maurer 3498908c3c8SFelix Maurer check_ping "$node1" "100.64.0.2" 40 3508908c3c8SFelix Maurer 3518908c3c8SFelix Maurer log_test "${tname}" 3528908c3c8SFelix Maurer} 3538908c3c8SFelix Maurer 354*bbbd531fSFelix Maurertest_reordering_hsrv0() 355*bbbd531fSFelix Maurer{ 356*bbbd531fSFelix Maurer test_reordering "HSRv0" 357*bbbd531fSFelix Maurer} 358*bbbd531fSFelix Maurer 359*bbbd531fSFelix Maurertest_reordering_hsrv1() 360*bbbd531fSFelix Maurer{ 361*bbbd531fSFelix Maurer test_reordering "HSRv1" 362*bbbd531fSFelix Maurer} 363*bbbd531fSFelix Maurer 3648908c3c8SFelix Maurertest_reordering_prp() 3658908c3c8SFelix Maurer{ 3668908c3c8SFelix Maurer test_reordering "PRP" 3678908c3c8SFelix Maurer} 3688908c3c8SFelix Maurer 369ca4a09a9SFelix Maurercleanup() 370ca4a09a9SFelix Maurer{ 371ca4a09a9SFelix Maurer cleanup_all_ns 372ca4a09a9SFelix Maurer} 373ca4a09a9SFelix Maurer 374ca4a09a9SFelix Maurertrap cleanup EXIT 375ca4a09a9SFelix Maurer 376ca4a09a9SFelix Maurertests_run 377ca4a09a9SFelix Maurer 378ca4a09a9SFelix Maurerexit $EXIT_STATUS 379