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:
Paolo Abeni 2026-04-02 12:11:05 +02:00
commit ae04bff949
6 changed files with 422 additions and 52 deletions

View File

@ -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
~~~~~~~~~~~~~~~~~~~

View File

@ -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 \

View File

@ -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

View 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

View File

@ -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()

View File

@ -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; "$@"
}