18c2ecf20Sopenharmony_ci#!/bin/bash
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ciALL_TESTS="
58c2ecf20Sopenharmony_ci	same_speeds_autoneg_off
68c2ecf20Sopenharmony_ci	different_speeds_autoneg_off
78c2ecf20Sopenharmony_ci	combination_of_neg_on_and_off
88c2ecf20Sopenharmony_ci	advertise_subset_of_speeds
98c2ecf20Sopenharmony_ci	check_highest_speed_is_chosen
108c2ecf20Sopenharmony_ci	different_speeds_autoneg_on
118c2ecf20Sopenharmony_ci"
128c2ecf20Sopenharmony_ciNUM_NETIFS=2
138c2ecf20Sopenharmony_cisource lib.sh
148c2ecf20Sopenharmony_cisource ethtool_lib.sh
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cih1_create()
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	simple_if_init $h1 192.0.2.1/24
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cih1_destroy()
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	simple_if_fini $h1 192.0.2.1/24
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cih2_create()
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	simple_if_init $h2 192.0.2.2/24
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cih2_destroy()
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	simple_if_fini $h2 192.0.2.2/24
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cisetup_prepare()
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	h1=${NETIFS[p1]}
398c2ecf20Sopenharmony_ci	h2=${NETIFS[p2]}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	h1_create
428c2ecf20Sopenharmony_ci	h2_create
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cicleanup()
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	pre_cleanup
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	h2_destroy
508c2ecf20Sopenharmony_ci	h1_destroy
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cisame_speeds_autoneg_off()
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	# Check that when each of the reported speeds is forced, the links come
568c2ecf20Sopenharmony_ci	# up and are operational.
578c2ecf20Sopenharmony_ci	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 0))
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	for speed in "${speeds_arr[@]}"; do
608c2ecf20Sopenharmony_ci		RET=0
618c2ecf20Sopenharmony_ci		ethtool_set $h1 speed $speed autoneg off
628c2ecf20Sopenharmony_ci		ethtool_set $h2 speed $speed autoneg off
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h1
658c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h2
668c2ecf20Sopenharmony_ci		ping_do $h1 192.0.2.2
678c2ecf20Sopenharmony_ci		check_err $? "speed $speed autoneg off"
688c2ecf20Sopenharmony_ci		log_test "force of same speed autoneg off"
698c2ecf20Sopenharmony_ci		log_info "speed = $speed"
708c2ecf20Sopenharmony_ci	done
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	ethtool -s $h2 autoneg on
738c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cidifferent_speeds_autoneg_off()
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	# Test that when we force different speeds, links are not up and ping
798c2ecf20Sopenharmony_ci	# fails.
808c2ecf20Sopenharmony_ci	RET=0
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	local -a speeds_arr=($(different_speeds_get $h1 $h2 0 0))
838c2ecf20Sopenharmony_ci	local speed1=${speeds_arr[0]}
848c2ecf20Sopenharmony_ci	local speed2=${speeds_arr[1]}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	ethtool_set $h1 speed $speed1 autoneg off
878c2ecf20Sopenharmony_ci	ethtool_set $h2 speed $speed2 autoneg off
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	setup_wait_dev_with_timeout $h1
908c2ecf20Sopenharmony_ci	setup_wait_dev_with_timeout $h2
918c2ecf20Sopenharmony_ci	ping_do $h1 192.0.2.2
928c2ecf20Sopenharmony_ci	check_fail $? "ping with different speeds"
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	log_test "force of different speeds autoneg off"
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	ethtool -s $h2 autoneg on
978c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cicombination_of_neg_on_and_off()
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	# Test that when one device is forced to a speed supported by both
1038c2ecf20Sopenharmony_ci	# endpoints and the other device is configured to autoneg on, the links
1048c2ecf20Sopenharmony_ci	# are up and ping passes.
1058c2ecf20Sopenharmony_ci	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1))
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	for speed in "${speeds_arr[@]}"; do
1088c2ecf20Sopenharmony_ci		RET=0
1098c2ecf20Sopenharmony_ci		ethtool_set $h1 speed $speed autoneg off
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h1
1128c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h2
1138c2ecf20Sopenharmony_ci		ping_do $h1 192.0.2.2
1148c2ecf20Sopenharmony_ci		check_err $? "h1-speed=$speed autoneg off, h2 autoneg on"
1158c2ecf20Sopenharmony_ci		log_test "one side with autoneg off and another with autoneg on"
1168c2ecf20Sopenharmony_ci		log_info "force speed = $speed"
1178c2ecf20Sopenharmony_ci	done
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cihex_speed_value_get()
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	local speed=$1; shift
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	local shift_size=${speed_values[$speed]}
1278c2ecf20Sopenharmony_ci	speed=$((0x1 << $"shift_size"))
1288c2ecf20Sopenharmony_ci	printf "%#x" "$speed"
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cisubset_of_common_speeds_get()
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	local dev1=$1; shift
1348c2ecf20Sopenharmony_ci	local dev2=$1; shift
1358c2ecf20Sopenharmony_ci	local adver=$1; shift
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	local -a speeds_arr=($(common_speeds_get $dev1 $dev2 0 $adver))
1388c2ecf20Sopenharmony_ci	local speed_to_advertise=0
1398c2ecf20Sopenharmony_ci	local speed_to_remove=${speeds_arr[0]}
1408c2ecf20Sopenharmony_ci	speed_to_remove+='base'
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	local -a speeds_mode_arr=($(common_speeds_get $dev1 $dev2 1 $adver))
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	for speed in ${speeds_mode_arr[@]}; do
1458c2ecf20Sopenharmony_ci		if [[ $speed != $speed_to_remove* ]]; then
1468c2ecf20Sopenharmony_ci			speed=$(hex_speed_value_get $speed)
1478c2ecf20Sopenharmony_ci			speed_to_advertise=$(($speed_to_advertise | \
1488c2ecf20Sopenharmony_ci						$speed))
1498c2ecf20Sopenharmony_ci		fi
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	done
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	# Convert to hex.
1548c2ecf20Sopenharmony_ci	printf "%#x" "$speed_to_advertise"
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cispeed_to_advertise_get()
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	# The function returns the hex number that is composed by OR-ing all
1608c2ecf20Sopenharmony_ci	# the modes corresponding to the provided speed.
1618c2ecf20Sopenharmony_ci	local speed_without_mode=$1; shift
1628c2ecf20Sopenharmony_ci	local supported_speeds=("$@"); shift
1638c2ecf20Sopenharmony_ci	local speed_to_advertise=0
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	speed_without_mode+='base'
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	for speed in ${supported_speeds[@]}; do
1688c2ecf20Sopenharmony_ci		if [[ $speed == $speed_without_mode* ]]; then
1698c2ecf20Sopenharmony_ci			speed=$(hex_speed_value_get $speed)
1708c2ecf20Sopenharmony_ci			speed_to_advertise=$(($speed_to_advertise | \
1718c2ecf20Sopenharmony_ci						$speed))
1728c2ecf20Sopenharmony_ci		fi
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	done
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	# Convert to hex.
1778c2ecf20Sopenharmony_ci	printf "%#x" "$speed_to_advertise"
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ciadvertise_subset_of_speeds()
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	# Test that when one device advertises a subset of speeds and another
1838c2ecf20Sopenharmony_ci	# advertises a specific speed (but all modes of this speed), the links
1848c2ecf20Sopenharmony_ci	# are up and ping passes.
1858c2ecf20Sopenharmony_ci	RET=0
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	local speed_1_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1)
1888c2ecf20Sopenharmony_ci	ethtool_set $h1 advertise $speed_1_to_advertise
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if [ $RET != 0 ]; then
1918c2ecf20Sopenharmony_ci		log_test "advertise subset of speeds"
1928c2ecf20Sopenharmony_ci		return
1938c2ecf20Sopenharmony_ci	fi
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	local -a speeds_arr_without_mode=($(common_speeds_get $h1 $h2 0 1))
1968c2ecf20Sopenharmony_ci	# Check only speeds that h1 advertised. Remove the first speed.
1978c2ecf20Sopenharmony_ci	unset speeds_arr_without_mode[0]
1988c2ecf20Sopenharmony_ci	local -a speeds_arr_with_mode=($(common_speeds_get $h1 $h2 1 1))
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	for speed_value in ${speeds_arr_without_mode[@]}; do
2018c2ecf20Sopenharmony_ci		RET=0
2028c2ecf20Sopenharmony_ci		local speed_2_to_advertise=$(speed_to_advertise_get $speed_value \
2038c2ecf20Sopenharmony_ci			"${speeds_arr_with_mode[@]}")
2048c2ecf20Sopenharmony_ci		ethtool_set $h2 advertise $speed_2_to_advertise
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h1
2078c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h2
2088c2ecf20Sopenharmony_ci		ping_do $h1 192.0.2.2
2098c2ecf20Sopenharmony_ci		check_err $? "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise ($speed_value)"
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci		log_test "advertise subset of speeds"
2128c2ecf20Sopenharmony_ci		log_info "h1=$speed_1_to_advertise, h2=$speed_2_to_advertise"
2138c2ecf20Sopenharmony_ci	done
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	ethtool -s $h2 autoneg on
2168c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cicheck_highest_speed_is_chosen()
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	# Test that when one device advertises a subset of speeds, the other
2228c2ecf20Sopenharmony_ci	# chooses the highest speed. This test checks configuration without
2238c2ecf20Sopenharmony_ci	# traffic.
2248c2ecf20Sopenharmony_ci	RET=0
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	local max_speed
2278c2ecf20Sopenharmony_ci	local chosen_speed
2288c2ecf20Sopenharmony_ci	local speed_to_advertise=$(subset_of_common_speeds_get $h1 $h2 1)
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	ethtool_set $h1 advertise $speed_to_advertise
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	if [ $RET != 0 ]; then
2338c2ecf20Sopenharmony_ci		log_test "check highest speed"
2348c2ecf20Sopenharmony_ci		return
2358c2ecf20Sopenharmony_ci	fi
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	local -a speeds_arr=($(common_speeds_get $h1 $h2 0 1))
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	max_speed=${speeds_arr[0]}
2408c2ecf20Sopenharmony_ci	for current in ${speeds_arr[@]}; do
2418c2ecf20Sopenharmony_ci		if [[ $current -gt $max_speed ]]; then
2428c2ecf20Sopenharmony_ci			max_speed=$current
2438c2ecf20Sopenharmony_ci		fi
2448c2ecf20Sopenharmony_ci	done
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	setup_wait_dev_with_timeout $h1
2478c2ecf20Sopenharmony_ci	setup_wait_dev_with_timeout $h2
2488c2ecf20Sopenharmony_ci	chosen_speed=$(ethtool $h1 | grep 'Speed:')
2498c2ecf20Sopenharmony_ci	chosen_speed=${chosen_speed%"Mb/s"*}
2508c2ecf20Sopenharmony_ci	chosen_speed=${chosen_speed#*"Speed: "}
2518c2ecf20Sopenharmony_ci	((chosen_speed == max_speed))
2528c2ecf20Sopenharmony_ci	check_err $? "h1 advertise $speed_to_advertise, h2 sync to speed $chosen_speed"
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	log_test "check highest speed"
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	ethtool -s $h2 autoneg on
2578c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cidifferent_speeds_autoneg_on()
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	# Test that when we configure links to advertise different speeds,
2638c2ecf20Sopenharmony_ci	# links are not up and ping fails.
2648c2ecf20Sopenharmony_ci	RET=0
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	local -a speeds=($(different_speeds_get $h1 $h2 1 1))
2678c2ecf20Sopenharmony_ci	local speed1=${speeds[0]}
2688c2ecf20Sopenharmony_ci	local speed2=${speeds[1]}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	speed1=$(hex_speed_value_get $speed1)
2718c2ecf20Sopenharmony_ci	speed2=$(hex_speed_value_get $speed2)
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	ethtool_set $h1 advertise $speed1
2748c2ecf20Sopenharmony_ci	ethtool_set $h2 advertise $speed2
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (($RET)); then
2778c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h1
2788c2ecf20Sopenharmony_ci		setup_wait_dev_with_timeout $h2
2798c2ecf20Sopenharmony_ci		ping_do $h1 192.0.2.2
2808c2ecf20Sopenharmony_ci		check_fail $? "ping with different speeds autoneg on"
2818c2ecf20Sopenharmony_ci	fi
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	log_test "advertise different speeds autoneg on"
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	ethtool -s $h2 autoneg on
2868c2ecf20Sopenharmony_ci	ethtool -s $h1 autoneg on
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ciskip_on_veth
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_citrap cleanup EXIT
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_cisetup_prepare
2948c2ecf20Sopenharmony_cisetup_wait
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cideclare -gA speed_values
2978c2ecf20Sopenharmony_cieval "speed_values=($(speeds_arr_get))"
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_citests_run
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ciexit $EXIT_STATUS
302