mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
net: ethtool: add support for structured PHY statistics
Introduce a new way to report PHY statistics in a structured and standardized format using the netlink API. This new method does not replace the old driver-specific stats, which can still be accessed with `ethtool -S <eth name>`. The structured stats are available with `ethtool -S <eth name> --all-groups`. This new method makes it easier to diagnose problems by organizing stats in a consistent and documented way. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
b7a2c1fe6b
commit
6167c0b6e8
@@ -1616,6 +1616,7 @@ the ``ETHTOOL_A_STATS_GROUPS`` bitset. Currently defined values are:
|
||||
ETHTOOL_STATS_ETH_PHY eth-phy Basic IEEE 802.3 PHY statistics (30.3.2.1.*)
|
||||
ETHTOOL_STATS_ETH_CTRL eth-ctrl Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*)
|
||||
ETHTOOL_STATS_RMON rmon RMON (RFC 2819) statistics
|
||||
ETHTOOL_STATS_PHY phy Additional PHY statistics, not defined by IEEE
|
||||
====================== ======== ===============================================
|
||||
|
||||
Each group should have a corresponding ``ETHTOOL_A_STATS_GRP`` in the reply.
|
||||
|
||||
@@ -681,6 +681,7 @@ enum ethtool_link_ext_substate_module {
|
||||
* @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics
|
||||
* @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics
|
||||
* @ETH_SS_STATS_RMON: names of RMON statistics
|
||||
* @ETH_SS_STATS_PHY: names of PHY(dev) statistics
|
||||
*
|
||||
* @ETH_SS_COUNT: number of defined string sets
|
||||
*/
|
||||
@@ -706,6 +707,7 @@ enum ethtool_stringset {
|
||||
ETH_SS_STATS_ETH_MAC,
|
||||
ETH_SS_STATS_ETH_CTRL,
|
||||
ETH_SS_STATS_RMON,
|
||||
ETH_SS_STATS_PHY,
|
||||
|
||||
/* add new constants above here */
|
||||
ETH_SS_COUNT
|
||||
|
||||
@@ -99,6 +99,7 @@ enum {
|
||||
ETHTOOL_STATS_ETH_MAC,
|
||||
ETHTOOL_STATS_ETH_CTRL,
|
||||
ETHTOOL_STATS_RMON,
|
||||
ETHTOOL_STATS_PHY,
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_STATS_CNT
|
||||
@@ -193,6 +194,19 @@ enum {
|
||||
ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
/* Basic packet counters if PHY has separate counters from the MAC */
|
||||
ETHTOOL_A_STATS_PHY_RX_PKTS,
|
||||
ETHTOOL_A_STATS_PHY_RX_BYTES,
|
||||
ETHTOOL_A_STATS_PHY_RX_ERRORS,
|
||||
ETHTOOL_A_STATS_PHY_TX_PKTS,
|
||||
ETHTOOL_A_STATS_PHY_TX_BYTES,
|
||||
ETHTOOL_A_STATS_PHY_TX_ERRORS,
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_A_STATS_PHY_CNT,
|
||||
ETHTOOL_A_STATS_PHY_MAX = (__ETHTOOL_A_STATS_PHY_CNT - 1)
|
||||
};
|
||||
|
||||
/* generic netlink info */
|
||||
#define ETHTOOL_GENL_NAME "ethtool"
|
||||
|
||||
@@ -511,5 +511,6 @@ extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING
|
||||
extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN];
|
||||
extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN];
|
||||
extern const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN];
|
||||
extern const char stats_phy_names[__ETHTOOL_A_STATS_PHY_CNT][ETH_GSTRING_LEN];
|
||||
|
||||
#endif /* _NET_ETHTOOL_NETLINK_H */
|
||||
|
||||
@@ -36,6 +36,7 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
|
||||
[ETHTOOL_STATS_ETH_MAC] = "eth-mac",
|
||||
[ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl",
|
||||
[ETHTOOL_STATS_RMON] = "rmon",
|
||||
[ETHTOOL_STATS_PHY] = "phydev",
|
||||
};
|
||||
|
||||
const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = {
|
||||
@@ -80,6 +81,15 @@ const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN] = {
|
||||
[ETHTOOL_A_STATS_RMON_JABBER] = "etherStatsJabbers",
|
||||
};
|
||||
|
||||
const char stats_phy_names[__ETHTOOL_A_STATS_PHY_CNT][ETH_GSTRING_LEN] = {
|
||||
[ETHTOOL_A_STATS_PHY_RX_PKTS] = "RxFrames",
|
||||
[ETHTOOL_A_STATS_PHY_RX_BYTES] = "RxOctets",
|
||||
[ETHTOOL_A_STATS_PHY_RX_ERRORS] = "RxErrors",
|
||||
[ETHTOOL_A_STATS_PHY_TX_PKTS] = "TxFrames",
|
||||
[ETHTOOL_A_STATS_PHY_TX_BYTES] = "TxOctets",
|
||||
[ETHTOOL_A_STATS_PHY_TX_ERRORS] = "TxErrors",
|
||||
};
|
||||
|
||||
const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1] = {
|
||||
[ETHTOOL_A_STATS_HEADER] =
|
||||
NLA_POLICY_NESTED(ethnl_header_policy),
|
||||
@@ -156,7 +166,8 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
|
||||
data->ctrl_stats.src = src;
|
||||
data->rmon_stats.src = src;
|
||||
|
||||
if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
|
||||
if ((test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask) ||
|
||||
test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask)) &&
|
||||
src == ETHTOOL_MAC_STATS_SRC_AGGREGATE) {
|
||||
if (phydev)
|
||||
phy_ethtool_get_phy_stats(phydev, &data->phy_stats,
|
||||
@@ -212,6 +223,10 @@ static int stats_reply_size(const struct ethnl_req_info *req_base,
|
||||
nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
|
||||
ETHTOOL_RMON_HIST_MAX * 2;
|
||||
}
|
||||
if (test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask)) {
|
||||
n_stats += sizeof(struct ethtool_phy_stats) / sizeof(u64);
|
||||
n_grps++;
|
||||
}
|
||||
|
||||
len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */
|
||||
nla_total_size(4) + /* _A_STATS_GRP_ID */
|
||||
@@ -265,6 +280,25 @@ static int stats_put_phy_stats(struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stats_put_phydev_stats(struct sk_buff *skb,
|
||||
const struct stats_reply_data *data)
|
||||
{
|
||||
if (stat_put(skb, ETHTOOL_A_STATS_PHY_RX_PKTS,
|
||||
data->phydev_stats.rx_packets) ||
|
||||
stat_put(skb, ETHTOOL_A_STATS_PHY_RX_BYTES,
|
||||
data->phydev_stats.rx_bytes) ||
|
||||
stat_put(skb, ETHTOOL_A_STATS_PHY_RX_ERRORS,
|
||||
data->phydev_stats.rx_errors) ||
|
||||
stat_put(skb, ETHTOOL_A_STATS_PHY_TX_PKTS,
|
||||
data->phydev_stats.tx_packets) ||
|
||||
stat_put(skb, ETHTOOL_A_STATS_PHY_TX_BYTES,
|
||||
data->phydev_stats.tx_bytes) ||
|
||||
stat_put(skb, ETHTOOL_A_STATS_PHY_TX_ERRORS,
|
||||
data->phydev_stats.tx_errors))
|
||||
return -EMSGSIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stats_put_mac_stats(struct sk_buff *skb,
|
||||
const struct stats_reply_data *data)
|
||||
{
|
||||
@@ -441,6 +475,9 @@ static int stats_fill_reply(struct sk_buff *skb,
|
||||
if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask))
|
||||
ret = stats_put_stats(skb, data, ETHTOOL_STATS_RMON,
|
||||
ETH_SS_STATS_RMON, stats_put_rmon_stats);
|
||||
if (!ret && test_bit(ETHTOOL_STATS_PHY, req_info->stat_mask))
|
||||
ret = stats_put_stats(skb, data, ETHTOOL_STATS_PHY,
|
||||
ETH_SS_STATS_PHY, stats_put_phydev_stats);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,11 @@ static const struct strset_info info_template[] = {
|
||||
.count = __ETHTOOL_A_STATS_RMON_CNT,
|
||||
.strings = stats_rmon_names,
|
||||
},
|
||||
[ETH_SS_STATS_PHY] = {
|
||||
.per_dev = false,
|
||||
.count = __ETHTOOL_A_STATS_PHY_CNT,
|
||||
.strings = stats_phy_names,
|
||||
},
|
||||
};
|
||||
|
||||
struct strset_req_info {
|
||||
|
||||
Reference in New Issue
Block a user