Add a new selftest - ethtool_std_stats.sh - which validates the
eth-ctrl, eth-mac and pause standard statistics exported by an
interface. Collision related eth-mac counters as well as the error ones
will be checked against zero since that is the most likely correct
scenario.

The central part of this patch is the traffic_test() function which
gathers the 'before' counter values, sends a batch of traffic and then
interrogates again the same counters in order to determine if the delta
is on target. The function receives an array through which the caller
can request what counters to be interrogated and, for each of them, what
is their target delta value.

The output from this selftest looks as follows on a LX2160ARDB board:

 $ ./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
 # TEST: eth-ctrl-MACControlFramesTransmitted on endpmac17             [ OK ]
 # TEST: eth-ctrl-MACControlFramesReceived on endpmac17                [ OK ]
 # TEST: eth-mac-FrameCheckSequenceErrors on endpmac17                 [ OK ]
 # TEST: eth-mac-AlignmentErrors on endpmac17                          [ OK ]
 # TEST: eth-mac-FramesLostDueToIntMACXmitError on endpmac17           [ OK ]
 # TEST: eth-mac-CarrierSenseErrors on endpmac17 (not supported)       [SKIP]
 # TEST: eth-mac-FramesLostDueToIntMACRcvError on endpmac17            [ OK ]
 # TEST: eth-mac-InRangeLengthErrors on endpmac17 (not supported)      [SKIP]
 # TEST: eth-mac-OutOfRangeLengthField on endpmac17 (not supported)    [SKIP]
 # TEST: eth-mac-FrameTooLongErrors on endpmac17 (not supported)       [SKIP]
 # TEST: eth-mac-FramesAbortedDueToXSColls on endpmac17 (not supported)  [SKIP]
 # TEST: eth-mac-SingleCollisionFrames on endpmac17 (not supported)    [SKIP]
 # TEST: eth-mac-MultipleCollisionFrames on endpmac17 (not supported)  [SKIP]
 # TEST: eth-mac-FramesWithDeferredXmissions on endpmac17 (not supported)  
[SKIP]
 # TEST: eth-mac-LateCollisions on endpmac17 (not supported)           [SKIP]
 # TEST: eth-mac-FramesWithExcessiveDeferral on endpmac17 (not supported)  
[SKIP]
 # TEST: eth-mac-BroadcastFramesXmittedOK on endpmac17                 [ OK ]
 # TEST: eth-mac-OctetsTransmittedOK on endpmac17                      [ OK ]
 # TEST: eth-mac-BroadcastFramesReceivedOK on endpmac17                [ OK ]
 # TEST: eth-mac-OctetsReceivedOK on endpmac17                         [ OK ]
 # TEST: eth-mac-FramesTransmittedOK on endpmac17                      [ OK ]
 # TEST: eth-mac-MulticastFramesXmittedOK on endpmac17                 [ OK ]
 # TEST: eth-mac-FramesReceivedOK on endpmac17                         [ OK ]
 # TEST: eth-mac-MulticastFramesReceivedOK on endpmac17                [ OK ]
 # TEST: pause-tx_pause_frames on endpmac17                            [ OK ]
 # TEST: pause-rx_pause_frames on endpmac17                            [ OK ]
 ok 1 selftests: drivers/net/hw: ethtool_std_stats.sh # SKIP

Please note that not all MACs are counting the software injected pause
frames as real Tx pause. For example, on a LS1028ARDB the selftest
output will reflect the fact that neither the ENETC MAC, nor the Felix
switch MAC are able to detect Tx pause frames injected by software.

 $ ./run_kselftest.sh -t drivers/net/hw:ethtool_std_stats.sh
 (...)
 # TEST: pause-tx_pause_frames on eno0 (software sent pause frames not 
detected)  [XFAIL]
 # TEST: pause-rx_pause_frames on eno0                                 [ OK ]

Signed-off-by: Ioana Ciornei <[email protected]>
---
Changes in v2:
- Use the new run_on helper
- No longer checking that each counter has a 1% tolerance against the
  target. The only upper limit is UINT32_MAX.
- Check that both the error counters and the collision related ones are
  zero since this is the most probable scenario (we don't expect errors
  with the traffic that we are sending).
- Removed any checks performed on the remot interface counters since
  that is being used only as a traffic generator.

 .../testing/selftests/drivers/net/hw/Makefile |   1 +
 .../drivers/net/hw/ethtool_std_stats.sh       | 187 ++++++++++++++++++
 2 files changed, 188 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh

diff --git a/tools/testing/selftests/drivers/net/hw/Makefile 
b/tools/testing/selftests/drivers/net/hw/Makefile
index 91df028abfc0..2b185d2fa32e 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -26,6 +26,7 @@ TEST_PROGS = \
        ethtool_extended_state.sh \
        ethtool_mm.sh \
        ethtool_rmon.sh \
+       ethtool_std_stats.sh \
        hw_stats_l3.sh \
        hw_stats_l3_gre.sh \
        iou-zcrx.py \
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh 
b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
new file mode 100755
index 000000000000..b411a0c80bde
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
@@ -0,0 +1,187 @@
+#!/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
+"
+STABLE_MAC_ADDRS=yes
+NUM_NETIFS=2
+lib_dir=$(dirname "$0")
+# shellcheck source=./../../../net/forwarding/lib.sh
+source "$lib_dir"/../../../net/forwarding/lib.sh
+
+UINT32_MAX=$((2**32 - 1))
+
+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 counter 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 counter target exact_check xfail_message <<< 
"${counters[$i]}"
+
+               before[i]=$(ethtool_std_stats_get "$int" "$grp" "$counter" 
"$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 counter target exact_check xfail_message <<< 
"${counters[$i]}"
+
+               after[i]=$(ethtool_std_stats_get "$int" "$grp" "$counter" 
"$src")
+               if [[ "${after[$i]}" == "null" ]]; then
+                       log_test_skip "$grp-$counter on $int" "not supported"
+                       continue;
+               fi
+
+               delta=$((after[i] - before[i]))
+
+               RET=0
+               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
+                       log_test_xfail "$grp-$counter on $int" "$xfail_message"
+                       continue;
+               fi
+               check_err "$err" "$grp-$counter is not valid on $int (expected 
$target, got $delta)"
+               log_test "$grp-$counter on $int"
+       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[@]}"
+}
+
+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 ucast_pkt_format="-a own -b $h2_mac -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[@]}"
+}
+
+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
+                       log_test_skip "No support for pause frames, skip tests"
+                       exit
+               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[@]}"
+}
+
+setup_prepare()
+{
+       local iface
+
+       h1=${NETIFS[p1]}
+       h2=${NETIFS[p2]}
+
+       h2_mac=$(mac_get "$h2")
+}
+
+check_ethtool_counter_group_support
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit "$EXIT_STATUS"
-- 
2.25.1


Reply via email to