1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4ALL_TESTS=" 5 same_speeds_autoneg_off 6 different_speeds_autoneg_off 7 combination_of_neg_on_and_off 8 advertise_subset_of_speeds 9 check_highest_speed_is_chosen 10 different_speeds_autoneg_on 11" 12NUM_NETIFS=2 13source lib.sh 14source ethtool_lib.sh 15 16h1_create() 17{ 18 simple_if_init $h1 192.0.2.1/24 19} 20 21h1_destroy() 22{ 23 simple_if_fini $h1 192.0.2.1/24 24} 25 26h2_create() 27{ 28 simple_if_init $h2 192.0.2.2/24 29} 30 31h2_destroy() 32{ 33 simple_if_fini $h2 192.0.2.2/24 34} 35 36setup_prepare() 37{ 38 h1=${NETIFS[p1]} 39 h2=${NETIFS[p2]} 40 41 h1_create 42 h2_create 43} 44 45cleanup() 46{ 47 pre_cleanup 48 49 h2_destroy 50 h1_destroy 51} 52 53different_speeds_get() 54{ 55 local dev1=$1; shift 56 local dev2=$1; shift 57 local with_mode=$1; shift 58 local adver=$1; shift 59 60 local -a speeds_arr 61 62 speeds_arr=($(common_speeds_get $dev1 $dev2 $with_mode $adver)) 63 if [[ ${#speeds_arr[@]} < 2 ]]; then 64 check_err 1 "cannot check different speeds. There are not enough speeds" 65 fi 66 67 echo ${speeds_arr[0]} ${speeds_arr[1]} 68} 69 70same_speeds_autoneg_off() 71{ 72 # Check that when each of the reported speeds is forced, the links come 73 # up and are operational. 74 local -a speeds_arr=($(common_speeds_get $h1 $h2 0 0)) 75 76 for speed in "${speeds_arr[@]}"; do 77 RET=0 78 ethtool_set $h1 speed $speed autoneg off 79 ethtool_set $h2 speed $speed autoneg off 80 81 setup_wait_dev_with_timeout $h1 82 setup_wait_dev_with_timeout $h2 83 ping_do $h1 192.0.2.2 84 check_err $? "speed $speed autoneg off" 85 log_test "force of same speed autoneg off" 86 log_info "speed = $speed" 87 done 88 89 ethtool -s $h2 autoneg on 90 ethtool -s $h1 autoneg on 91} 92 93different_speeds_autoneg_off() 94{ 95 # Test that when we force different speeds, links are not up and ping 96 # fails. 97 RET=0 98 99 local -a speeds_arr=($(different_speeds_get $h1 $h2 0 0)) 100 local speed1=${speeds_arr[0]} 101 local speed2=${speeds_arr[1]} 102 103 ethtool_set $h1 speed $speed1 autoneg off 104 ethtool_set $h2 speed $speed2 autoneg off 105 106 setup_wait_dev_with_timeout $h1 107 setup_wait_dev_with_timeout $h2 108 ping_do $h1 192.0.2.2 109 check_fail $? "ping with different speeds" 110 111 log_test "force of different speeds autoneg off" 112 113 ethtool -s $h2 autoneg on 114 ethtool -s $h1 autoneg on 115} 116 117combination_of_neg_on_and_off() 118{ 119 # Test that when one device is forced to a speed supported by both 120 # endpoints and the other device is configured to autoneg on, the links 121 # are up and ping passes. 122 local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1)) 123 124 for speed in "${speeds_arr[@]}"; do 125 RET=0 126 ethtool_set $h1 speed $speed autoneg off 127 128 setup_wait_dev_with_timeout $h1 129 setup_wait_dev_with_timeout $h2 130 ping_do $h1 192.0.2.2 131 check_err $? "h1-speed=$speed autoneg off, h2 autoneg on" 132 log_test "one side with autoneg off and another with autoneg on" 133 log_info "force speed = $speed" 134 done 135 136 ethtool -s $h1 autoneg on 137} 138 139hex_speed_value_get() 140{ 141 local speed=$1; shift 142 143 local shift_size=${speed_values[$speed]} 144 speed=$((0x1 << $"shift_size")) 145 printf "%#x" "$speed" 146} 147 148subset_of_common_speeds_get() 149{ 150 local dev1=$1; shift 151 local dev2=$1; shift 152 local adver=$1; shift 153 154 local -a speeds_arr=($(common_speeds_get $dev1 $dev2 0 $adver)) 155 local speed_to_advertise=0 156 local speed_to_remove=${speeds_arr[0]} 157 speed_to_remove+='base' 158 159 local -a speeds_mode_arr=($(common_speeds_get $dev1 $dev2 1 $adver)) 160 161 for speed in ${speeds_mode_arr[@]}; do 162 if [[ $speed != $speed_to_remove* ]]; then 163 speed=$(hex_speed_value_get $speed) 164 speed_to_advertise=$(($speed_to_advertise | \ 165 $speed)) 166 fi 167 168 done 169 170 # Convert to hex. 171 printf "%#x" "$speed_to_advertise" 172} 173 174speed_to_advertise_get() 175{ 176 # The function returns the hex number that is composed by OR-ing all 177 # the modes corresponding to the provided speed. 178 local speed_without_mode=$1; shift 179 local supported_speeds=("$@"); shift 180 local speed_to_advertise=0 181 182 speed_without_mode+='base' 183 184 for speed in ${supported_speeds[@]}; do 185 if [[ $speed == $speed_without_mode* ]]; then 186 speed=$(hex_speed_value_get $speed) 187 speed_to_advertise=$(($speed_to_advertise | \ 188 $speed)) 189 fi 190 191 done 192 193 # Convert to hex. 194 printf "%#x" "$speed_to_advertise" 195} 196 197advertise_subset_of_speeds() 198{ 199 # Test that when one device advertises a subset of speeds and another 200 # advertises a specific speed (but all modes of this speed), the links 201 # are up and ping passes. 202 RET=0 203 204 local speed_1_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1) 205 ethtool_set $h1 advertise $speed_1_to_advertise 206 207 if [ $RET != 0 ]; then 208 log_test "advertise subset of speeds" 209 return 210 fi 211 212 local -a speeds_arr_without_mode=($(common_speeds_get $h1 $h2 0 1)) 213 # Check only speeds that h1 advertised. Remove the first speed. 214 unset speeds_arr_without_mode[0] 215 local -a speeds_arr_with_mode=($(common_speeds_get $h1 $h2 1 1)) 216 217 for speed_value in ${speeds_arr_without_mode[@]}; do 218 RET=0 219 local speed_2_to_advertise=$(speed_to_advertise_get $speed_value \ 220 "${speeds_arr_with_mode[@]}") 221 ethtool_set $h2 advertise $speed_2_to_advertise 222 223 setup_wait_dev_with_timeout $h1 224 setup_wait_dev_with_timeout $h2 225 ping_do $h1 192.0.2.2 226 check_err $? "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)" 227 228 log_test "advertise subset of speeds" 229 log_info "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise" 230 done 231 232 ethtool -s $h2 autoneg on 233 ethtool -s $h1 autoneg on 234} 235 236check_highest_speed_is_chosen() 237{ 238 # Test that when one device advertises a subset of speeds, the other 239 # chooses the highest speed. This test checks configuration without 240 # traffic. 241 RET=0 242 243 local max_speed 244 local chosen_speed 245 local speed_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1) 246 247 ethtool_set $h1 advertise $speed_to_advertise 248 249 if [ $RET != 0 ]; then 250 log_test "check highest speed" 251 return 252 fi 253 254 local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1)) 255 # Remove the first speed, h1 does not advertise this speed. 256 unset speeds_arr[0] 257 258 max_speed=${speeds_arr[0]} 259 for current in ${speeds_arr[@]}; do 260 if [[ $current -gt $max_speed ]]; then 261 max_speed=$current 262 fi 263 done 264 265 setup_wait_dev_with_timeout $h1 266 setup_wait_dev_with_timeout $h2 267 chosen_speed=$(ethtool $h1 | grep 'Speed:') 268 chosen_speed=${chosen_speed%"Mb/s"*} 269 chosen_speed=${chosen_speed#*"Speed: "} 270 ((chosen_speed == max_speed)) 271 check_err $? "h1 advertise $speed_to_advertise, h2 sync to speed $chosen_speed" 272 273 log_test "check highest speed" 274 275 ethtool -s $h2 autoneg on 276 ethtool -s $h1 autoneg on 277} 278 279different_speeds_autoneg_on() 280{ 281 # Test that when we configure links to advertise different speeds, 282 # links are not up and ping fails. 283 RET=0 284 285 local -a speeds=($(different_speeds_get $h1 $h2 1 1)) 286 local speed1=${speeds[0]} 287 local speed2=${speeds[1]} 288 289 speed1=$(hex_speed_value_get $speed1) 290 speed2=$(hex_speed_value_get $speed2) 291 292 ethtool_set $h1 advertise $speed1 293 ethtool_set $h2 advertise $speed2 294 295 if (($RET)); then 296 setup_wait_dev_with_timeout $h1 297 setup_wait_dev_with_timeout $h2 298 ping_do $h1 192.0.2.2 299 check_fail $? "ping with different speeds autoneg on" 300 fi 301 302 log_test "advertise different speeds autoneg on" 303 304 ethtool -s $h2 autoneg on 305 ethtool -s $h1 autoneg on 306} 307 308trap cleanup EXIT 309 310setup_prepare 311setup_wait 312 313declare -gA speed_values 314eval "speed_values=($(speeds_arr_get))" 315 316tests_run 317 318exit $EXIT_STATUS 319