Skip to content

Commit bada6b4

Browse files
vladimirolteanNipaLocal
authored andcommitted
net: dsa: append ethtool counters of all hidden ports to conduit
Currently there is no way to see packet counters on cascade ports, and no clarity on how the API for that would look like. Because it's something that is currently needed, just extend the hack where ethtool -S on the conduit interface dumps CPU port counters, and also use it to dump counters of cascade ports. Note that the "pXX_" naming convention changes to "sXX_pYY", to distinguish between ports having the same index but belonging to different switches. This has a slight chance of causing regressions to existing tooling: - grepping for "p04_counter_name" still works, but might return more than one string now - grepping for " p04_counter_name" no longer works Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: NipaLocal <nipa@local>
1 parent 4be2497 commit bada6b4

File tree

1 file changed

+93
-33
lines changed

1 file changed

+93
-33
lines changed

net/dsa/conduit.c

Lines changed: 93 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,51 @@ static void dsa_conduit_get_regs(struct net_device *dev,
8787
}
8888
}
8989

90+
static ssize_t dsa_conduit_append_port_stats(struct dsa_switch *ds, int port,
91+
u64 *data, size_t start)
92+
{
93+
int count;
94+
95+
if (!ds->ops->get_sset_count)
96+
return 0;
97+
98+
count = ds->ops->get_sset_count(ds, port, ETH_SS_STATS);
99+
if (count < 0)
100+
return count;
101+
102+
if (ds->ops->get_ethtool_stats)
103+
ds->ops->get_ethtool_stats(ds, port, data + start);
104+
105+
return count;
106+
}
107+
90108
static void dsa_conduit_get_ethtool_stats(struct net_device *dev,
91109
struct ethtool_stats *stats,
92110
u64 *data)
93111
{
94-
struct dsa_port *cpu_dp = dev->dsa_ptr;
112+
struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
95113
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
96-
struct dsa_switch *ds = cpu_dp->ds;
97-
int port = cpu_dp->index;
98-
int count = 0;
114+
struct dsa_switch_tree *dst = cpu_dp->dst;
115+
int count, mcount = 0;
99116

100117
if (ops && ops->get_sset_count && ops->get_ethtool_stats) {
101118
netdev_lock_ops(dev);
102-
count = ops->get_sset_count(dev, ETH_SS_STATS);
119+
mcount = ops->get_sset_count(dev, ETH_SS_STATS);
103120
ops->get_ethtool_stats(dev, stats, data);
104121
netdev_unlock_ops(dev);
105122
}
106123

107-
if (ds->ops->get_ethtool_stats)
108-
ds->ops->get_ethtool_stats(ds, port, data + count);
124+
list_for_each_entry(dp, &dst->ports, list) {
125+
if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
126+
continue;
127+
128+
count = dsa_conduit_append_port_stats(dp->ds, dp->index,
129+
data, mcount);
130+
if (count < 0)
131+
return;
132+
133+
mcount += count;
134+
}
109135
}
110136

111137
static void dsa_conduit_get_ethtool_phy_stats(struct net_device *dev,
@@ -136,11 +162,18 @@ static void dsa_conduit_get_ethtool_phy_stats(struct net_device *dev,
136162
ds->ops->get_ethtool_phy_stats(ds, port, data + count);
137163
}
138164

165+
static void dsa_conduit_append_port_sset_count(struct dsa_switch *ds, int port,
166+
int sset, int *count)
167+
{
168+
if (ds->ops->get_sset_count)
169+
*count += ds->ops->get_sset_count(ds, port, sset);
170+
}
171+
139172
static int dsa_conduit_get_sset_count(struct net_device *dev, int sset)
140173
{
141-
struct dsa_port *cpu_dp = dev->dsa_ptr;
174+
struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
142175
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
143-
struct dsa_switch *ds = cpu_dp->ds;
176+
struct dsa_switch_tree *dst = cpu_dp->dst;
144177
int count = 0;
145178

146179
netdev_lock_ops(dev);
@@ -154,26 +187,57 @@ static int dsa_conduit_get_sset_count(struct net_device *dev, int sset)
154187
if (count < 0)
155188
count = 0;
156189

157-
if (ds->ops->get_sset_count)
158-
count += ds->ops->get_sset_count(ds, cpu_dp->index, sset);
190+
list_for_each_entry(dp, &dst->ports, list) {
191+
if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
192+
continue;
193+
194+
dsa_conduit_append_port_sset_count(dp->ds, dp->index, sset,
195+
&count);
196+
}
159197

160198
return count;
161199
}
162200

163-
static void dsa_conduit_get_strings(struct net_device *dev, u32 stringset,
164-
u8 *data)
201+
static ssize_t dsa_conduit_append_port_strings(struct dsa_switch *ds, int port,
202+
u32 stringset, u8 *data,
203+
size_t start)
165204
{
166-
struct dsa_port *cpu_dp = dev->dsa_ptr;
167-
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
168-
struct dsa_switch *ds = cpu_dp->ds;
169-
int port = cpu_dp->index;
170205
int len = ETH_GSTRING_LEN;
171-
int mcount = 0, count, i;
172-
u8 pfx[4], *ndata;
206+
u8 pfx[8], *ndata;
207+
int count, i;
208+
209+
if (!ds->ops->get_strings)
210+
return 0;
173211

174-
snprintf(pfx, sizeof(pfx), "p%.2d", port);
212+
snprintf(pfx, sizeof(pfx), "s%.2d_p%.2d", ds->index, port);
175213
/* We do not want to be NULL-terminated, since this is a prefix */
176214
pfx[sizeof(pfx) - 1] = '_';
215+
ndata = data + start * len;
216+
/* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
217+
* the output after to prepend our CPU port prefix we
218+
* constructed earlier
219+
*/
220+
ds->ops->get_strings(ds, port, stringset, ndata);
221+
count = ds->ops->get_sset_count(ds, port, stringset);
222+
if (count < 0)
223+
return count;
224+
225+
for (i = 0; i < count; i++) {
226+
memmove(ndata + (i * len + sizeof(pfx)),
227+
ndata + i * len, len - sizeof(pfx));
228+
memcpy(ndata + i * len, pfx, sizeof(pfx));
229+
}
230+
231+
return count;
232+
}
233+
234+
static void dsa_conduit_get_strings(struct net_device *dev, u32 stringset,
235+
u8 *data)
236+
{
237+
struct dsa_port *dp, *cpu_dp = dev->dsa_ptr;
238+
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
239+
struct dsa_switch_tree *dst = cpu_dp->dst;
240+
int count, mcount = 0;
177241

178242
netdev_lock_ops(dev);
179243
if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
@@ -191,21 +255,17 @@ static void dsa_conduit_get_strings(struct net_device *dev, u32 stringset,
191255
}
192256
netdev_unlock_ops(dev);
193257

194-
if (ds->ops->get_strings) {
195-
ndata = data + mcount * len;
196-
/* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
197-
* the output after to prepend our CPU port prefix we
198-
* constructed earlier
199-
*/
200-
ds->ops->get_strings(ds, port, stringset, ndata);
201-
count = ds->ops->get_sset_count(ds, port, stringset);
258+
list_for_each_entry(dp, &dst->ports, list) {
259+
if (!dsa_port_is_dsa(dp) && !dsa_port_is_cpu(dp))
260+
continue;
261+
262+
count = dsa_conduit_append_port_strings(dp->ds, dp->index,
263+
stringset, data,
264+
mcount);
202265
if (count < 0)
203266
return;
204-
for (i = 0; i < count; i++) {
205-
memmove(ndata + (i * len + sizeof(pfx)),
206-
ndata + i * len, len - sizeof(pfx));
207-
memcpy(ndata + i * len, pfx, sizeof(pfx));
208-
}
267+
268+
mcount += count;
209269
}
210270
}
211271

0 commit comments

Comments
 (0)