xref: /linux/tools/testing/selftests/drivers/net/hw/ethtool_rmon.sh (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#shellcheck disable=SC2034 # SC does not see the global variables
4#shellcheck disable=SC2317,SC2329 # unused functions
5
6ALL_TESTS="
7	rmon_rx_histogram
8	rmon_tx_histogram
9"
10
11: "${DRIVER_TEST_CONFORMANT:=yes}"
12NUM_NETIFS=2
13lib_dir=$(dirname "$0")
14source "$lib_dir"/../../../net/forwarding/lib.sh
15source "$lib_dir"/../../../kselftest/ktap_helpers.sh
16
17UINT32_MAX=$((2**32 - 1))
18ETH_FCS_LEN=4
19ETH_HLEN=$((6+6+2))
20TEST_NAME=$(basename "$0" .sh)
21
22declare -A netif_mtu
23
24ensure_mtu()
25{
26	local iface=$1; shift
27	local len=$1; shift
28	local required=$((len - ETH_HLEN - ETH_FCS_LEN))
29	local current
30
31	current=$(run_on "$iface" \
32		ip -j link show dev "$iface" | jq -r '.[0].mtu')
33	if [ "$current" -lt "$required" ]; then
34		run_on "$iface" ip link set dev "$iface" mtu "$required" \
35			|| return 1
36	fi
37}
38
39bucket_test()
40{
41	local iface=$1; shift
42	local neigh=$1; shift
43	local set=$1; shift
44	local bucket=$1; shift
45	local len=$1; shift
46	local num_rx=10000
47	local num_tx=20000
48	local expected=
49	local before=
50	local after=
51	local delta=
52
53	# Mausezahn does not include FCS bytes in its length - but the
54	# histogram counters do
55	len=$((len - ETH_FCS_LEN))
56	len=$((len > 0 ? len : 0))
57
58	before=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
59		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
60
61	# Send 10k one way and 20k in the other, to detect counters
62	# mapped to the wrong direction
63	run_on "$neigh" \
64		"$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us
65	run_on "$iface" \
66		"$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us
67
68	after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
69		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
70
71	delta=$((after - before))
72
73	expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx")
74
75	[ "$delta" -ge "$expected" ] && [ "$delta" -le "$UINT32_MAX" ]
76}
77
78rmon_histogram()
79{
80	local iface=$1; shift
81	local neigh=$1; shift
82	local set=$1; shift
83	local nbuckets=0
84	local step=
85
86	while read -r -a bucket; do
87		step="$set-pkts${bucket[0]}to${bucket[1]}"
88
89		for if in "$iface" "$neigh"; do
90			if ! ensure_mtu "$if" "${bucket[0]}"; then
91				ktap_print_msg "$if does not support the required MTU for $step"
92				ktap_test_xfail "$TEST_NAME.$step"
93				return
94			fi
95		done
96
97		if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then
98			ktap_test_fail "$TEST_NAME.$step"
99			return 1
100		fi
101		ktap_test_pass "$TEST_NAME.$step"
102		nbuckets=$((nbuckets + 1))
103	done < <(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \
104		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
105
106	if [ "$nbuckets" -eq 0 ]; then
107		ktap_print_msg "$iface does not support $set histogram counters"
108		return
109	fi
110}
111
112rmon_rx_histogram()
113{
114	rmon_histogram "$h1" "$h2" rx
115}
116
117rmon_tx_histogram()
118{
119	rmon_histogram "$h1" "$h2" tx
120}
121
122setup_prepare()
123{
124	h1=${NETIFS[p1]}
125	h2=${NETIFS[p2]}
126
127	for iface in "$h1" "$h2"; do
128		netif_mtu["$iface"]=$(run_on "$iface" \
129			ip -j link show dev "$iface" | jq -r '.[0].mtu')
130	done
131}
132
133cleanup()
134{
135	pre_cleanup
136
137	# Do not bring down the interfaces, just configure the initial MTU
138	for iface in "$h2" "$h1"; do
139		run_on "$iface" ip link set dev "$iface" \
140			mtu "${netif_mtu[$iface]}"
141	done
142}
143
144check_ethtool_counter_group_support
145trap cleanup EXIT
146
147bucket_count=$(ethtool --json -S "${NETIFS[p1]}" --groups rmon | \
148	jq -r '.[0].rmon |
149		"\((."rx-pktsNtoM" | length) +
150		   (."tx-pktsNtoM" | length))"')
151ktap_print_header
152ktap_set_plan "$bucket_count"
153
154setup_prepare
155setup_wait
156
157tests_run
158
159ktap_finished
160