Some devices refresh the statistics exposed via ethtool only
periodically, every stats-block-usecs (as reported by ethtool -c).
ethtool_std_stats and ethtool_rmon sample the counters immediately
after generating traffic, so on such devices they can read stale
values and fail with a delta short of the packets just sent.

Add a hw_stats_settle() helper which sleeps for 1.25x the configured
stats-block-usecs (defaulting to 20ms when the device reports no, or
a zero, period). Use it for ethtool std stats and RMON.
The 1.25x/20msec heuristic matches what the Python tests do.

Signed-off-by: Jakub Kicinski <[email protected]>
---
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
---
 .../selftests/drivers/net/hw/ethtool_rmon.sh      |  2 ++
 .../selftests/drivers/net/hw/ethtool_std_stats.sh |  2 ++
 tools/testing/selftests/net/forwarding/lib.sh     | 15 +++++++++++++++
 3 files changed, 19 insertions(+)

diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh 
b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
index 2ec19edddfaa..a074834cbe59 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh
@@ -65,6 +65,8 @@ bucket_test()
        run_on "$iface" \
                "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
 
+       hw_stats_settle "$iface"
+
        after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
                jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
 
diff --git a/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh 
b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
index 1b329b3f60c2..09f8128c51f3 100755
--- a/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
+++ b/tools/testing/selftests/drivers/net/hw/ethtool_std_stats.sh
@@ -48,6 +48,8 @@ traffic_test()
        # shellcheck disable=SC2086 # needs split options
        run_on "$neigh" "$MZ" "$neigh" -q -d 10usec -c "$num_rx" $pkt_format
 
+       hw_stats_settle "$int"
+
        for i in "${!counters[@]}"; do
                read -r int grp cnt target exact_check xfail_message \
                        <<< "${counters[$i]}"
diff --git a/tools/testing/selftests/net/forwarding/lib.sh 
b/tools/testing/selftests/net/forwarding/lib.sh
index ac8358bcb22c..05acd4011456 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -406,6 +406,21 @@ get_ifname_by_ip()
        __run_on "$target" ip -j addr show to "$ip_addr" | jq -r '.[].ifname'
 }
 
+# Wait for the device to refresh its HW statistics. Devices latch the stats
+# reported via ethtool only every stats-block-usecs, so sample after that.
+hw_stats_settle()
+{
+       local iface=$1; shift
+       local usecs
+
+       # Match only a non-zero integer; 0 or "n/a" use default (20msec)
+       usecs=$(run_on "$iface" ethtool -c "$iface" 2>/dev/null | \
+               sed -n 's/^stats-block-usecs:[[:space:]]*\([1-9][0-9]*\)$/\1/p')
+       usecs=${usecs:-20000}
+
+       sleep "$(echo "$usecs * 1.25 / 1000 / 1000" | bc -l)"
+}
+
 # Whether the test is conforming to the requirements and usage described in
 # drivers/net/README.rst.
 : "${DRIVER_TEST_CONFORMANT:=no}"
-- 
2.55.0


Reply via email to