Commit f72e2f48 authored by Danielle Ratson's avatar Danielle Ratson Committed by Jakub Kicinski
Browse files

net: selftests: Add lanes setting test



Test that setting lanes parameter is working.

Set max speed and max lanes in the list of advertised link modes,
and then try to set max speed with the lanes below max lanes if exists
in the list.

And then, test that setting number of lanes larger than max lanes fails.

Do the above for both autoneg on and off.

$ ./ethtool_lanes.sh

TEST: 4 lanes is autonegotiated                                     [ OK ]
TEST: Lanes number larger than max width is not set                 [ OK ]
TEST: Autoneg off, 4 lanes detected during force mode               [ OK ]
TEST: Lanes number larger than max width is not set                 [ OK ]

Signed-off-by: default avatarDanielle Ratson <danieller@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 25a96f05
Loading
Loading
Loading
Loading
+187 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

lib_dir=$(dirname $0)/../../../net/forwarding

ALL_TESTS="
	autoneg
	autoneg_force_mode
"

NUM_NETIFS=2
: ${TIMEOUT:=30000} # ms
source $lib_dir/lib.sh
source $lib_dir/ethtool_lib.sh

setup_prepare()
{
	swp1=${NETIFS[p1]}
	swp2=${NETIFS[p2]}

	ip link set dev $swp1 up
	ip link set dev $swp2 up

	busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
	check_err $? "ports did not come up"

	local lanes_exist=$(ethtool $swp1 | grep 'Lanes:')
	if [[ -z $lanes_exist ]]; then
		log_test "SKIP: driver does not support lanes setting"
		exit 1
	fi

	ip link set dev $swp2 down
	ip link set dev $swp1 down
}

check_lanes()
{
	local dev=$1; shift
	local lanes=$1; shift
	local max_speed=$1; shift
	local chosen_lanes

	chosen_lanes=$(ethtool $dev | grep 'Lanes:')
	chosen_lanes=${chosen_lanes#*"Lanes: "}

	((chosen_lanes == lanes))
	check_err $? "swp1 advertise $max_speed and $lanes, devs sync to $chosen_lanes"
}

check_unsupported_lanes()
{
	local dev=$1; shift
	local max_speed=$1; shift
	local max_lanes=$1; shift
	local autoneg=$1; shift
	local autoneg_str=""

	local unsupported_lanes=$((max_lanes *= 2))

	if [[ $autoneg -eq 0 ]]; then
		autoneg_str="autoneg off"
	fi

	ethtool -s $swp1 speed $max_speed lanes $unsupported_lanes $autoneg_str &> /dev/null
	check_fail $? "Unsuccessful $unsupported_lanes lanes setting was expected"
}

max_speed_and_lanes_get()
{
	local dev=$1; shift
	local arr=("$@")
	local max_lanes
	local max_speed
	local -a lanes_arr
	local -a speeds_arr
	local -a max_values

	for ((i=0; i<${#arr[@]}; i+=2)); do
		speeds_arr+=("${arr[$i]}")
		lanes_arr+=("${arr[i+1]}")
	done

	max_values+=($(get_max "${speeds_arr[@]}"))
	max_values+=($(get_max "${lanes_arr[@]}"))

	echo ${max_values[@]}
}

search_linkmode()
{
	local speed=$1; shift
	local lanes=$1; shift
	local arr=("$@")

	for ((i=0; i<${#arr[@]}; i+=2)); do
		if [[ $speed -eq ${arr[$i]} && $lanes -eq ${arr[i+1]} ]]; then
			return 1
		fi
	done
	return 0
}

autoneg()
{
	RET=0

	local lanes
	local max_speed
	local max_lanes

	local -a linkmodes_params=($(dev_linkmodes_params_get $swp1 1))
	local -a max_values=($(max_speed_and_lanes_get $swp1 "${linkmodes_params[@]}"))
	max_speed=${max_values[0]}
	max_lanes=${max_values[1]}

	lanes=$max_lanes

	while [[ $lanes -ge 1 ]]; do
		search_linkmode $max_speed $lanes "${linkmodes_params[@]}"
		if [[ $? -eq 1 ]]; then
			ethtool_set $swp1 speed $max_speed lanes $lanes
			ip link set dev $swp1 up
			ip link set dev $swp2 up
			busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
			check_err $? "ports did not come up"

			check_lanes $swp1 $lanes $max_speed
			log_test "$lanes lanes is autonegotiated"
		fi
		let $((lanes /= 2))
	done

	check_unsupported_lanes $swp1 $max_speed $max_lanes 1
	log_test "Lanes number larger than max width is not set"

	ip link set dev $swp2 down
	ip link set dev $swp1 down
}

autoneg_force_mode()
{
	RET=0

	local lanes
	local max_speed
	local max_lanes

	local -a linkmodes_params=($(dev_linkmodes_params_get $swp1 1))
	local -a max_values=($(max_speed_and_lanes_get $swp1 "${linkmodes_params[@]}"))
	max_speed=${max_values[0]}
	max_lanes=${max_values[1]}

	lanes=$max_lanes

	while [[ $lanes -ge 1 ]]; do
		search_linkmode $max_speed $lanes "${linkmodes_params[@]}"
		if [[ $? -eq 1 ]]; then
			ethtool_set $swp1 speed $max_speed lanes $lanes autoneg off
			ethtool_set $swp2 speed $max_speed lanes $lanes autoneg off
			ip link set dev $swp1 up
			ip link set dev $swp2 up
			busywait "$TIMEOUT" wait_for_port_up ethtool $swp2
			check_err $? "ports did not come up"

			check_lanes $swp1 $lanes $max_speed
			log_test "Autoneg off, $lanes lanes detected during force mode"
		fi
		let $((lanes /= 2))
	done

	check_unsupported_lanes $swp1 $max_speed $max_lanes 0
	log_test "Lanes number larger than max width is not set"

	ip link set dev $swp2 down
	ip link set dev $swp1 down

	ethtool -s $swp2 autoneg on
	ethtool -s $swp1 autoneg on
}

check_ethtool_lanes_support
setup_prepare

tests_run

exit $EXIT_STATUS
+34 −0
Original line number Diff line number Diff line
@@ -22,6 +22,40 @@ ethtool_set()
	check_err $out "error in configuration. $cmd"
}

dev_linkmodes_params_get()
{
	local dev=$1; shift
	local adver=$1; shift
	local -a linkmodes_params
	local param_count
	local arr

	if (($adver)); then
		mode="Advertised link modes"
	else
		mode="Supported link modes"
	fi

	local -a dev_linkmodes=($(dev_speeds_get $dev 1 $adver))
	for ((i=0; i<${#dev_linkmodes[@]}; i++)); do
		linkmodes_params[$i]=$(echo -e "${dev_linkmodes[$i]}" | \
			# Replaces all non numbers with spaces
			sed -e 's/[^0-9]/ /g' | \
			# Squeeze spaces in sequence to 1 space
			tr -s ' ')
		# Count how many numbers were found in the linkmode
		param_count=$(echo "${linkmodes_params[$i]}" | wc -w)
		if [[ $param_count -eq 1 ]]; then
			linkmodes_params[$i]="${linkmodes_params[$i]} 1"
		elif [[ $param_count -ge 3 ]]; then
			arr=(${linkmodes_params[$i]})
			# Take only first two params
			linkmodes_params[$i]=$(echo "${arr[@]:0:2}")
		fi
	done
	echo ${linkmodes_params[@]}
}

dev_speeds_get()
{
	local dev=$1; shift
+28 −0
Original line number Diff line number Diff line
@@ -69,6 +69,15 @@ check_tc_action_hw_stats_support()
	fi
}

check_ethtool_lanes_support()
{
	ethtool --help 2>&1| grep lanes &> /dev/null
	if [[ $? -ne 0 ]]; then
		echo "SKIP: ethtool too old; it is missing lanes support"
		exit 1
	fi
}

if [[ "$(id -u)" -ne 0 ]]; then
	echo "SKIP: need root privileges"
	exit 0
@@ -263,6 +272,20 @@ not()
	[[ $? != 0 ]]
}

get_max()
{
	local arr=("$@")

	max=${arr[0]}
	for cur in ${arr[@]}; do
		if [[ $cur -gt $max ]]; then
			max=$cur
		fi
	done

	echo $max
}

grep_bridge_fdb()
{
	local addr=$1; shift
@@ -279,6 +302,11 @@ grep_bridge_fdb()
	$@ | grep $addr | grep $flag "$word"
}

wait_for_port_up()
{
	"$@" | grep -q "Link detected: yes"
}

wait_for_offload()
{
	"$@" | grep -q offload