1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Test bonding options with mode 1,5,6 5 6ALL_TESTS=" 7 prio 8 arp_validate 9 num_grat_arp 10" 11 12lib_dir=$(dirname "$0") 13source ${lib_dir}/bond_topo_3d1c.sh 14c_maddr="33:33:00:00:00:10" 15g_maddr="33:33:00:00:02:54" 16 17skip_prio() 18{ 19 local skip=1 20 21 # check if iproute support prio option 22 ip -n ${s_ns} link set eth0 type bond_slave prio 10 23 [[ $? -ne 0 ]] && skip=0 24 25 # check if kernel support prio option 26 ip -n ${s_ns} -d link show eth0 | grep -q "prio 10" 27 [[ $? -ne 0 ]] && skip=0 28 29 return $skip 30} 31 32skip_ns() 33{ 34 local skip=1 35 36 # check if iproute support ns_ip6_target option 37 ip -n ${s_ns} link add bond1 type bond ns_ip6_target ${g_ip6} 38 [[ $? -ne 0 ]] && skip=0 39 40 # check if kernel support ns_ip6_target option 41 ip -n ${s_ns} -d link show bond1 | grep -q "ns_ip6_target ${g_ip6}" 42 [[ $? -ne 0 ]] && skip=0 43 44 ip -n ${s_ns} link del bond1 45 46 return $skip 47} 48 49active_slave="" 50active_slave_changed() 51{ 52 local old_active_slave=$1 53 local new_active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" \ 54 ".[].linkinfo.info_data.active_slave") 55 [ "$new_active_slave" != "$old_active_slave" -a "$new_active_slave" != "null" ] 56} 57 58check_active_slave() 59{ 60 local target_active_slave=$1 61 slowwait 5 active_slave_changed $active_slave 62 active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") 63 test "$active_slave" = "$target_active_slave" 64 check_err $? "Current active slave is $active_slave but not $target_active_slave" 65} 66 67# Test bonding prio option 68prio_test() 69{ 70 local param="$1" 71 RET=0 72 73 # create bond 74 bond_reset "${param}" 75 # set active_slave to primary eth1 specifically 76 ip -n ${s_ns} link set bond0 type bond active_slave eth1 77 78 # check bonding member prio value 79 ip -n ${s_ns} link set eth0 type bond_slave prio 0 80 ip -n ${s_ns} link set eth1 type bond_slave prio 10 81 ip -n ${s_ns} link set eth2 type bond_slave prio 11 82 cmd_jq "ip -n ${s_ns} -d -j link show eth0" \ 83 ".[].linkinfo.info_slave_data | select (.prio == 0)" "-e" &> /dev/null 84 check_err $? "eth0 prio is not 0" 85 cmd_jq "ip -n ${s_ns} -d -j link show eth1" \ 86 ".[].linkinfo.info_slave_data | select (.prio == 10)" "-e" &> /dev/null 87 check_err $? "eth1 prio is not 10" 88 cmd_jq "ip -n ${s_ns} -d -j link show eth2" \ 89 ".[].linkinfo.info_slave_data | select (.prio == 11)" "-e" &> /dev/null 90 check_err $? "eth2 prio is not 11" 91 92 bond_check_connection "setup" 93 94 # active slave should be the primary slave 95 check_active_slave eth1 96 97 # active slave should be the higher prio slave 98 ip -n ${s_ns} link set $active_slave down 99 check_active_slave eth2 100 bond_check_connection "fail over" 101 102 # when only 1 slave is up 103 ip -n ${s_ns} link set $active_slave down 104 check_active_slave eth0 105 bond_check_connection "only 1 slave up" 106 107 # when a higher prio slave change to up 108 ip -n ${s_ns} link set eth2 up 109 bond_check_connection "higher prio slave up" 110 case $primary_reselect in 111 "0") 112 check_active_slave "eth2" 113 ;; 114 "1") 115 check_active_slave "eth0" 116 ;; 117 "2") 118 check_active_slave "eth0" 119 ;; 120 esac 121 local pre_active_slave=$active_slave 122 123 # when the primary slave change to up 124 ip -n ${s_ns} link set eth1 up 125 bond_check_connection "primary slave up" 126 case $primary_reselect in 127 "0") 128 check_active_slave "eth1" 129 ;; 130 "1") 131 check_active_slave "$pre_active_slave" 132 ;; 133 "2") 134 check_active_slave "$pre_active_slave" 135 ip -n ${s_ns} link set $active_slave down 136 bond_check_connection "pre_active slave down" 137 check_active_slave "eth1" 138 ;; 139 esac 140 141 # Test changing bond slave prio 142 if [[ "$primary_reselect" == "0" ]];then 143 ip -n ${s_ns} link set eth0 type bond_slave prio 1000000 144 ip -n ${s_ns} link set eth1 type bond_slave prio 0 145 ip -n ${s_ns} link set eth2 type bond_slave prio -50 146 ip -n ${s_ns} -d link show eth0 | grep -q 'prio 1000000' 147 check_err $? "eth0 prio is not 1000000" 148 ip -n ${s_ns} -d link show eth1 | grep -q 'prio 0' 149 check_err $? "eth1 prio is not 0" 150 ip -n ${s_ns} -d link show eth2 | grep -q 'prio -50' 151 check_err $? "eth3 prio is not -50" 152 check_active_slave "eth1" 153 154 ip -n ${s_ns} link set $active_slave down 155 check_active_slave "eth0" 156 bond_check_connection "change slave prio" 157 fi 158} 159 160prio_miimon() 161{ 162 local primary_reselect 163 local mode=$1 164 165 for primary_reselect in 0 1 2; do 166 prio_test "mode $mode miimon 100 primary eth1 primary_reselect $primary_reselect" 167 log_test "prio" "$mode miimon primary_reselect $primary_reselect" 168 done 169} 170 171prio_arp() 172{ 173 local primary_reselect 174 local mode=$1 175 176 for primary_reselect in 0 1 2; do 177 prio_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} primary eth1 primary_reselect $primary_reselect" 178 log_test "prio" "$mode arp_ip_target primary_reselect $primary_reselect" 179 done 180} 181 182prio_ns() 183{ 184 local primary_reselect 185 local mode=$1 186 187 if skip_ns; then 188 log_test_skip "prio ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'." 189 return 0 190 fi 191 192 for primary_reselect in 0 1 2; do 193 prio_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} primary eth1 primary_reselect $primary_reselect" 194 log_test "prio" "$mode ns_ip6_target primary_reselect $primary_reselect" 195 done 196} 197 198prio() 199{ 200 local mode modes="active-backup balance-tlb balance-alb" 201 202 if skip_prio; then 203 log_test_skip "prio" "Current iproute or kernel doesn't support bond option 'prio'." 204 return 0 205 fi 206 207 for mode in $modes; do 208 prio_miimon $mode 209 done 210 prio_arp "active-backup" 211 prio_ns "active-backup" 212} 213 214wait_mii_up() 215{ 216 for i in $(seq 0 2); do 217 mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status") 218 [ ${mii_status} != "UP" ] && return 1 219 done 220 return 0 221} 222 223arp_validate_test() 224{ 225 local param="$1" 226 RET=0 227 228 # create bond 229 bond_reset "${param}" 230 231 bond_check_connection 232 [ $RET -ne 0 ] && log_test "arp_validate" "$retmsg" 233 234 # wait for a while to make sure the mii status stable 235 slowwait 5 wait_mii_up 236 for i in $(seq 0 2); do 237 mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status") 238 if [ ${mii_status} != "UP" ]; then 239 RET=1 240 log_test "arp_validate" "interface eth$i mii_status $mii_status" 241 fi 242 done 243} 244 245# Testing correct multicast groups are added to slaves for ns targets 246arp_validate_mcast() 247{ 248 RET=0 249 local arp_valid=$(cmd_jq "ip -n ${s_ns} -j -d link show bond0" ".[].linkinfo.info_data.arp_validate") 250 local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") 251 252 for i in $(seq 0 2); do 253 maddr_list=$(ip -n ${s_ns} maddr show dev eth${i}) 254 255 # arp_valid == 0 or active_slave should not join any maddrs 256 if { [ "$arp_valid" == "null" ] || [ "eth${i}" == ${active_slave} ]; } && \ 257 echo "$maddr_list" | grep -qE "${c_maddr}|${g_maddr}"; then 258 RET=1 259 check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group" 260 # arp_valid != 0 and backup_slave should join both maddrs 261 elif [ "$arp_valid" != "null" ] && [ "eth${i}" != ${active_slave} ] && \ 262 ( ! echo "$maddr_list" | grep -q "${c_maddr}" || \ 263 ! echo "$maddr_list" | grep -q "${m_maddr}"); then 264 RET=1 265 check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group" 266 fi 267 done 268 269 # Do failover 270 ip -n ${s_ns} link set ${active_slave} down 271 # wait for active link change 272 slowwait 2 active_slave_changed $active_slave 273 active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") 274 275 for i in $(seq 0 2); do 276 maddr_list=$(ip -n ${s_ns} maddr show dev eth${i}) 277 278 # arp_valid == 0 or active_slave should not join any maddrs 279 if { [ "$arp_valid" == "null" ] || [ "eth${i}" == ${active_slave} ]; } && \ 280 echo "$maddr_list" | grep -qE "${c_maddr}|${g_maddr}"; then 281 RET=1 282 check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group" 283 # arp_valid != 0 and backup_slave should join both maddrs 284 elif [ "$arp_valid" != "null" ] && [ "eth${i}" != ${active_slave} ] && \ 285 ( ! echo "$maddr_list" | grep -q "${c_maddr}" || \ 286 ! echo "$maddr_list" | grep -q "${m_maddr}"); then 287 RET=1 288 check_err 1 "arp_valid $arp_valid active_slave $active_slave, eth$i has mcast group" 289 fi 290 done 291} 292 293arp_validate_arp() 294{ 295 local mode=$1 296 local val 297 for val in $(seq 0 6); do 298 arp_validate_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} arp_validate $val" 299 log_test "arp_validate" "$mode arp_ip_target arp_validate $val" 300 done 301} 302 303arp_validate_ns() 304{ 305 local mode=$1 306 local val 307 308 if skip_ns; then 309 log_test_skip "arp_validate ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'." 310 return 0 311 fi 312 313 for val in $(seq 0 6); do 314 arp_validate_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6},${c_ip6} arp_validate $val" 315 log_test "arp_validate" "$mode ns_ip6_target arp_validate $val" 316 arp_validate_mcast 317 log_test "arp_validate" "join mcast group" 318 done 319} 320 321arp_validate() 322{ 323 arp_validate_arp "active-backup" 324 arp_validate_ns "active-backup" 325} 326 327garp_test() 328{ 329 local param="$1" 330 local active_slave exp_num real_num i 331 RET=0 332 333 # create bond 334 bond_reset "${param}" 335 336 bond_check_connection 337 [ $RET -ne 0 ] && log_test "num_grat_arp" "$retmsg" 338 339 340 # Add tc rules to count GARP number 341 for i in $(seq 0 2); do 342 tc -n ${g_ns} filter add dev s$i ingress protocol arp pref 1 handle 101 \ 343 flower skip_hw arp_op request arp_sip ${s_ip4} arp_tip ${s_ip4} action pass 344 done 345 346 # Do failover 347 active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") 348 ip -n ${s_ns} link set ${active_slave} down 349 350 # wait for active link change 351 slowwait 2 active_slave_changed $active_slave 352 353 exp_num=$(echo "${param}" | cut -f6 -d ' ') 354 active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") 355 slowwait_for_counter $((exp_num + 5)) $exp_num \ 356 tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}" 357 358 # check result 359 real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}") 360 if [ "${real_num}" -ne "${exp_num}" ]; then 361 echo "$real_num garp packets sent on active slave ${active_slave}" 362 RET=1 363 fi 364 365 for i in $(seq 0 2); do 366 tc -n ${g_ns} filter del dev s$i ingress 367 done 368} 369 370num_grat_arp() 371{ 372 local val 373 for val in 10 20 30; do 374 garp_test "mode active-backup miimon 10 num_grat_arp $val peer_notify_delay 100" 375 log_test "num_grat_arp" "active-backup miimon num_grat_arp $val" 376 done 377} 378 379trap cleanup EXIT 380 381setup_prepare 382setup_wait 383tests_run 384 385exit $EXIT_STATUS 386