1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="
5	rmon_rx_histogram
6	rmon_tx_histogram
7"
8
9NUM_NETIFS=2
10source lib.sh
11
12ETH_FCS_LEN=4
13ETH_HLEN=$((6+6+2))
14
15declare -A netif_mtu
16
17ensure_mtu()
18{
19	local iface=$1; shift
20	local len=$1; shift
21	local current=$(ip -j link show dev $iface | jq -r '.[0].mtu')
22	local required=$((len - ETH_HLEN - ETH_FCS_LEN))
23
24	if [ $current -lt $required ]; then
25		ip link set dev $iface mtu $required || return 1
26	fi
27}
28
29bucket_test()
30{
31	local iface=$1; shift
32	local neigh=$1; shift
33	local set=$1; shift
34	local bucket=$1; shift
35	local len=$1; shift
36	local num_rx=10000
37	local num_tx=20000
38	local expected=
39	local before=
40	local after=
41	local delta=
42
43	# Mausezahn does not include FCS bytes in its length - but the
44	# histogram counters do
45	len=$((len - ETH_FCS_LEN))
46
47	before=$(ethtool --json -S $iface --groups rmon | \
48		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
49
50	# Send 10k one way and 20k in the other, to detect counters
51	# mapped to the wrong direction
52	$MZ $neigh -q -c $num_rx -p $len -a own -b bcast -d 10us
53	$MZ $iface -q -c $num_tx -p $len -a own -b bcast -d 10us
54
55	after=$(ethtool --json -S $iface --groups rmon | \
56		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
57
58	delta=$((after - before))
59
60	expected=$([ $set = rx ] && echo $num_rx || echo $num_tx)
61
62	# Allow some extra tolerance for other packets sent by the stack
63	[ $delta -ge $expected ] && [ $delta -le $((expected + 100)) ]
64}
65
66rmon_histogram()
67{
68	local iface=$1; shift
69	local neigh=$1; shift
70	local set=$1; shift
71	local nbuckets=0
72	local step=
73
74	RET=0
75
76	while read -r -a bucket; do
77		step="$set-pkts${bucket[0]}to${bucket[1]} on $iface"
78
79		for if in $iface $neigh; do
80			if ! ensure_mtu $if ${bucket[0]}; then
81				log_test_skip "$if does not support the required MTU for $step"
82				return
83			fi
84		done
85
86		if ! bucket_test $iface $neigh $set $nbuckets ${bucket[0]}; then
87			check_err 1 "$step failed"
88			return 1
89		fi
90		log_test "$step"
91		nbuckets=$((nbuckets + 1))
92	done < <(ethtool --json -S $iface --groups rmon | \
93		jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
94
95	if [ $nbuckets -eq 0 ]; then
96		log_test_skip "$iface does not support $set histogram counters"
97		return
98	fi
99}
100
101rmon_rx_histogram()
102{
103	rmon_histogram $h1 $h2 rx
104	rmon_histogram $h2 $h1 rx
105}
106
107rmon_tx_histogram()
108{
109	rmon_histogram $h1 $h2 tx
110	rmon_histogram $h2 $h1 tx
111}
112
113setup_prepare()
114{
115	h1=${NETIFS[p1]}
116	h2=${NETIFS[p2]}
117
118	for iface in $h1 $h2; do
119		netif_mtu[$iface]=$(ip -j link show dev $iface | jq -r '.[0].mtu')
120		ip link set dev $iface up
121	done
122}
123
124cleanup()
125{
126	pre_cleanup
127
128	for iface in $h2 $h1; do
129		ip link set dev $iface \
130			mtu ${netif_mtu[$iface]} \
131			down
132	done
133}
134
135check_ethtool_counter_group_support
136trap cleanup EXIT
137
138setup_prepare
139setup_wait
140
141tests_run
142
143exit $EXIT_STATUS
144