164916b57SAmit Cohen#!/bin/bash
264916b57SAmit Cohen# SPDX-License-Identifier: GPL-2.0
364916b57SAmit Cohen
464916b57SAmit CohenALL_TESTS="
564916b57SAmit Cohen	same_speeds_autoneg_off
664916b57SAmit Cohen	different_speeds_autoneg_off
764916b57SAmit Cohen	combination_of_neg_on_and_off
864916b57SAmit Cohen	advertise_subset_of_speeds
964916b57SAmit Cohen	check_highest_speed_is_chosen
1064916b57SAmit Cohen	different_speeds_autoneg_on
1164916b57SAmit Cohen"
1264916b57SAmit CohenNUM_NETIFS=2
1364916b57SAmit Cohensource lib.sh
1464916b57SAmit Cohensource ethtool_lib.sh
1564916b57SAmit Cohen
1664916b57SAmit Cohenh1_create()
1764916b57SAmit Cohen{
1864916b57SAmit Cohen	simple_if_init $h1 192.0.2.1/24
1964916b57SAmit Cohen}
2064916b57SAmit Cohen
2164916b57SAmit Cohenh1_destroy()
2264916b57SAmit Cohen{
2364916b57SAmit Cohen	simple_if_fini $h1 192.0.2.1/24
2464916b57SAmit Cohen}
2564916b57SAmit Cohen
2664916b57SAmit Cohenh2_create()
2764916b57SAmit Cohen{
2864916b57SAmit Cohen	simple_if_init $h2 192.0.2.2/24
2964916b57SAmit Cohen}
3064916b57SAmit Cohen
3164916b57SAmit Cohenh2_destroy()
3264916b57SAmit Cohen{
3364916b57SAmit Cohen	simple_if_fini $h2 192.0.2.2/24
3464916b57SAmit Cohen}
3564916b57SAmit Cohen
3664916b57SAmit Cohensetup_prepare()
3764916b57SAmit Cohen{
3864916b57SAmit Cohen	h1=${NETIFS[p1]}
3964916b57SAmit Cohen	h2=${NETIFS[p2]}
4064916b57SAmit Cohen
4164916b57SAmit Cohen	h1_create
4264916b57SAmit Cohen	h2_create
4364916b57SAmit Cohen}
4464916b57SAmit Cohen
4564916b57SAmit Cohencleanup()
4664916b57SAmit Cohen{
4764916b57SAmit Cohen	pre_cleanup
4864916b57SAmit Cohen
4964916b57SAmit Cohen	h2_destroy
5064916b57SAmit Cohen	h1_destroy
5164916b57SAmit Cohen}
5264916b57SAmit Cohen
5364916b57SAmit Cohensame_speeds_autoneg_off()
5464916b57SAmit Cohen{
5564916b57SAmit Cohen	# Check that when each of the reported speeds is forced, the links come
5664916b57SAmit Cohen	# up and are operational.
5764916b57SAmit Cohen	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 0))
5864916b57SAmit Cohen
5964916b57SAmit Cohen	for speed in "${speeds_arr[@]}"; do
6064916b57SAmit Cohen		RET=0
6164916b57SAmit Cohen		ethtool_set $h1 speed $speed autoneg off
6264916b57SAmit Cohen		ethtool_set $h2 speed $speed autoneg off
6364916b57SAmit Cohen
6464916b57SAmit Cohen		setup_wait_dev_with_timeout $h1
6564916b57SAmit Cohen		setup_wait_dev_with_timeout $h2
6664916b57SAmit Cohen		ping_do $h1 192.0.2.2
6764916b57SAmit Cohen		check_err $? "speed $speed autoneg off"
6864916b57SAmit Cohen		log_test "force of same speed autoneg off"
6964916b57SAmit Cohen		log_info "speed = $speed"
7064916b57SAmit Cohen	done
7164916b57SAmit Cohen
7264916b57SAmit Cohen	ethtool -s $h2 autoneg on
7364916b57SAmit Cohen	ethtool -s $h1 autoneg on
7464916b57SAmit Cohen}
7564916b57SAmit Cohen
7664916b57SAmit Cohendifferent_speeds_autoneg_off()
7764916b57SAmit Cohen{
7864916b57SAmit Cohen	# Test that when we force different speeds, links are not up and ping
7964916b57SAmit Cohen	# fails.
8064916b57SAmit Cohen	RET=0
8164916b57SAmit Cohen
8264916b57SAmit Cohen	local -a speeds_arr=($(different_speeds_get $h1 $h2 0 0))
8364916b57SAmit Cohen	local speed1=${speeds_arr[0]}
8464916b57SAmit Cohen	local speed2=${speeds_arr[1]}
8564916b57SAmit Cohen
8664916b57SAmit Cohen	ethtool_set $h1 speed $speed1 autoneg off
8764916b57SAmit Cohen	ethtool_set $h2 speed $speed2 autoneg off
8864916b57SAmit Cohen
8964916b57SAmit Cohen	setup_wait_dev_with_timeout $h1
9064916b57SAmit Cohen	setup_wait_dev_with_timeout $h2
9164916b57SAmit Cohen	ping_do $h1 192.0.2.2
9264916b57SAmit Cohen	check_fail $? "ping with different speeds"
9364916b57SAmit Cohen
9464916b57SAmit Cohen	log_test "force of different speeds autoneg off"
9564916b57SAmit Cohen
9664916b57SAmit Cohen	ethtool -s $h2 autoneg on
9764916b57SAmit Cohen	ethtool -s $h1 autoneg on
9864916b57SAmit Cohen}
9964916b57SAmit Cohen
10064916b57SAmit Cohencombination_of_neg_on_and_off()
10164916b57SAmit Cohen{
10264916b57SAmit Cohen	# Test that when one device is forced to a speed supported by both
10364916b57SAmit Cohen	# endpoints and the other device is configured to autoneg on, the links
10464916b57SAmit Cohen	# are up and ping passes.
10564916b57SAmit Cohen	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1))
10664916b57SAmit Cohen
10764916b57SAmit Cohen	for speed in "${speeds_arr[@]}"; do
10864916b57SAmit Cohen		RET=0
10964916b57SAmit Cohen		ethtool_set $h1 speed $speed autoneg off
11064916b57SAmit Cohen
11164916b57SAmit Cohen		setup_wait_dev_with_timeout $h1
11264916b57SAmit Cohen		setup_wait_dev_with_timeout $h2
11364916b57SAmit Cohen		ping_do $h1 192.0.2.2
11464916b57SAmit Cohen		check_err $? "h1-speed=$speed autoneg off, h2 autoneg on"
11564916b57SAmit Cohen		log_test "one side with autoneg off and another with autoneg on"
11664916b57SAmit Cohen		log_info "force speed = $speed"
11764916b57SAmit Cohen	done
11864916b57SAmit Cohen
11964916b57SAmit Cohen	ethtool -s $h1 autoneg on
12064916b57SAmit Cohen}
12164916b57SAmit Cohen
12264916b57SAmit Cohenhex_speed_value_get()
12364916b57SAmit Cohen{
12464916b57SAmit Cohen	local speed=$1; shift
12564916b57SAmit Cohen
12664916b57SAmit Cohen	local shift_size=${speed_values[$speed]}
12764916b57SAmit Cohen	speed=$((0x1 << $"shift_size"))
12864916b57SAmit Cohen	printf "%#x" "$speed"
12964916b57SAmit Cohen}
13064916b57SAmit Cohen
13164916b57SAmit Cohensubset_of_common_speeds_get()
13264916b57SAmit Cohen{
13364916b57SAmit Cohen	local dev1=$1; shift
13464916b57SAmit Cohen	local dev2=$1; shift
13564916b57SAmit Cohen	local adver=$1; shift
13664916b57SAmit Cohen
13764916b57SAmit Cohen	local -a speeds_arr=($(common_speeds_get $dev1 $dev2 0 $adver))
13864916b57SAmit Cohen	local speed_to_advertise=0
13964916b57SAmit Cohen	local speed_to_remove=${speeds_arr[0]}
14064916b57SAmit Cohen	speed_to_remove+='base'
14164916b57SAmit Cohen
14264916b57SAmit Cohen	local -a speeds_mode_arr=($(common_speeds_get $dev1 $dev2 1 $adver))
14364916b57SAmit Cohen
14464916b57SAmit Cohen	for speed in ${speeds_mode_arr[@]}; do
14564916b57SAmit Cohen		if [[ $speed != $speed_to_remove* ]]; then
14664916b57SAmit Cohen			speed=$(hex_speed_value_get $speed)
14764916b57SAmit Cohen			speed_to_advertise=$(($speed_to_advertise | \
14864916b57SAmit Cohen						$speed))
14964916b57SAmit Cohen		fi
15064916b57SAmit Cohen
15164916b57SAmit Cohen	done
15264916b57SAmit Cohen
15364916b57SAmit Cohen	# Convert to hex.
15464916b57SAmit Cohen	printf "%#x" "$speed_to_advertise"
15564916b57SAmit Cohen}
15664916b57SAmit Cohen
15764916b57SAmit Cohenspeed_to_advertise_get()
15864916b57SAmit Cohen{
15964916b57SAmit Cohen	# The function returns the hex number that is composed by OR-ing all
16064916b57SAmit Cohen	# the modes corresponding to the provided speed.
16164916b57SAmit Cohen	local speed_without_mode=$1; shift
16264916b57SAmit Cohen	local supported_speeds=("$@"); shift
16364916b57SAmit Cohen	local speed_to_advertise=0
16464916b57SAmit Cohen
16564916b57SAmit Cohen	speed_without_mode+='base'
16664916b57SAmit Cohen
16764916b57SAmit Cohen	for speed in ${supported_speeds[@]}; do
16864916b57SAmit Cohen		if [[ $speed == $speed_without_mode* ]]; then
16964916b57SAmit Cohen			speed=$(hex_speed_value_get $speed)
17064916b57SAmit Cohen			speed_to_advertise=$(($speed_to_advertise | \
17164916b57SAmit Cohen						$speed))
17264916b57SAmit Cohen		fi
17364916b57SAmit Cohen
17464916b57SAmit Cohen	done
17564916b57SAmit Cohen
17664916b57SAmit Cohen	# Convert to hex.
17764916b57SAmit Cohen	printf "%#x" "$speed_to_advertise"
17864916b57SAmit Cohen}
17964916b57SAmit Cohen
18064916b57SAmit Cohenadvertise_subset_of_speeds()
18164916b57SAmit Cohen{
18264916b57SAmit Cohen	# Test that when one device advertises a subset of speeds and another
18364916b57SAmit Cohen	# advertises a specific speed (but all modes of this speed), the links
18464916b57SAmit Cohen	# are up and ping passes.
18564916b57SAmit Cohen	RET=0
18664916b57SAmit Cohen
18764916b57SAmit Cohen	local speed_1_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1)
18864916b57SAmit Cohen	ethtool_set $h1 advertise $speed_1_to_advertise
18964916b57SAmit Cohen
19064916b57SAmit Cohen	if [ $RET != 0 ]; then
19164916b57SAmit Cohen		log_test "advertise subset of speeds"
19264916b57SAmit Cohen		return
19364916b57SAmit Cohen	fi
19464916b57SAmit Cohen
19564916b57SAmit Cohen	local -a speeds_arr_without_mode=($(common_speeds_get $h1 $h2 0 1))
19664916b57SAmit Cohen	# Check only speeds that h1 advertised. Remove the first speed.
19764916b57SAmit Cohen	unset speeds_arr_without_mode[0]
19864916b57SAmit Cohen	local -a speeds_arr_with_mode=($(common_speeds_get $h1 $h2 1 1))
19964916b57SAmit Cohen
20064916b57SAmit Cohen	for speed_value in ${speeds_arr_without_mode[@]}; do
20164916b57SAmit Cohen		RET=0
20264916b57SAmit Cohen		local speed_2_to_advertise=$(speed_to_advertise_get $speed_value \
20364916b57SAmit Cohen			"${speeds_arr_with_mode[@]}")
20464916b57SAmit Cohen		ethtool_set $h2 advertise $speed_2_to_advertise
20564916b57SAmit Cohen
20664916b57SAmit Cohen		setup_wait_dev_with_timeout $h1
20764916b57SAmit Cohen		setup_wait_dev_with_timeout $h2
20864916b57SAmit Cohen		ping_do $h1 192.0.2.2
20964916b57SAmit Cohen		check_err $? "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)"
21064916b57SAmit Cohen
21164916b57SAmit Cohen		log_test "advertise subset of speeds"
21264916b57SAmit Cohen		log_info "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise"
21364916b57SAmit Cohen	done
21464916b57SAmit Cohen
21564916b57SAmit Cohen	ethtool -s $h2 autoneg on
21664916b57SAmit Cohen	ethtool -s $h1 autoneg on
21764916b57SAmit Cohen}
21864916b57SAmit Cohen
21964916b57SAmit Cohencheck_highest_speed_is_chosen()
22064916b57SAmit Cohen{
22164916b57SAmit Cohen	# Test that when one device advertises a subset of speeds, the other
22264916b57SAmit Cohen	# chooses the highest speed. This test checks configuration without
22364916b57SAmit Cohen	# traffic.
22464916b57SAmit Cohen	RET=0
22564916b57SAmit Cohen
22664916b57SAmit Cohen	local max_speed
22764916b57SAmit Cohen	local chosen_speed
22864916b57SAmit Cohen	local speed_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1)
22964916b57SAmit Cohen
23064916b57SAmit Cohen	ethtool_set $h1 advertise $speed_to_advertise
23164916b57SAmit Cohen
23264916b57SAmit Cohen	if [ $RET != 0 ]; then
23364916b57SAmit Cohen		log_test "check highest speed"
23464916b57SAmit Cohen		return
23564916b57SAmit Cohen	fi
23664916b57SAmit Cohen
23764916b57SAmit Cohen	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1))
23864916b57SAmit Cohen
23964916b57SAmit Cohen	max_speed=${speeds_arr[0]}
24064916b57SAmit Cohen	for current in ${speeds_arr[@]}; do
24164916b57SAmit Cohen		if [[ $current -gt $max_speed ]]; then
24264916b57SAmit Cohen			max_speed=$current
24364916b57SAmit Cohen		fi
24464916b57SAmit Cohen	done
24564916b57SAmit Cohen
24664916b57SAmit Cohen	setup_wait_dev_with_timeout $h1
24764916b57SAmit Cohen	setup_wait_dev_with_timeout $h2
24864916b57SAmit Cohen	chosen_speed=$(ethtool $h1 | grep 'Speed:')
24964916b57SAmit Cohen	chosen_speed=${chosen_speed%"Mb/s"*}
25064916b57SAmit Cohen	chosen_speed=${chosen_speed#*"Speed: "}
25164916b57SAmit Cohen	((chosen_speed == max_speed))
25264916b57SAmit Cohen	check_err $? "h1 advertise $speed_to_advertise, h2 sync to speed $chosen_speed"
25364916b57SAmit Cohen
25464916b57SAmit Cohen	log_test "check highest speed"
25564916b57SAmit Cohen
25664916b57SAmit Cohen	ethtool -s $h2 autoneg on
25764916b57SAmit Cohen	ethtool -s $h1 autoneg on
25864916b57SAmit Cohen}
25964916b57SAmit Cohen
26064916b57SAmit Cohendifferent_speeds_autoneg_on()
26164916b57SAmit Cohen{
26264916b57SAmit Cohen	# Test that when we configure links to advertise different speeds,
26364916b57SAmit Cohen	# links are not up and ping fails.
26464916b57SAmit Cohen	RET=0
26564916b57SAmit Cohen
26664916b57SAmit Cohen	local -a speeds=($(different_speeds_get $h1 $h2 1 1))
26764916b57SAmit Cohen	local speed1=${speeds[0]}
26864916b57SAmit Cohen	local speed2=${speeds[1]}
26964916b57SAmit Cohen
27064916b57SAmit Cohen	speed1=$(hex_speed_value_get $speed1)
27164916b57SAmit Cohen	speed2=$(hex_speed_value_get $speed2)
27264916b57SAmit Cohen
27364916b57SAmit Cohen	ethtool_set $h1 advertise $speed1
27464916b57SAmit Cohen	ethtool_set $h2 advertise $speed2
27564916b57SAmit Cohen
27664916b57SAmit Cohen	if (($RET)); then
27764916b57SAmit Cohen		setup_wait_dev_with_timeout $h1
27864916b57SAmit Cohen		setup_wait_dev_with_timeout $h2
27964916b57SAmit Cohen		ping_do $h1 192.0.2.2
28064916b57SAmit Cohen		check_fail $? "ping with different speeds autoneg on"
28164916b57SAmit Cohen	fi
28264916b57SAmit Cohen
28364916b57SAmit Cohen	log_test "advertise different speeds autoneg on"
28464916b57SAmit Cohen
28564916b57SAmit Cohen	ethtool -s $h2 autoneg on
28664916b57SAmit Cohen	ethtool -s $h1 autoneg on
28764916b57SAmit Cohen}
28864916b57SAmit Cohen
289*60a36e21SIdo Schimmelskip_on_veth
290*60a36e21SIdo Schimmel
29164916b57SAmit Cohentrap cleanup EXIT
29264916b57SAmit Cohen
29364916b57SAmit Cohensetup_prepare
29464916b57SAmit Cohensetup_wait
29564916b57SAmit Cohen
29664916b57SAmit Cohendeclare -gA speed_values
29764916b57SAmit Coheneval "speed_values=($(speeds_arr_get))"
29864916b57SAmit Cohen
29964916b57SAmit Cohentests_run
30064916b57SAmit Cohen
30164916b57SAmit Cohenexit $EXIT_STATUS
302