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