Skip to content

Commit b84d66b

Browse files
committed
Merge branch 'mv88e6xxx-counters'
Tobias Waldekranz says: ==================== net: dsa: mv88e6xxx: Add "eth-mac" and "rmon" counter group support The majority of the changes (2/8) are about refactoring the existing ethtool statistics support to make it possible to read individual counters, rather than the whole set. 4/8 tries to collect all information about a stat in a single place using a mapper macro, which is then used to generate the original list of stats, along with a matching enum. checkpatch is less than amused with this construct, but prior art exists (__BPF_FUNC_MAPPER in include/uapi/linux/bpf.h, for example). To support the histogram counters from the "rmon" group, we have to change mv88e6xxx's configuration of them. Instead of counting rx and tx, we restrict them to rx-only. 6/8 has the details. With that in place, adding the actual counter groups is pretty straight forward (5,7/8). Tie it all together with a selftest (8/8). v3 -> v4: - Return size_t from mv88e6xxx_stats_get_stats - Spelling errors in commit message of 6/8 - Improve selftest: - Report progress per-bucket - Test both ports in the pair - Increase MTU, if required v2 -> v3: - Added 6/8 - Added 8/8 v1 -> v2: - Added 1/6 - Added 3/6 - Changed prototype of stats operation to reflect the fact that the number of read stats are returned, no errors - Moved comma into MV88E6XXX_HW_STAT_MAPPER definition - Avoid the construction of mapping table iteration which relied on struct layouts outside of mv88e6xxx's control ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 9ed816b + 00e7f29 commit b84d66b

File tree

8 files changed

+435
-166
lines changed

8 files changed

+435
-166
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 254 additions & 138 deletions
Large diffs are not rendered by default.

drivers/net/dsa/mv88e6xxx/chip.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,17 @@ struct mv88e6xxx_mst {
318318
struct mv88e6xxx_stu_entry stu;
319319
};
320320

321+
#define STATS_TYPE_PORT BIT(0)
322+
#define STATS_TYPE_BANK0 BIT(1)
323+
#define STATS_TYPE_BANK1 BIT(2)
324+
325+
struct mv88e6xxx_hw_stat {
326+
char string[ETH_GSTRING_LEN];
327+
size_t size;
328+
int reg;
329+
int type;
330+
};
331+
321332
struct mv88e6xxx_chip {
322333
const struct mv88e6xxx_info *info;
323334

@@ -574,8 +585,9 @@ struct mv88e6xxx_ops {
574585
/* Return the number of strings describing statistics */
575586
int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
576587
int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
577-
int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
578-
uint64_t *data);
588+
size_t (*stats_get_stat)(struct mv88e6xxx_chip *chip, int port,
589+
const struct mv88e6xxx_hw_stat *stat,
590+
uint64_t *data);
579591
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
580592
int (*set_egress_port)(struct mv88e6xxx_chip *chip,
581593
enum mv88e6xxx_egress_direction direction,
@@ -601,8 +613,8 @@ struct mv88e6xxx_ops {
601613
int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
602614
int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
603615
uint8_t *data);
604-
int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
605-
uint64_t *data);
616+
size_t (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
617+
uint64_t *data);
606618

607619
/* SERDES registers for ethtool */
608620
int (*serdes_get_regs_len)(struct mv88e6xxx_chip *chip, int port);
@@ -727,17 +739,6 @@ struct mv88e6xxx_pcs_ops {
727739

728740
};
729741

730-
#define STATS_TYPE_PORT BIT(0)
731-
#define STATS_TYPE_BANK0 BIT(1)
732-
#define STATS_TYPE_BANK1 BIT(2)
733-
734-
struct mv88e6xxx_hw_stat {
735-
char string[ETH_GSTRING_LEN];
736-
size_t size;
737-
int reg;
738-
int type;
739-
};
740-
741742
static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip)
742743
{
743744
return chip->info->max_sid > 0 &&

drivers/net/dsa/mv88e6xxx/global1.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip)
462462
int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
463463
{
464464
return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK,
465-
MV88E6390_G1_CTL2_HIST_MODE_RX |
466-
MV88E6390_G1_CTL2_HIST_MODE_TX);
465+
MV88E6390_G1_CTL2_HIST_MODE_RX);
467466
}
468467

469468
int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
@@ -491,7 +490,7 @@ int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
491490
if (err)
492491
return err;
493492

494-
val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
493+
val |= MV88E6XXX_G1_STATS_OP_HIST_RX;
495494

496495
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
497496

@@ -506,7 +505,7 @@ int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
506505
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
507506
MV88E6XXX_G1_STATS_OP_BUSY |
508507
MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
509-
MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
508+
MV88E6XXX_G1_STATS_OP_HIST_RX | port);
510509
if (err)
511510
return err;
512511

drivers/net/dsa/mv88e6xxx/serdes.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
177177
return val;
178178
}
179179

180-
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
181-
uint64_t *data)
180+
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
181+
uint64_t *data)
182182
{
183183
struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
184184
struct mv88e6352_serdes_hw_stat *stat;
@@ -187,7 +187,7 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
187187

188188
err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
189189
if (err <= 0)
190-
return err;
190+
return 0;
191191

192192
BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
193193
ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
@@ -429,8 +429,8 @@ static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
429429
return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
430430
}
431431

432-
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
433-
uint64_t *data)
432+
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
433+
uint64_t *data)
434434
{
435435
struct mv88e6390_serdes_hw_stat *stat;
436436
int lane;

drivers/net/dsa/mv88e6xxx/serdes.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,13 @@ unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
127127
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
128128
int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
129129
int port, uint8_t *data);
130-
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
131-
uint64_t *data);
130+
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
131+
uint64_t *data);
132132
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
133133
int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
134134
int port, uint8_t *data);
135-
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
136-
uint64_t *data);
135+
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
136+
uint64_t *data);
137137

138138
int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
139139
void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);

tools/testing/selftests/net/forwarding/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
1717
dual_vxlan_bridge.sh \
1818
ethtool_extended_state.sh \
1919
ethtool_mm.sh \
20+
ethtool_rmon.sh \
2021
ethtool.sh \
2122
gre_custom_multipath_hash.sh \
2223
gre_inner_v4_multipath.sh \
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
ALL_TESTS="
5+
rmon_rx_histogram
6+
rmon_tx_histogram
7+
"
8+
9+
NUM_NETIFS=2
10+
source lib.sh
11+
12+
ETH_FCS_LEN=4
13+
ETH_HLEN=$((6+6+2))
14+
15+
declare -A netif_mtu
16+
17+
ensure_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+
29+
bucket_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+
66+
rmon_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+
101+
rmon_rx_histogram()
102+
{
103+
rmon_histogram $h1 $h2 rx
104+
rmon_histogram $h2 $h1 rx
105+
}
106+
107+
rmon_tx_histogram()
108+
{
109+
rmon_histogram $h1 $h2 tx
110+
rmon_histogram $h2 $h1 tx
111+
}
112+
113+
setup_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+
124+
cleanup()
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+
135+
check_ethtool_counter_group_support
136+
trap cleanup EXIT
137+
138+
setup_prepare
139+
setup_wait
140+
141+
tests_run
142+
143+
exit $EXIT_STATUS

tools/testing/selftests/net/forwarding/lib.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ check_ethtool_mm_support()
146146
fi
147147
}
148148

149+
check_ethtool_counter_group_support()
150+
{
151+
ethtool --help 2>&1| grep -- '--all-groups' &> /dev/null
152+
if [[ $? -ne 0 ]]; then
153+
echo "SKIP: ethtool too old; it is missing standard counter group support"
154+
exit $ksft_skip
155+
fi
156+
}
157+
149158
check_locked_port_support()
150159
{
151160
if ! bridge -d link show | grep -q " locked"; then

0 commit comments

Comments
 (0)