1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/phylib_stubs.h>
10 struct stats_req_info
{
11 struct ethnl_req_info base
;
12 DECLARE_BITMAP(stat_mask
, __ETHTOOL_STATS_CNT
);
13 enum ethtool_mac_stats_src src
;
16 #define STATS_REQINFO(__req_base) \
17 container_of(__req_base, struct stats_req_info, base)
19 struct stats_reply_data
{
20 struct ethnl_reply_data base
;
22 struct ethtool_eth_phy_stats phy_stats
;
23 struct ethtool_eth_mac_stats mac_stats
;
24 struct ethtool_eth_ctrl_stats ctrl_stats
;
25 struct ethtool_rmon_stats rmon_stats
;
26 struct ethtool_phy_stats phydev_stats
;
28 const struct ethtool_rmon_hist_range
*rmon_ranges
;
31 #define STATS_REPDATA(__reply_base) \
32 container_of(__reply_base, struct stats_reply_data, base)
34 const char stats_std_names
[__ETHTOOL_STATS_CNT
][ETH_GSTRING_LEN
] = {
35 [ETHTOOL_STATS_ETH_PHY
] = "eth-phy",
36 [ETHTOOL_STATS_ETH_MAC
] = "eth-mac",
37 [ETHTOOL_STATS_ETH_CTRL
] = "eth-ctrl",
38 [ETHTOOL_STATS_RMON
] = "rmon",
39 [ETHTOOL_STATS_PHY
] = "phydev",
42 const char stats_eth_phy_names
[__ETHTOOL_A_STATS_ETH_PHY_CNT
][ETH_GSTRING_LEN
] = {
43 [ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR
] = "SymbolErrorDuringCarrier",
46 const char stats_eth_mac_names
[__ETHTOOL_A_STATS_ETH_MAC_CNT
][ETH_GSTRING_LEN
] = {
47 [ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT
] = "FramesTransmittedOK",
48 [ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL
] = "SingleCollisionFrames",
49 [ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL
] = "MultipleCollisionFrames",
50 [ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT
] = "FramesReceivedOK",
51 [ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR
] = "FrameCheckSequenceErrors",
52 [ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR
] = "AlignmentErrors",
53 [ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES
] = "OctetsTransmittedOK",
54 [ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER
] = "FramesWithDeferredXmissions",
55 [ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL
] = "LateCollisions",
56 [ETHTOOL_A_STATS_ETH_MAC_11_XS_COL
] = "FramesAbortedDueToXSColls",
57 [ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR
] = "FramesLostDueToIntMACXmitError",
58 [ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR
] = "CarrierSenseErrors",
59 [ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES
] = "OctetsReceivedOK",
60 [ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR
] = "FramesLostDueToIntMACRcvError",
61 [ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST
] = "MulticastFramesXmittedOK",
62 [ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST
] = "BroadcastFramesXmittedOK",
63 [ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER
] = "FramesWithExcessiveDeferral",
64 [ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST
] = "MulticastFramesReceivedOK",
65 [ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST
] = "BroadcastFramesReceivedOK",
66 [ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR
] = "InRangeLengthErrors",
67 [ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN
] = "OutOfRangeLengthField",
68 [ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR
] = "FrameTooLongErrors",
71 const char stats_eth_ctrl_names
[__ETHTOOL_A_STATS_ETH_CTRL_CNT
][ETH_GSTRING_LEN
] = {
72 [ETHTOOL_A_STATS_ETH_CTRL_3_TX
] = "MACControlFramesTransmitted",
73 [ETHTOOL_A_STATS_ETH_CTRL_4_RX
] = "MACControlFramesReceived",
74 [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP
] = "UnsupportedOpcodesReceived",
77 const char stats_rmon_names
[__ETHTOOL_A_STATS_RMON_CNT
][ETH_GSTRING_LEN
] = {
78 [ETHTOOL_A_STATS_RMON_UNDERSIZE
] = "etherStatsUndersizePkts",
79 [ETHTOOL_A_STATS_RMON_OVERSIZE
] = "etherStatsOversizePkts",
80 [ETHTOOL_A_STATS_RMON_FRAG
] = "etherStatsFragments",
81 [ETHTOOL_A_STATS_RMON_JABBER
] = "etherStatsJabbers",
84 const char stats_phy_names
[__ETHTOOL_A_STATS_PHY_CNT
][ETH_GSTRING_LEN
] = {
85 [ETHTOOL_A_STATS_PHY_RX_PKTS
] = "RxFrames",
86 [ETHTOOL_A_STATS_PHY_RX_BYTES
] = "RxOctets",
87 [ETHTOOL_A_STATS_PHY_RX_ERRORS
] = "RxErrors",
88 [ETHTOOL_A_STATS_PHY_TX_PKTS
] = "TxFrames",
89 [ETHTOOL_A_STATS_PHY_TX_BYTES
] = "TxOctets",
90 [ETHTOOL_A_STATS_PHY_TX_ERRORS
] = "TxErrors",
93 const struct nla_policy ethnl_stats_get_policy
[ETHTOOL_A_STATS_SRC
+ 1] = {
94 [ETHTOOL_A_STATS_HEADER
] =
95 NLA_POLICY_NESTED(ethnl_header_policy
),
96 [ETHTOOL_A_STATS_GROUPS
] = { .type
= NLA_NESTED
},
97 [ETHTOOL_A_STATS_SRC
] =
98 NLA_POLICY_MAX(NLA_U32
, ETHTOOL_MAC_STATS_SRC_PMAC
),
101 static int stats_parse_request(struct ethnl_req_info
*req_base
,
103 struct netlink_ext_ack
*extack
)
105 enum ethtool_mac_stats_src src
= ETHTOOL_MAC_STATS_SRC_AGGREGATE
;
106 struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
110 err
= ethnl_update_bitset(req_info
->stat_mask
, __ETHTOOL_STATS_CNT
,
111 tb
[ETHTOOL_A_STATS_GROUPS
], stats_std_names
,
117 NL_SET_ERR_MSG(extack
, "no stats requested");
121 if (tb
[ETHTOOL_A_STATS_SRC
])
122 src
= nla_get_u32(tb
[ETHTOOL_A_STATS_SRC
]);
129 static int stats_prepare_data(const struct ethnl_req_info
*req_base
,
130 struct ethnl_reply_data
*reply_base
,
131 const struct genl_info
*info
)
133 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
134 struct stats_reply_data
*data
= STATS_REPDATA(reply_base
);
135 enum ethtool_mac_stats_src src
= req_info
->src
;
136 struct net_device
*dev
= reply_base
->dev
;
137 struct nlattr
**tb
= info
->attrs
;
138 struct phy_device
*phydev
;
141 phydev
= ethnl_req_get_phydev(req_base
, tb
[ETHTOOL_A_STATS_HEADER
],
144 return PTR_ERR(phydev
);
146 ret
= ethnl_ops_begin(dev
);
150 if ((src
== ETHTOOL_MAC_STATS_SRC_EMAC
||
151 src
== ETHTOOL_MAC_STATS_SRC_PMAC
) &&
152 !__ethtool_dev_mm_supported(dev
)) {
153 NL_SET_ERR_MSG_MOD(info
->extack
,
154 "Device does not support MAC merge layer");
155 ethnl_ops_complete(dev
);
159 /* Mark all stats as unset (see ETHTOOL_STAT_NOT_SET) to prevent them
160 * from being reported to user space in case driver did not set them.
162 memset(&data
->stats
, 0xff, sizeof(data
->stats
));
164 data
->phy_stats
.src
= src
;
165 data
->mac_stats
.src
= src
;
166 data
->ctrl_stats
.src
= src
;
167 data
->rmon_stats
.src
= src
;
169 if ((test_bit(ETHTOOL_STATS_PHY
, req_info
->stat_mask
) ||
170 test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
)) &&
171 src
== ETHTOOL_MAC_STATS_SRC_AGGREGATE
) {
173 phy_ethtool_get_phy_stats(phydev
, &data
->phy_stats
,
174 &data
->phydev_stats
);
177 if (test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
) &&
178 dev
->ethtool_ops
->get_eth_phy_stats
)
179 dev
->ethtool_ops
->get_eth_phy_stats(dev
, &data
->phy_stats
);
180 if (test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
) &&
181 dev
->ethtool_ops
->get_eth_mac_stats
)
182 dev
->ethtool_ops
->get_eth_mac_stats(dev
, &data
->mac_stats
);
183 if (test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
) &&
184 dev
->ethtool_ops
->get_eth_ctrl_stats
)
185 dev
->ethtool_ops
->get_eth_ctrl_stats(dev
, &data
->ctrl_stats
);
186 if (test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
) &&
187 dev
->ethtool_ops
->get_rmon_stats
)
188 dev
->ethtool_ops
->get_rmon_stats(dev
, &data
->rmon_stats
,
191 ethnl_ops_complete(dev
);
195 static int stats_reply_size(const struct ethnl_req_info
*req_base
,
196 const struct ethnl_reply_data
*reply_base
)
198 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
199 unsigned int n_grps
= 0, n_stats
= 0;
202 len
+= nla_total_size(sizeof(u32
)); /* _STATS_SRC */
204 if (test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
)) {
205 n_stats
+= sizeof(struct ethtool_eth_phy_stats
) / sizeof(u64
);
208 if (test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
)) {
209 n_stats
+= sizeof(struct ethtool_eth_mac_stats
) / sizeof(u64
);
212 if (test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
)) {
213 n_stats
+= sizeof(struct ethtool_eth_ctrl_stats
) / sizeof(u64
);
216 if (test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
)) {
217 n_stats
+= sizeof(struct ethtool_rmon_stats
) / sizeof(u64
);
219 /* Above includes the space for _A_STATS_GRP_HIST_VALs */
221 len
+= (nla_total_size(0) + /* _A_STATS_GRP_HIST */
222 nla_total_size(4) + /* _A_STATS_GRP_HIST_BKT_LOW */
223 nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
224 ETHTOOL_RMON_HIST_MAX
* 2;
226 if (test_bit(ETHTOOL_STATS_PHY
, req_info
->stat_mask
)) {
227 n_stats
+= sizeof(struct ethtool_phy_stats
) / sizeof(u64
);
231 len
+= n_grps
* (nla_total_size(0) + /* _A_STATS_GRP */
232 nla_total_size(4) + /* _A_STATS_GRP_ID */
233 nla_total_size(4)); /* _A_STATS_GRP_SS_ID */
234 len
+= n_stats
* (nla_total_size(0) + /* _A_STATS_GRP_STAT */
235 nla_total_size_64bit(sizeof(u64
)));
240 static int stat_put(struct sk_buff
*skb
, u16 attrtype
, u64 val
)
245 if (val
== ETHTOOL_STAT_NOT_SET
)
248 /* We want to start stats attr types from 0, so we don't have a type
249 * for pad inside ETHTOOL_A_STATS_GRP_STAT. Pad things on the outside
250 * of ETHTOOL_A_STATS_GRP_STAT. Since we're one nest away from the
251 * actual attr we're 4B off - nla_need_padding_for_64bit() & co.
254 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
255 if (!IS_ALIGNED((unsigned long)skb_tail_pointer(skb
), 8))
256 if (!nla_reserve(skb
, ETHTOOL_A_STATS_GRP_PAD
, 0))
260 nest
= nla_nest_start(skb
, ETHTOOL_A_STATS_GRP_STAT
);
264 ret
= nla_put_u64_64bit(skb
, attrtype
, val
, -1 /* not used */);
266 nla_nest_cancel(skb
, nest
);
270 nla_nest_end(skb
, nest
);
274 static int stats_put_phy_stats(struct sk_buff
*skb
,
275 const struct stats_reply_data
*data
)
277 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR
,
278 data
->phy_stats
.SymbolErrorDuringCarrier
))
283 static int stats_put_phydev_stats(struct sk_buff
*skb
,
284 const struct stats_reply_data
*data
)
286 if (stat_put(skb
, ETHTOOL_A_STATS_PHY_RX_PKTS
,
287 data
->phydev_stats
.rx_packets
) ||
288 stat_put(skb
, ETHTOOL_A_STATS_PHY_RX_BYTES
,
289 data
->phydev_stats
.rx_bytes
) ||
290 stat_put(skb
, ETHTOOL_A_STATS_PHY_RX_ERRORS
,
291 data
->phydev_stats
.rx_errors
) ||
292 stat_put(skb
, ETHTOOL_A_STATS_PHY_TX_PKTS
,
293 data
->phydev_stats
.tx_packets
) ||
294 stat_put(skb
, ETHTOOL_A_STATS_PHY_TX_BYTES
,
295 data
->phydev_stats
.tx_bytes
) ||
296 stat_put(skb
, ETHTOOL_A_STATS_PHY_TX_ERRORS
,
297 data
->phydev_stats
.tx_errors
))
302 static int stats_put_mac_stats(struct sk_buff
*skb
,
303 const struct stats_reply_data
*data
)
305 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_2_TX_PKT
,
306 data
->mac_stats
.FramesTransmittedOK
) ||
307 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_3_SINGLE_COL
,
308 data
->mac_stats
.SingleCollisionFrames
) ||
309 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_4_MULTI_COL
,
310 data
->mac_stats
.MultipleCollisionFrames
) ||
311 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_5_RX_PKT
,
312 data
->mac_stats
.FramesReceivedOK
) ||
313 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_6_FCS_ERR
,
314 data
->mac_stats
.FrameCheckSequenceErrors
) ||
315 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_7_ALIGN_ERR
,
316 data
->mac_stats
.AlignmentErrors
) ||
317 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_8_TX_BYTES
,
318 data
->mac_stats
.OctetsTransmittedOK
) ||
319 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_9_TX_DEFER
,
320 data
->mac_stats
.FramesWithDeferredXmissions
) ||
321 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_10_LATE_COL
,
322 data
->mac_stats
.LateCollisions
) ||
323 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_11_XS_COL
,
324 data
->mac_stats
.FramesAbortedDueToXSColls
) ||
325 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_12_TX_INT_ERR
,
326 data
->mac_stats
.FramesLostDueToIntMACXmitError
) ||
327 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_13_CS_ERR
,
328 data
->mac_stats
.CarrierSenseErrors
) ||
329 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_14_RX_BYTES
,
330 data
->mac_stats
.OctetsReceivedOK
) ||
331 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_15_RX_INT_ERR
,
332 data
->mac_stats
.FramesLostDueToIntMACRcvError
) ||
333 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_18_TX_MCAST
,
334 data
->mac_stats
.MulticastFramesXmittedOK
) ||
335 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_19_TX_BCAST
,
336 data
->mac_stats
.BroadcastFramesXmittedOK
) ||
337 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_20_XS_DEFER
,
338 data
->mac_stats
.FramesWithExcessiveDeferral
) ||
339 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_21_RX_MCAST
,
340 data
->mac_stats
.MulticastFramesReceivedOK
) ||
341 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_22_RX_BCAST
,
342 data
->mac_stats
.BroadcastFramesReceivedOK
) ||
343 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_23_IR_LEN_ERR
,
344 data
->mac_stats
.InRangeLengthErrors
) ||
345 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_24_OOR_LEN
,
346 data
->mac_stats
.OutOfRangeLengthField
) ||
347 stat_put(skb
, ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR
,
348 data
->mac_stats
.FrameTooLongErrors
))
353 static int stats_put_ctrl_stats(struct sk_buff
*skb
,
354 const struct stats_reply_data
*data
)
356 if (stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_3_TX
,
357 data
->ctrl_stats
.MACControlFramesTransmitted
) ||
358 stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_4_RX
,
359 data
->ctrl_stats
.MACControlFramesReceived
) ||
360 stat_put(skb
, ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP
,
361 data
->ctrl_stats
.UnsupportedOpcodesReceived
))
366 static int stats_put_rmon_hist(struct sk_buff
*skb
, u32 attr
, const u64
*hist
,
367 const struct ethtool_rmon_hist_range
*ranges
)
375 for (i
= 0; i
< ETHTOOL_RMON_HIST_MAX
; i
++) {
376 if (!ranges
[i
].low
&& !ranges
[i
].high
)
378 if (hist
[i
] == ETHTOOL_STAT_NOT_SET
)
381 nest
= nla_nest_start(skb
, attr
);
385 if (nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_HIST_BKT_LOW
,
387 nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_HIST_BKT_HI
,
389 nla_put_u64_64bit(skb
, ETHTOOL_A_STATS_GRP_HIST_VAL
,
390 hist
[i
], ETHTOOL_A_STATS_GRP_PAD
))
391 goto err_cancel_hist
;
393 nla_nest_end(skb
, nest
);
399 nla_nest_cancel(skb
, nest
);
403 static int stats_put_rmon_stats(struct sk_buff
*skb
,
404 const struct stats_reply_data
*data
)
406 if (stats_put_rmon_hist(skb
, ETHTOOL_A_STATS_GRP_HIST_RX
,
407 data
->rmon_stats
.hist
, data
->rmon_ranges
) ||
408 stats_put_rmon_hist(skb
, ETHTOOL_A_STATS_GRP_HIST_TX
,
409 data
->rmon_stats
.hist_tx
, data
->rmon_ranges
))
412 if (stat_put(skb
, ETHTOOL_A_STATS_RMON_UNDERSIZE
,
413 data
->rmon_stats
.undersize_pkts
) ||
414 stat_put(skb
, ETHTOOL_A_STATS_RMON_OVERSIZE
,
415 data
->rmon_stats
.oversize_pkts
) ||
416 stat_put(skb
, ETHTOOL_A_STATS_RMON_FRAG
,
417 data
->rmon_stats
.fragments
) ||
418 stat_put(skb
, ETHTOOL_A_STATS_RMON_JABBER
,
419 data
->rmon_stats
.jabbers
))
425 static int stats_put_stats(struct sk_buff
*skb
,
426 const struct stats_reply_data
*data
,
428 int (*cb
)(struct sk_buff
*skb
,
429 const struct stats_reply_data
*data
))
433 nest
= nla_nest_start(skb
, ETHTOOL_A_STATS_GRP
);
437 if (nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_ID
, id
) ||
438 nla_put_u32(skb
, ETHTOOL_A_STATS_GRP_SS_ID
, ss_id
))
444 nla_nest_end(skb
, nest
);
448 nla_nest_cancel(skb
, nest
);
452 static int stats_fill_reply(struct sk_buff
*skb
,
453 const struct ethnl_req_info
*req_base
,
454 const struct ethnl_reply_data
*reply_base
)
456 const struct stats_req_info
*req_info
= STATS_REQINFO(req_base
);
457 const struct stats_reply_data
*data
= STATS_REPDATA(reply_base
);
460 if (nla_put_u32(skb
, ETHTOOL_A_STATS_SRC
, req_info
->src
))
463 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_PHY
, req_info
->stat_mask
))
464 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_PHY
,
465 ETH_SS_STATS_ETH_PHY
,
466 stats_put_phy_stats
);
467 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_MAC
, req_info
->stat_mask
))
468 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_MAC
,
469 ETH_SS_STATS_ETH_MAC
,
470 stats_put_mac_stats
);
471 if (!ret
&& test_bit(ETHTOOL_STATS_ETH_CTRL
, req_info
->stat_mask
))
472 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_ETH_CTRL
,
473 ETH_SS_STATS_ETH_CTRL
,
474 stats_put_ctrl_stats
);
475 if (!ret
&& test_bit(ETHTOOL_STATS_RMON
, req_info
->stat_mask
))
476 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_RMON
,
477 ETH_SS_STATS_RMON
, stats_put_rmon_stats
);
478 if (!ret
&& test_bit(ETHTOOL_STATS_PHY
, req_info
->stat_mask
))
479 ret
= stats_put_stats(skb
, data
, ETHTOOL_STATS_PHY
,
480 ETH_SS_STATS_PHY
, stats_put_phydev_stats
);
485 const struct ethnl_request_ops ethnl_stats_request_ops
= {
486 .request_cmd
= ETHTOOL_MSG_STATS_GET
,
487 .reply_cmd
= ETHTOOL_MSG_STATS_GET_REPLY
,
488 .hdr_attr
= ETHTOOL_A_STATS_HEADER
,
489 .req_info_size
= sizeof(struct stats_req_info
),
490 .reply_data_size
= sizeof(struct stats_reply_data
),
492 .parse_request
= stats_parse_request
,
493 .prepare_data
= stats_prepare_data
,
494 .reply_size
= stats_reply_size
,
495 .fill_reply
= stats_fill_reply
,
498 static u64
ethtool_stats_sum(u64 a
, u64 b
)
500 if (a
== ETHTOOL_STAT_NOT_SET
)
502 if (b
== ETHTOOL_STAT_NOT_SET
)
507 /* Avoid modifying the aggregation procedure every time a new counter is added
508 * by treating the structures as an array of u64 statistics.
510 static void ethtool_aggregate_stats(void *aggr_stats
, const void *emac_stats
,
511 const void *pmac_stats
, size_t stats_size
,
514 size_t num_stats
= stats_size
/ sizeof(u64
);
515 const u64
*s1
= emac_stats
+ stats_offset
;
516 const u64
*s2
= pmac_stats
+ stats_offset
;
517 u64
*s
= aggr_stats
+ stats_offset
;
520 for (i
= 0; i
< num_stats
; i
++)
521 s
[i
] = ethtool_stats_sum(s1
[i
], s2
[i
]);
524 void ethtool_aggregate_mac_stats(struct net_device
*dev
,
525 struct ethtool_eth_mac_stats
*mac_stats
)
527 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
528 struct ethtool_eth_mac_stats pmac
, emac
;
530 memset(&emac
, 0xff, sizeof(emac
));
531 memset(&pmac
, 0xff, sizeof(pmac
));
532 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
533 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
535 ops
->get_eth_mac_stats(dev
, &emac
);
536 ops
->get_eth_mac_stats(dev
, &pmac
);
538 ethtool_aggregate_stats(mac_stats
, &emac
, &pmac
,
539 sizeof(mac_stats
->stats
),
540 offsetof(struct ethtool_eth_mac_stats
, stats
));
542 EXPORT_SYMBOL(ethtool_aggregate_mac_stats
);
544 void ethtool_aggregate_phy_stats(struct net_device
*dev
,
545 struct ethtool_eth_phy_stats
*phy_stats
)
547 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
548 struct ethtool_eth_phy_stats pmac
, emac
;
550 memset(&emac
, 0xff, sizeof(emac
));
551 memset(&pmac
, 0xff, sizeof(pmac
));
552 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
553 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
555 ops
->get_eth_phy_stats(dev
, &emac
);
556 ops
->get_eth_phy_stats(dev
, &pmac
);
558 ethtool_aggregate_stats(phy_stats
, &emac
, &pmac
,
559 sizeof(phy_stats
->stats
),
560 offsetof(struct ethtool_eth_phy_stats
, stats
));
562 EXPORT_SYMBOL(ethtool_aggregate_phy_stats
);
564 void ethtool_aggregate_ctrl_stats(struct net_device
*dev
,
565 struct ethtool_eth_ctrl_stats
*ctrl_stats
)
567 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
568 struct ethtool_eth_ctrl_stats pmac
, emac
;
570 memset(&emac
, 0xff, sizeof(emac
));
571 memset(&pmac
, 0xff, sizeof(pmac
));
572 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
573 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
575 ops
->get_eth_ctrl_stats(dev
, &emac
);
576 ops
->get_eth_ctrl_stats(dev
, &pmac
);
578 ethtool_aggregate_stats(ctrl_stats
, &emac
, &pmac
,
579 sizeof(ctrl_stats
->stats
),
580 offsetof(struct ethtool_eth_ctrl_stats
, stats
));
582 EXPORT_SYMBOL(ethtool_aggregate_ctrl_stats
);
584 void ethtool_aggregate_pause_stats(struct net_device
*dev
,
585 struct ethtool_pause_stats
*pause_stats
)
587 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
588 struct ethtool_pause_stats pmac
, emac
;
590 memset(&emac
, 0xff, sizeof(emac
));
591 memset(&pmac
, 0xff, sizeof(pmac
));
592 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
593 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
595 ops
->get_pause_stats(dev
, &emac
);
596 ops
->get_pause_stats(dev
, &pmac
);
598 ethtool_aggregate_stats(pause_stats
, &emac
, &pmac
,
599 sizeof(pause_stats
->stats
),
600 offsetof(struct ethtool_pause_stats
, stats
));
602 EXPORT_SYMBOL(ethtool_aggregate_pause_stats
);
604 void ethtool_aggregate_rmon_stats(struct net_device
*dev
,
605 struct ethtool_rmon_stats
*rmon_stats
)
607 const struct ethtool_ops
*ops
= dev
->ethtool_ops
;
608 const struct ethtool_rmon_hist_range
*dummy
;
609 struct ethtool_rmon_stats pmac
, emac
;
611 memset(&emac
, 0xff, sizeof(emac
));
612 memset(&pmac
, 0xff, sizeof(pmac
));
613 emac
.src
= ETHTOOL_MAC_STATS_SRC_EMAC
;
614 pmac
.src
= ETHTOOL_MAC_STATS_SRC_PMAC
;
616 ops
->get_rmon_stats(dev
, &emac
, &dummy
);
617 ops
->get_rmon_stats(dev
, &pmac
, &dummy
);
619 ethtool_aggregate_stats(rmon_stats
, &emac
, &pmac
,
620 sizeof(rmon_stats
->stats
),
621 offsetof(struct ethtool_rmon_stats
, stats
));
623 EXPORT_SYMBOL(ethtool_aggregate_rmon_stats
);