mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 20:46:48 +02:00
Merge branch 'selftests-drivers-bash-support-for-remote-traffic-generators'
Ioana Ciornei says: ==================== selftests: drivers: bash support for remote traffic generators This patch set aims to add the necessary support so that bash written selftests are also able to easily run with a remote traffic generator system, either be it in another netns or one accessible through ssh. This patch set is a result of the discussion from v1: https://lore.kernel.org/all/20260303084330.340b6459@kernel.org/ Even though the python infrastructure is already established, some things are easier in bash and it would be a shame to leave behind the bash tests that we already have. This support is based on the requirements described in the tools/testing/selftests/drivers/net/README.rst file. Mainly, the drivers/net selftests should be able to run on a interface specified through the NETIF env variable. On top of that, variables such as REMOTE_TYPE and REMOTE_ARGS define how the remote traffic generator can be accessed. Patch 3/10 parses these env variables and constructs the NETIFS array that bash tests are accustomed to. This is with the intention of enabling already written tests to incur minimal changes. The second patch also defines the TARGETS array which will hold the necessary information about the target on which a specific interface is located. For example, a net.config which looks like below: NETIF=eth0 LOCAL_V4=192.168.1.1 REMOTE_V4=192.168.1.2 REMOTE_TYPE=ssh REMOTE_ARGS=root@192.168.1.2 will generate the NETIFS and TARGETS arrays with the following data. NETIFS[p1]="eth0" NETIFS[p2]="eth2" TARGETS[eth0]="local:" TARGETS[eth2]="ssh:root@192.168.1.2" The above will be true if on the remote target, the interface which has the 192.168.1.2 address is named eth2. The values held in the TARGETS array will be used by the new 'run_on' helper added in patch 2/10 to know how to run a specific command, on the local system, on another netns or by using ssh. Patch 4/10 updates some helpers to use run_on so that, for example, lib.sh is able to ensure stable MAC addresses even with the remote interface located in another netns. The next 5 patches, 5/10-9/10 update the ethtool_rmon.sh script so that it can work with the kselftest infrastructure and the new NETIF/REMOTE_TYPE etc way of working. Beside updating each ip link or ethtool command to use the run_on helper, the patches also remove any testing done on the remote interface. The last patch adds a new test which checks the standard counters - eth-ctrl, eth-mac and pause - and uses the new infrastructure put in place by the first patches. With this patch set, both tests can be run using a net.config file and run_kselftest.sh as shown below. $ make -C tools/testing/selftests/ TARGETS="drivers/net drivers/net/hw" \ install INSTALL_PATH=/tmp/ksft-net-drv $ cd /tmp/ksft-net-drv/ $ cat > ./drivers/net/net.config <<EOF NETIF=endpmac17 LOCAL_V4=17.0.0.1 REMOTE_V4=17.0.0.2 REMOTE_TYPE=ssh REMOTE_ARGS=root@192.168.5.200 EOF $ ./run_kselftest.sh -t drivers/net/hw:ethtool_rmon.sh TAP version 13 1..1 # timeout set to 0 # selftests: drivers/net/hw: ethtool_rmon.sh # TAP version 13 # 1..14 # ok 1 ethtool_rmon.rx-pkts64to64 # ok 2 ethtool_rmon.rx-pkts65to127 # ok 3 ethtool_rmon.rx-pkts128to255 # ok 4 ethtool_rmon.rx-pkts256to511 # ok 5 ethtool_rmon.rx-pkts512to1023 # ok 6 ethtool_rmon.rx-pkts1024to1518 # ok 7 ethtool_rmon.rx-pkts1519to10240 # ok 8 ethtool_rmon.tx-pkts64to64 # ok 9 ethtool_rmon.tx-pkts65to127 # ok 10 ethtool_rmon.tx-pkts128to255 # ok 11 ethtool_rmon.tx-pkts256to511 # ok 12 ethtool_rmon.tx-pkts512to1023 # ok 13 ethtool_rmon.tx-pkts1024to1518 # ok 14 ethtool_rmon.tx-pkts1519to10240 # # Totals: pass:14 fail:0 xfail:0 xpass:0 skip:0 error:0 ok 1 selftests: drivers/net/hw: ethtool_rmon.sh $ ./run_kselftest.sh -t drivers/net/hw:ethtool_std_stats.sh TAP version 13 1..1 # timeout set to 0 # selftests: drivers/net/hw: ethtool_std_stats.sh # TAP version 13 # 1..26 # ok 1 ethtool_std_stats.eth-ctrl-MACControlFramesTransmitted # ok 2 ethtool_std_stats.eth-ctrl-MACControlFramesReceived # ok 3 ethtool_std_stats.eth-mac-FrameCheckSequenceErrors # ok 4 ethtool_std_stats.eth-mac-AlignmentErrors # ok 5 ethtool_std_stats.eth-mac-FramesLostDueToIntMACXmitError # ok 6 ethtool_std_stats.eth-mac-CarrierSenseErrors # SKIP # ok 7 ethtool_std_stats.eth-mac-FramesLostDueToIntMACRcvError # ok 8 ethtool_std_stats.eth-mac-InRangeLengthErrors # SKIP # ok 9 ethtool_std_stats.eth-mac-OutOfRangeLengthField # SKIP # ok 10 ethtool_std_stats.eth-mac-FrameTooLongErrors # SKIP # ok 11 ethtool_std_stats.eth-mac-FramesAbortedDueToXSColls # SKIP # ok 12 ethtool_std_stats.eth-mac-SingleCollisionFrames # SKIP # ok 13 ethtool_std_stats.eth-mac-MultipleCollisionFrames # SKIP # ok 14 ethtool_std_stats.eth-mac-FramesWithDeferredXmissions # SKIP # ok 15 ethtool_std_stats.eth-mac-LateCollisions # SKIP # ok 16 ethtool_std_stats.eth-mac-FramesWithExcessiveDeferral # SKIP # ok 17 ethtool_std_stats.eth-mac-BroadcastFramesXmittedOK # ok 18 ethtool_std_stats.eth-mac-OctetsTransmittedOK # ok 19 ethtool_std_stats.eth-mac-BroadcastFramesReceivedOK # ok 20 ethtool_std_stats.eth-mac-OctetsReceivedOK # ok 21 ethtool_std_stats.eth-mac-FramesTransmittedOK # ok 22 ethtool_std_stats.eth-mac-MulticastFramesXmittedOK # ok 23 ethtool_std_stats.eth-mac-FramesReceivedOK # ok 24 ethtool_std_stats.eth-mac-MulticastFramesReceivedOK # ok 25 ethtool_std_stats.pause-tx_pause_frames # ok 26 ethtool_std_stats.pause-rx_pause_frames # # 10 skipped test(s) detected. Consider enabling relevant config options to improve coverage. # # Totals: pass:16 fail:0 xfail:0 xpass:0 skip:10 error:0 ok 1 selftests: drivers/net/hw: ethtool_std_stats.sh ==================== Link: https://patch.msgid.link/20260330152933.2195885-1-ioana.ciornei@nxp.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
ae04bff949
|
|
@ -26,6 +26,10 @@ The netdevice against which tests will be run must exist, be running
|
|||
Refer to list of :ref:`Variables` later in this file to set up running
|
||||
the tests against a real device.
|
||||
|
||||
The current support for bash tests restricts the use of the same interface name
|
||||
on the local system and the remote one and will bail if this case is
|
||||
encountered.
|
||||
|
||||
Both modes required
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ TEST_PROGS = \
|
|||
ethtool_extended_state.sh \
|
||||
ethtool_mm.sh \
|
||||
ethtool_rmon.sh \
|
||||
ethtool_std_stats.sh \
|
||||
gro_hw.py \
|
||||
hw_stats_l3.sh \
|
||||
hw_stats_l3_gre.sh \
|
||||
|
|
|
|||
|
|
@ -1,17 +1,23 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#shellcheck disable=SC2034 # SC does not see the global variables
|
||||
#shellcheck disable=SC2317,SC2329 # unused functions
|
||||
|
||||
ALL_TESTS="
|
||||
rmon_rx_histogram
|
||||
rmon_tx_histogram
|
||||
"
|
||||
|
||||
: "${DRIVER_TEST_CONFORMANT:=yes}"
|
||||
NUM_NETIFS=2
|
||||
lib_dir=$(dirname "$0")
|
||||
source "$lib_dir"/../../../net/forwarding/lib.sh
|
||||
source "$lib_dir"/../../../kselftest/ktap_helpers.sh
|
||||
|
||||
UINT32_MAX=$((2**32 - 1))
|
||||
ETH_FCS_LEN=4
|
||||
ETH_HLEN=$((6+6+2))
|
||||
TEST_NAME=$(basename "$0" .sh)
|
||||
|
||||
declare -A netif_mtu
|
||||
|
||||
|
|
@ -19,11 +25,14 @@ ensure_mtu()
|
|||
{
|
||||
local iface=$1; shift
|
||||
local len=$1; shift
|
||||
local current=$(ip -j link show dev $iface | jq -r '.[0].mtu')
|
||||
local required=$((len - ETH_HLEN - ETH_FCS_LEN))
|
||||
local current
|
||||
|
||||
if [ $current -lt $required ]; then
|
||||
ip link set dev $iface mtu $required || return 1
|
||||
current=$(run_on "$iface" \
|
||||
ip -j link show dev "$iface" | jq -r '.[0].mtu')
|
||||
if [ "$current" -lt "$required" ]; then
|
||||
run_on "$iface" ip link set dev "$iface" mtu "$required" \
|
||||
|| return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -46,23 +55,24 @@ bucket_test()
|
|||
len=$((len - ETH_FCS_LEN))
|
||||
len=$((len > 0 ? len : 0))
|
||||
|
||||
before=$(ethtool --json -S $iface --groups rmon | \
|
||||
before=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
|
||||
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
|
||||
|
||||
# Send 10k one way and 20k in the other, to detect counters
|
||||
# mapped to the wrong direction
|
||||
$MZ $neigh -q -c $num_rx -p $len -a own -b bcast -d 10us
|
||||
$MZ $iface -q -c $num_tx -p $len -a own -b bcast -d 10us
|
||||
run_on "$neigh" \
|
||||
"$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us
|
||||
run_on "$iface" \
|
||||
"$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
|
||||
|
||||
after=$(ethtool --json -S $iface --groups rmon | \
|
||||
after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
|
||||
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
|
||||
|
||||
delta=$((after - before))
|
||||
|
||||
expected=$([ $set = rx ] && echo $num_rx || echo $num_tx)
|
||||
expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx")
|
||||
|
||||
# Allow some extra tolerance for other packets sent by the stack
|
||||
[ $delta -ge $expected ] && [ $delta -le $((expected + 100)) ]
|
||||
[ "$delta" -ge "$expected" ] && [ "$delta" -le "$UINT32_MAX" ]
|
||||
}
|
||||
|
||||
rmon_histogram()
|
||||
|
|
@ -73,43 +83,40 @@ rmon_histogram()
|
|||
local nbuckets=0
|
||||
local step=
|
||||
|
||||
RET=0
|
||||
|
||||
while read -r -a bucket; do
|
||||
step="$set-pkts${bucket[0]}to${bucket[1]} on $iface"
|
||||
step="$set-pkts${bucket[0]}to${bucket[1]}"
|
||||
|
||||
for if in $iface $neigh; do
|
||||
if ! ensure_mtu $if ${bucket[0]}; then
|
||||
log_test_xfail "$if does not support the required MTU for $step"
|
||||
for if in "$iface" "$neigh"; do
|
||||
if ! ensure_mtu "$if" "${bucket[0]}"; then
|
||||
ktap_print_msg "$if does not support the required MTU for $step"
|
||||
ktap_test_xfail "$TEST_NAME.$step"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
if ! bucket_test $iface $neigh $set $nbuckets ${bucket[0]}; then
|
||||
check_err 1 "$step failed"
|
||||
if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then
|
||||
ktap_test_fail "$TEST_NAME.$step"
|
||||
return 1
|
||||
fi
|
||||
log_test "$step"
|
||||
ktap_test_pass "$TEST_NAME.$step"
|
||||
nbuckets=$((nbuckets + 1))
|
||||
done < <(ethtool --json -S $iface --groups rmon | \
|
||||
done < <(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
|
||||
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
|
||||
|
||||
if [ $nbuckets -eq 0 ]; then
|
||||
log_test_xfail "$iface does not support $set histogram counters"
|
||||
if [ "$nbuckets" -eq 0 ]; then
|
||||
ktap_print_msg "$iface does not support $set histogram counters"
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
rmon_rx_histogram()
|
||||
{
|
||||
rmon_histogram $h1 $h2 rx
|
||||
rmon_histogram $h2 $h1 rx
|
||||
rmon_histogram "$h1" "$h2" rx
|
||||
}
|
||||
|
||||
rmon_tx_histogram()
|
||||
{
|
||||
rmon_histogram $h1 $h2 tx
|
||||
rmon_histogram $h2 $h1 tx
|
||||
rmon_histogram "$h1" "$h2" tx
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
|
|
@ -117,9 +124,9 @@ setup_prepare()
|
|||
h1=${NETIFS[p1]}
|
||||
h2=${NETIFS[p2]}
|
||||
|
||||
for iface in $h1 $h2; do
|
||||
netif_mtu[$iface]=$(ip -j link show dev $iface | jq -r '.[0].mtu')
|
||||
ip link set dev $iface up
|
||||
for iface in "$h1" "$h2"; do
|
||||
netif_mtu["$iface"]=$(run_on "$iface" \
|
||||
ip -j link show dev "$iface" | jq -r '.[0].mtu')
|
||||
done
|
||||
}
|
||||
|
||||
|
|
@ -127,19 +134,26 @@ cleanup()
|
|||
{
|
||||
pre_cleanup
|
||||
|
||||
for iface in $h2 $h1; do
|
||||
ip link set dev $iface \
|
||||
mtu ${netif_mtu[$iface]} \
|
||||
down
|
||||
# Do not bring down the interfaces, just configure the initial MTU
|
||||
for iface in "$h2" "$h1"; do
|
||||
run_on "$iface" ip link set dev "$iface" \
|
||||
mtu "${netif_mtu[$iface]}"
|
||||
done
|
||||
}
|
||||
|
||||
check_ethtool_counter_group_support
|
||||
trap cleanup EXIT
|
||||
|
||||
bucket_count=$(ethtool --json -S "${NETIFS[p1]}" --groups rmon | \
|
||||
jq -r '.[0].rmon |
|
||||
"\((."rx-pktsNtoM" | length) +
|
||||
(."tx-pktsNtoM" | length))"')
|
||||
ktap_print_header
|
||||
ktap_set_plan "$bucket_count"
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
||||
ktap_finished
|
||||
|
|
|
|||
206
tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
Executable file
206
tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
Executable file
|
|
@ -0,0 +1,206 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#shellcheck disable=SC2034 # SC does not see the global variables
|
||||
#shellcheck disable=SC2317,SC2329 # unused functions
|
||||
|
||||
ALL_TESTS="
|
||||
test_eth_ctrl_stats
|
||||
test_eth_mac_stats
|
||||
test_pause_stats
|
||||
"
|
||||
: "${DRIVER_TEST_CONFORMANT:=yes}"
|
||||
STABLE_MAC_ADDRS=yes
|
||||
NUM_NETIFS=2
|
||||
lib_dir=$(dirname "$0")
|
||||
# shellcheck source=./../../../net/forwarding/lib.sh
|
||||
source "$lib_dir"/../../../net/forwarding/lib.sh
|
||||
# shellcheck source=./../../../kselftest/ktap_helpers.sh
|
||||
source "$lib_dir"/../../../kselftest/ktap_helpers.sh
|
||||
|
||||
UINT32_MAX=$((2**32 - 1))
|
||||
SUBTESTS=0
|
||||
TEST_NAME=$(basename "$0" .sh)
|
||||
|
||||
traffic_test()
|
||||
{
|
||||
local iface=$1; shift
|
||||
local neigh=$1; shift
|
||||
local num_tx=$1; shift
|
||||
local pkt_format="$1"; shift
|
||||
local -a counters=("$@")
|
||||
local int grp cnt target exact_check
|
||||
local before after delta
|
||||
local num_rx=$((num_tx * 2))
|
||||
local xfail_message
|
||||
local src="aggregate"
|
||||
local i
|
||||
|
||||
for i in "${!counters[@]}"; do
|
||||
read -r int grp cnt target exact_check xfail_message \
|
||||
<<< "${counters[$i]}"
|
||||
|
||||
before[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src")
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086 # needs split options
|
||||
run_on "$iface" "$MZ" "$iface" -q -c "$num_tx" $pkt_format
|
||||
|
||||
# shellcheck disable=SC2086 # needs split options
|
||||
run_on "$neigh" "$MZ" "$neigh" -q -c "$num_rx" $pkt_format
|
||||
|
||||
for i in "${!counters[@]}"; do
|
||||
read -r int grp cnt target exact_check xfail_message \
|
||||
<<< "${counters[$i]}"
|
||||
|
||||
after[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src")
|
||||
if [[ "${after[$i]}" == "null" ]]; then
|
||||
ktap_test_skip "$TEST_NAME.$grp-$cnt"
|
||||
continue;
|
||||
fi
|
||||
|
||||
delta=$((after[i] - before[i]))
|
||||
|
||||
if [ "$exact_check" -ne 0 ]; then
|
||||
[ "$delta" -eq "$target" ]
|
||||
else
|
||||
[ "$delta" -ge "$target" ] && \
|
||||
[ "$delta" -le "$UINT32_MAX" ]
|
||||
fi
|
||||
err="$?"
|
||||
|
||||
if [[ $err != 0 ]] && [[ -n $xfail_message ]]; then
|
||||
ktap_print_msg "$xfail_message"
|
||||
ktap_test_xfail "$TEST_NAME.$grp-$cnt"
|
||||
continue;
|
||||
fi
|
||||
|
||||
if [[ $err != 0 ]]; then
|
||||
ktap_print_msg "$grp-$cnt is not valid on $int (expected $target, got $delta)"
|
||||
ktap_test_fail "$TEST_NAME.$grp-$cnt"
|
||||
else
|
||||
ktap_test_pass "$TEST_NAME.$grp-$cnt"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
test_eth_ctrl_stats()
|
||||
{
|
||||
local pkt_format="-a own -b bcast 88:08 -p 64"
|
||||
local num_pkts=1000
|
||||
local -a counters
|
||||
|
||||
counters=("$h1 eth-ctrl MACControlFramesTransmitted $num_pkts 0")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 eth-ctrl MACControlFramesReceived $num_pkts 0")
|
||||
traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \
|
||||
"${counters[@]}"
|
||||
}
|
||||
SUBTESTS=$((SUBTESTS + 2))
|
||||
|
||||
test_eth_mac_stats()
|
||||
{
|
||||
local pkt_size=100
|
||||
local pkt_size_fcs=$((pkt_size + 4))
|
||||
local bcast_pkt_format="-a own -b bcast -p $pkt_size"
|
||||
local mcast_pkt_format="-a own -b 01:00:5E:00:00:01 -p $pkt_size"
|
||||
local num_pkts=2000
|
||||
local octets=$((pkt_size_fcs * num_pkts))
|
||||
local -a counters error_cnt collision_cnt
|
||||
|
||||
# Error counters should be exactly zero
|
||||
counters=("$h1 eth-mac FrameCheckSequenceErrors 0 1"
|
||||
"$h1 eth-mac AlignmentErrors 0 1"
|
||||
"$h1 eth-mac FramesLostDueToIntMACXmitError 0 1"
|
||||
"$h1 eth-mac CarrierSenseErrors 0 1"
|
||||
"$h1 eth-mac FramesLostDueToIntMACRcvError 0 1"
|
||||
"$h1 eth-mac InRangeLengthErrors 0 1"
|
||||
"$h1 eth-mac OutOfRangeLengthField 0 1"
|
||||
"$h1 eth-mac FrameTooLongErrors 0 1"
|
||||
"$h1 eth-mac FramesAbortedDueToXSColls 0 1")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
# Collision related counters should also be zero
|
||||
counters=("$h1 eth-mac SingleCollisionFrames 0 1"
|
||||
"$h1 eth-mac MultipleCollisionFrames 0 1"
|
||||
"$h1 eth-mac FramesWithDeferredXmissions 0 1"
|
||||
"$h1 eth-mac LateCollisions 0 1"
|
||||
"$h1 eth-mac FramesWithExcessiveDeferral 0 1")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 eth-mac BroadcastFramesXmittedOK $num_pkts 0"
|
||||
"$h1 eth-mac OctetsTransmittedOK $octets 0")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 eth-mac BroadcastFramesReceivedOK $num_pkts 0"
|
||||
"$h1 eth-mac OctetsReceivedOK $octets 0")
|
||||
traffic_test "$h2" "$h1" "$num_pkts" "$bcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 eth-mac FramesTransmittedOK $num_pkts 0"
|
||||
"$h1 eth-mac MulticastFramesXmittedOK $num_pkts 0")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$mcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 eth-mac FramesReceivedOK $num_pkts 0"
|
||||
"$h1 eth-mac MulticastFramesReceivedOK $num_pkts 0")
|
||||
traffic_test "$h2" "$h1" "$num_pkts" "$mcast_pkt_format" \
|
||||
"${counters[@]}"
|
||||
}
|
||||
SUBTESTS=$((SUBTESTS + 22))
|
||||
|
||||
test_pause_stats()
|
||||
{
|
||||
local pkt_format="-a own -b 01:80:c2:00:00:01 88:08:00:01:00:01"
|
||||
local xfail_message="software sent pause frames not detected"
|
||||
local num_pkts=2000
|
||||
local -a counters
|
||||
local int
|
||||
local i
|
||||
|
||||
# Check that there is pause frame support
|
||||
for ((i = 1; i <= NUM_NETIFS; ++i)); do
|
||||
int="${NETIFS[p$i]}"
|
||||
if ! run_on "$int" ethtool -I --json -a "$int" > /dev/null 2>&1; then
|
||||
ktap_test_skip "$TEST_NAME.tx_pause_frames"
|
||||
ktap_test_skip "$TEST_NAME.rx_pause_frames"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
counters=("$h1 pause tx_pause_frames $num_pkts 0 $xfail_message")
|
||||
traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \
|
||||
"${counters[@]}"
|
||||
|
||||
counters=("$h1 pause rx_pause_frames $num_pkts 0")
|
||||
traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \
|
||||
"${counters[@]}"
|
||||
}
|
||||
SUBTESTS=$((SUBTESTS + 2))
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
local iface
|
||||
|
||||
h1=${NETIFS[p1]}
|
||||
h2=${NETIFS[p2]}
|
||||
|
||||
h2_mac=$(mac_get "$h2")
|
||||
}
|
||||
|
||||
ktap_print_header
|
||||
ktap_set_plan $SUBTESTS
|
||||
|
||||
check_ethtool_counter_group_support
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
ktap_finished
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#shellcheck disable=SC2034 # SC doesn't see our uses of global variables
|
||||
|
||||
##############################################################################
|
||||
# Topology description. p1 looped back to p2, p3 to p4 and so on.
|
||||
|
|
@ -340,17 +341,144 @@ fi
|
|||
##############################################################################
|
||||
# Command line options handling
|
||||
|
||||
count=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
if [[ "$count" -eq "0" ]]; then
|
||||
unset NETIFS
|
||||
declare -A NETIFS
|
||||
check_env() {
|
||||
if [[ ! (( -n "$LOCAL_V4" && -n "$REMOTE_V4") ||
|
||||
( -n "$LOCAL_V6" && -n "$REMOTE_V6" )) ]]; then
|
||||
echo "SKIP: Invalid environment, missing or inconsistent LOCAL_V4/REMOTE_V4/LOCAL_V6/REMOTE_V6"
|
||||
echo "Please see tools/testing/selftests/drivers/net/README.rst"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
count=$((count + 1))
|
||||
NETIFS[p$count]="$1"
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -z "$REMOTE_TYPE" ]]; then
|
||||
echo "SKIP: Invalid environment, missing REMOTE_TYPE"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
|
||||
if [[ -z "$REMOTE_ARGS" ]]; then
|
||||
echo "SKIP: Invalid environment, missing REMOTE_ARGS"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
}
|
||||
|
||||
__run_on()
|
||||
{
|
||||
local target=$1; shift
|
||||
local type args
|
||||
|
||||
IFS=':' read -r type args <<< "$target"
|
||||
|
||||
case "$type" in
|
||||
netns)
|
||||
# Execute command in network namespace
|
||||
# args contains the namespace name
|
||||
ip netns exec "$args" "$@"
|
||||
;;
|
||||
ssh)
|
||||
# Execute command via SSH args contains user@host
|
||||
ssh -n "$args" "$@"
|
||||
;;
|
||||
local|*)
|
||||
# Execute command locally. This is also the fallback
|
||||
# case for when the interface's target is not found in
|
||||
# the TARGETS array.
|
||||
"$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_on()
|
||||
{
|
||||
local iface=$1; shift
|
||||
local target="local:"
|
||||
|
||||
if [ "${DRIVER_TEST_CONFORMANT}" = "yes" ]; then
|
||||
target="${TARGETS[$iface]}"
|
||||
fi
|
||||
|
||||
__run_on "$target" "$@"
|
||||
}
|
||||
|
||||
get_ifname_by_ip()
|
||||
{
|
||||
local target=$1; shift
|
||||
local ip_addr=$1; shift
|
||||
|
||||
__run_on "$target" ip -j addr show to "$ip_addr" | jq -r '.[].ifname'
|
||||
}
|
||||
|
||||
# Whether the test is conforming to the requirements and usage described in
|
||||
# drivers/net/README.rst.
|
||||
: "${DRIVER_TEST_CONFORMANT:=no}"
|
||||
|
||||
declare -A TARGETS
|
||||
|
||||
# Based on DRIVER_TEST_CONFORMANT, decide if to source drivers/net/net.config
|
||||
# or not. In the "yes" case, the test expects to pass the arguments through the
|
||||
# variables specified in drivers/net/README.rst file. If not, fallback on
|
||||
# parsing the script arguments for interface names.
|
||||
if [ "${DRIVER_TEST_CONFORMANT}" = "yes" ]; then
|
||||
if [[ -f $net_forwarding_dir/../../drivers/net/net.config ]]; then
|
||||
source "$net_forwarding_dir/../../drivers/net/net.config"
|
||||
fi
|
||||
|
||||
if (( NUM_NETIFS > 2)); then
|
||||
echo "SKIP: DRIVER_TEST_CONFORMANT=yes and NUM_NETIFS is bigger than 2"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
|
||||
check_env
|
||||
|
||||
# Populate the NETIFS and TARGETS arrays automatically based on the
|
||||
# environment variables. The TARGETS array is indexed by the network
|
||||
# interface name keeping track of the target on which the interface
|
||||
# resides. Values will be strings of the following format -
|
||||
# <type>:<args>.
|
||||
#
|
||||
# TARGETS[eth0]="local:" - meaning that the eth0 interface is
|
||||
# accessible locally
|
||||
# TARGETS[eth1]="netns:foo" - eth1 is in the foo netns
|
||||
# TARGETS[eth2]="ssh:root@10.0.0.2" - eth2 is accessible through
|
||||
# running the 'ssh root@10.0.0.2' command.
|
||||
|
||||
unset NETIFS
|
||||
declare -A NETIFS
|
||||
|
||||
NETIFS[p1]="$NETIF"
|
||||
TARGETS[$NETIF]="local:"
|
||||
|
||||
# Locate the name of the remote interface
|
||||
remote_target="$REMOTE_TYPE:$REMOTE_ARGS"
|
||||
if [[ -v REMOTE_V4 ]]; then
|
||||
remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V4")
|
||||
else
|
||||
remote_netif=$(get_ifname_by_ip "$remote_target" "$REMOTE_V6")
|
||||
fi
|
||||
if [[ ! -n "$remote_netif" ]]; then
|
||||
echo "SKIP: cannot find remote interface"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
|
||||
if [[ "$NETIF" == "$remote_netif" ]]; then
|
||||
echo "SKIP: local and remote interfaces cannot have the same name"
|
||||
exit "$ksft_skip"
|
||||
fi
|
||||
|
||||
NETIFS[p2]="$remote_netif"
|
||||
TARGETS[$remote_netif]="$REMOTE_TYPE:$REMOTE_ARGS"
|
||||
else
|
||||
count=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
if [[ "$count" -eq "0" ]]; then
|
||||
unset NETIFS
|
||||
declare -A NETIFS
|
||||
fi
|
||||
count=$((count + 1))
|
||||
NETIFS[p$count]="$1"
|
||||
TARGETS[$1]="local:"
|
||||
shift
|
||||
done
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Network interfaces configuration
|
||||
|
|
@ -418,10 +546,11 @@ mac_addr_prepare()
|
|||
dev=${NETIFS[p$i]}
|
||||
new_addr=$(printf "00:01:02:03:04:%02x" $i)
|
||||
|
||||
MAC_ADDR_ORIG["$dev"]=$(ip -j link show dev $dev | jq -e '.[].address')
|
||||
MAC_ADDR_ORIG["$dev"]=$(run_on "$dev" \
|
||||
ip -j link show dev "$dev" | jq -e '.[].address')
|
||||
# Strip quotes
|
||||
MAC_ADDR_ORIG["$dev"]=${MAC_ADDR_ORIG["$dev"]//\"/}
|
||||
ip link set dev $dev address $new_addr
|
||||
run_on "$dev" ip link set dev "$dev" address $new_addr
|
||||
done
|
||||
}
|
||||
|
||||
|
|
@ -431,7 +560,8 @@ mac_addr_restore()
|
|||
|
||||
for ((i = 1; i <= NUM_NETIFS; ++i)); do
|
||||
dev=${NETIFS[p$i]}
|
||||
ip link set dev $dev address ${MAC_ADDR_ORIG["$dev"]}
|
||||
run_on "$dev" \
|
||||
ip link set dev "$dev" address ${MAC_ADDR_ORIG["$dev"]}
|
||||
done
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +574,9 @@ if [[ "$STABLE_MAC_ADDRS" = "yes" ]]; then
|
|||
fi
|
||||
|
||||
for ((i = 1; i <= NUM_NETIFS; ++i)); do
|
||||
ip link show dev ${NETIFS[p$i]} &> /dev/null
|
||||
int="${NETIFS[p$i]}"
|
||||
|
||||
run_on "$int" ip link show dev "$int" &> /dev/null
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "SKIP: could not find all required interfaces"
|
||||
exit $ksft_skip
|
||||
|
|
@ -527,7 +659,7 @@ setup_wait_dev_with_timeout()
|
|||
local i
|
||||
|
||||
for ((i = 1; i <= $max_iterations; ++i)); do
|
||||
ip link show dev $dev up \
|
||||
run_on "$dev" ip link show dev "$dev" up \
|
||||
| grep 'state UP' &> /dev/null
|
||||
if [[ $? -ne 0 ]]; then
|
||||
sleep 1
|
||||
|
|
@ -831,8 +963,15 @@ ethtool_std_stats_get()
|
|||
local name=$1; shift
|
||||
local src=$1; shift
|
||||
|
||||
ethtool --json -S $dev --groups $grp -- --src $src | \
|
||||
jq '.[]."'"$grp"'"."'$name'"'
|
||||
if [[ "$grp" == "pause" ]]; then
|
||||
run_on "$dev" ethtool -I --json -a "$dev" --src "$src" | \
|
||||
jq --arg name "$name" '.[].statistics[$name]'
|
||||
return
|
||||
fi
|
||||
|
||||
run_on "$dev" \
|
||||
ethtool --json -S "$dev" --groups "$grp" -- --src "$src" | \
|
||||
jq --arg grp "$grp" --arg name "$name" '.[][$grp][$name]'
|
||||
}
|
||||
|
||||
qdisc_stats_get()
|
||||
|
|
|
|||
|
|
@ -514,7 +514,8 @@ mac_get()
|
|||
{
|
||||
local if_name=$1
|
||||
|
||||
ip -j link show dev $if_name | jq -r '.[]["address"]'
|
||||
run_on "$if_name" \
|
||||
ip -j link show dev "$if_name" | jq -r '.[]["address"]'
|
||||
}
|
||||
|
||||
kill_process()
|
||||
|
|
@ -670,3 +671,8 @@ cmd_jq()
|
|||
# return success only in case of non-empty output
|
||||
[ ! -z "$output" ]
|
||||
}
|
||||
|
||||
run_on()
|
||||
{
|
||||
shift; "$@"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user