| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| |
| ALL_TESTS=" |
| same_speeds_autoneg_off |
| different_speeds_autoneg_off |
| combination_of_neg_on_and_off |
| advertise_subset_of_speeds |
| check_highest_speed_is_chosen |
| different_speeds_autoneg_on |
| " |
| NUM_NETIFS=2 |
| lib_dir=$(dirname "$0") |
| source "$lib_dir"/../../../net/forwarding/lib.sh |
| source ethtool_lib.sh |
| |
| h1_create() |
| { |
| simple_if_init $h1 192.0.2.1/24 |
| } |
| |
| h1_destroy() |
| { |
| simple_if_fini $h1 192.0.2.1/24 |
| } |
| |
| h2_create() |
| { |
| simple_if_init $h2 192.0.2.2/24 |
| } |
| |
| h2_destroy() |
| { |
| simple_if_fini $h2 192.0.2.2/24 |
| } |
| |
| setup_prepare() |
| { |
| h1=${NETIFS[p1]} |
| h2=${NETIFS[p2]} |
| |
| h1_create |
| h2_create |
| } |
| |
| cleanup() |
| { |
| pre_cleanup |
| |
| h2_destroy |
| h1_destroy |
| } |
| |
| same_speeds_autoneg_off() |
| { |
| # Check that when each of the reported speeds is forced, the links come |
| # up and are operational. |
| local -a speeds_arr=($(common_speeds_get $h1 $h2 0 0)) |
| |
| for speed in "${speeds_arr[@]}"; do |
| RET=0 |
| ethtool_set $h1 speed $speed autoneg off |
| ethtool_set $h2 speed $speed autoneg off |
| |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| ping_do $h1 192.0.2.2 |
| check_err $? "ping with speed $speed autoneg off" |
| log_test "force speed $speed on both ends" |
| done |
| |
| ethtool -s $h2 autoneg on |
| ethtool -s $h1 autoneg on |
| } |
| |
| different_speeds_autoneg_off() |
| { |
| # Test that when we force different speeds, links are not up and ping |
| # fails. |
| RET=0 |
| |
| local -a speeds_arr=($(different_speeds_get $h1 $h2 0 0)) |
| local speed1=${speeds_arr[0]} |
| local speed2=${speeds_arr[1]} |
| |
| ethtool_set $h1 speed $speed1 autoneg off |
| ethtool_set $h2 speed $speed2 autoneg off |
| |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| ping_do $h1 192.0.2.2 |
| check_fail $? "ping with different speeds" |
| |
| log_test "force of different speeds autoneg off" |
| |
| ethtool -s $h2 autoneg on |
| ethtool -s $h1 autoneg on |
| } |
| |
| combination_of_neg_on_and_off() |
| { |
| # Test that when one device is forced to a speed supported by both |
| # endpoints and the other device is configured to autoneg on, the links |
| # are up and ping passes. |
| local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1)) |
| |
| for speed in "${speeds_arr[@]}"; do |
| RET=0 |
| ethtool_set $h1 speed $speed autoneg off |
| |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| ping_do $h1 192.0.2.2 |
| check_err $? "ping with h1-speed=$speed autoneg off, h2 autoneg on" |
| log_test "force speed $speed vs. autoneg" |
| done |
| |
| ethtool -s $h1 autoneg on |
| } |
| |
| hex_speed_value_get() |
| { |
| local speed=$1; shift |
| |
| local shift_size=${speed_values[$speed]} |
| speed=$((0x1 << $"shift_size")) |
| printf "%#x" "$speed" |
| } |
| |
| subset_of_common_speeds_get() |
| { |
| local dev1=$1; shift |
| local dev2=$1; shift |
| local adver=$1; shift |
| |
| local -a speeds_arr=($(common_speeds_get $dev1 $dev2 0 $adver)) |
| local speed_to_advertise=0 |
| local speed_to_remove=${speeds_arr[0]} |
| speed_to_remove+='base' |
| |
| local -a speeds_mode_arr=($(common_speeds_get $dev1 $dev2 1 $adver)) |
| |
| for speed in ${speeds_mode_arr[@]}; do |
| if [[ $speed != $speed_to_remove* ]]; then |
| speed=$(hex_speed_value_get $speed) |
| speed_to_advertise=$(($speed_to_advertise | \ |
| $speed)) |
| fi |
| |
| done |
| |
| # Convert to hex. |
| printf "%#x" "$speed_to_advertise" |
| } |
| |
| speed_to_advertise_get() |
| { |
| # The function returns the hex number that is composed by OR-ing all |
| # the modes corresponding to the provided speed. |
| local speed_without_mode=$1; shift |
| local supported_speeds=("$@"); shift |
| local speed_to_advertise=0 |
| |
| speed_without_mode+='base' |
| |
| for speed in ${supported_speeds[@]}; do |
| if [[ $speed == $speed_without_mode* ]]; then |
| speed=$(hex_speed_value_get $speed) |
| speed_to_advertise=$(($speed_to_advertise | \ |
| $speed)) |
| fi |
| |
| done |
| |
| # Convert to hex. |
| printf "%#x" "$speed_to_advertise" |
| } |
| |
| advertise_subset_of_speeds() |
| { |
| # Test that when one device advertises a subset of speeds and another |
| # advertises a specific speed (but all modes of this speed), the links |
| # are up and ping passes. |
| RET=0 |
| |
| local speed_1_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1) |
| ethtool_set $h1 advertise $speed_1_to_advertise |
| |
| if [ $RET != 0 ]; then |
| log_test "advertise subset of speeds" |
| return |
| fi |
| |
| local -a speeds_arr_without_mode=($(common_speeds_get $h1 $h2 0 1)) |
| # Check only speeds that h1 advertised. Remove the first speed. |
| unset speeds_arr_without_mode[0] |
| local -a speeds_arr_with_mode=($(common_speeds_get $h1 $h2 1 1)) |
| |
| for speed_value in ${speeds_arr_without_mode[@]}; do |
| RET=0 |
| local speed_2_to_advertise=$(speed_to_advertise_get $speed_value \ |
| "${speeds_arr_with_mode[@]}") |
| ethtool_set $h2 advertise $speed_2_to_advertise |
| |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| ping_do $h1 192.0.2.2 |
| check_err $? "ping with h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)" |
| |
| log_test "advertise $speed_1_to_advertise vs. $speed_2_to_advertise" |
| done |
| |
| ethtool -s $h2 autoneg on |
| ethtool -s $h1 autoneg on |
| } |
| |
| check_highest_speed_is_chosen() |
| { |
| # Test that when one device advertises a subset of speeds, the other |
| # chooses the highest speed. This test checks configuration without |
| # traffic. |
| RET=0 |
| |
| local max_speed |
| local chosen_speed |
| local speed_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1) |
| |
| ethtool_set $h1 advertise $speed_to_advertise |
| |
| if [ $RET != 0 ]; then |
| log_test "check highest speed" |
| return |
| fi |
| |
| local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1)) |
| |
| max_speed=${speeds_arr[0]} |
| for current in ${speeds_arr[@]}; do |
| if [[ $current -gt $max_speed ]]; then |
| max_speed=$current |
| fi |
| done |
| |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| chosen_speed=$(ethtool $h1 | grep 'Speed:') |
| chosen_speed=${chosen_speed%"Mb/s"*} |
| chosen_speed=${chosen_speed#*"Speed: "} |
| ((chosen_speed == max_speed)) |
| check_err $? "h1 advertise $speed_to_advertise, h2 sync to speed $chosen_speed" |
| |
| log_test "check highest speed" |
| |
| ethtool -s $h2 autoneg on |
| ethtool -s $h1 autoneg on |
| } |
| |
| different_speeds_autoneg_on() |
| { |
| # Test that when we configure links to advertise different speeds, |
| # links are not up and ping fails. |
| RET=0 |
| |
| local -a speeds=($(different_speeds_get $h1 $h2 1 1)) |
| local speed1=${speeds[0]} |
| local speed2=${speeds[1]} |
| |
| speed1=$(hex_speed_value_get $speed1) |
| speed2=$(hex_speed_value_get $speed2) |
| |
| ethtool_set $h1 advertise $speed1 |
| ethtool_set $h2 advertise $speed2 |
| |
| if (($RET)); then |
| setup_wait_dev_with_timeout $h1 |
| setup_wait_dev_with_timeout $h2 |
| ping_do $h1 192.0.2.2 |
| check_fail $? "ping with different speeds autoneg on" |
| fi |
| |
| log_test "advertise different speeds autoneg on" |
| |
| ethtool -s $h2 autoneg on |
| ethtool -s $h1 autoneg on |
| } |
| |
| trap cleanup EXIT |
| |
| setup_prepare |
| setup_wait |
| |
| declare -gA speed_values |
| eval "speed_values=($(speeds_arr_get))" |
| |
| tests_run |
| |
| exit $EXIT_STATUS |