Commit bfad2b97 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

ethtool: add interface to read standard MAC Ctrl stats



Number of devices maintains the standard-based MAC control
counters for control frames. Add a API for those.

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ca224454
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -285,6 +285,15 @@ struct ethtool_eth_phy_stats {
	u64 SymbolErrorDuringCarrier;
};

/* Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*), not otherwise exposed
 * via a more targeted API.
 */
struct ethtool_eth_ctrl_stats {
	u64 MACControlFramesTransmitted;
	u64 MACControlFramesReceived;
	u64 UnsupportedOpcodesReceived;
};

/**
 * struct ethtool_pause_stats - statistics for IEEE 802.3x pause frames
 * @tx_pause_frames: transmitted pause frame count. Reported to user space
@@ -524,6 +533,7 @@ struct ethtool_module_eeprom {
 *	read.
 * @get_eth_phy_stats: Query some of the IEEE 802.3 PHY statistics.
 * @get_eth_mac_stats: Query some of the IEEE 802.3 MAC statistics.
 * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics.
 *
 * All operations are optional (i.e. the function pointer may be set
 * to %NULL) and callers must take this into account.  Callers must
@@ -638,6 +648,8 @@ struct ethtool_ops {
				     struct ethtool_eth_phy_stats *phy_stats);
	void	(*get_eth_mac_stats)(struct net_device *dev,
				     struct ethtool_eth_mac_stats *mac_stats);
	void	(*get_eth_ctrl_stats)(struct net_device *dev,
				      struct ethtool_eth_ctrl_stats *ctrl_stats);
};

int ethtool_check_ops(const struct ethtool_ops *ops);
+2 −0
Original line number Diff line number Diff line
@@ -672,6 +672,7 @@ enum ethtool_link_ext_substate_cable_issue {
 * @ETH_SS_STATS_STD: standardized stats
 * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics
 * @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_COUNT: number of defined string sets
 */
@@ -695,6 +696,7 @@ enum ethtool_stringset {
	ETH_SS_STATS_STD,
	ETH_SS_STATS_ETH_PHY,
	ETH_SS_STATS_ETH_MAC,
	ETH_SS_STATS_ETH_CTRL,

	/* add new constants above here */
	ETH_SS_COUNT
+14 −0
Original line number Diff line number Diff line
@@ -699,6 +699,7 @@ enum {
enum {
	ETHTOOL_STATS_ETH_PHY,
	ETHTOOL_STATS_ETH_MAC,
	ETHTOOL_STATS_ETH_CTRL,

	/* add new constants above here */
	__ETHTOOL_STATS_CNT
@@ -779,6 +780,19 @@ enum {
	ETHTOOL_A_STATS_ETH_MAC_MAX = (__ETHTOOL_A_STATS_ETH_MAC_CNT - 1)
};

enum {
	/* 30.3.3.3 aMACControlFramesTransmitted */
	ETHTOOL_A_STATS_ETH_CTRL_3_TX,
	/* 30.3.3.4 aMACControlFramesReceived */
	ETHTOOL_A_STATS_ETH_CTRL_4_RX,
	/* 30.3.3.5 aUnsupportedOpcodesReceived */
	ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP,

	/* add new constants above here */
	__ETHTOOL_A_STATS_ETH_CTRL_CNT,
	ETHTOOL_A_STATS_ETH_CTRL_MAX = (__ETHTOOL_A_STATS_ETH_CTRL_CNT - 1)
};

/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
+1 −0
Original line number Diff line number Diff line
@@ -404,5 +404,6 @@ int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info);
extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
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];

#endif /* _NET_ETHTOOL_NETLINK_H */
+33 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ struct stats_reply_data {
	struct ethnl_reply_data		base;
	struct ethtool_eth_phy_stats	phy_stats;
	struct ethtool_eth_mac_stats	mac_stats;
	struct ethtool_eth_ctrl_stats	ctrl_stats;
};

#define STATS_REPDATA(__reply_base) \
@@ -24,6 +25,7 @@ struct stats_reply_data {
const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
	[ETHTOOL_STATS_ETH_PHY]			= "eth-phy",
	[ETHTOOL_STATS_ETH_MAC]			= "eth-mac",
	[ETHTOOL_STATS_ETH_CTRL]		= "eth-ctrl",
};

const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = {
@@ -55,6 +57,12 @@ const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN] =
	[ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR]	= "FrameTooLongErrors",
};

const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN] = {
	[ETHTOOL_A_STATS_ETH_CTRL_3_TX]		= "MACControlFramesTransmitted",
	[ETHTOOL_A_STATS_ETH_CTRL_4_RX]		= "MACControlFramesReceived",
	[ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP]	= "UnsupportedOpcodesReceived",
};

const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1] = {
	[ETHTOOL_A_STATS_HEADER]	=
		NLA_POLICY_NESTED(ethnl_header_policy),
@@ -98,6 +106,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,

	memset(&data->phy_stats, 0xff, sizeof(data->phy_stats));
	memset(&data->mac_stats, 0xff, sizeof(data->mac_stats));
	memset(&data->ctrl_stats, 0xff, sizeof(data->mac_stats));

	if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
	    dev->ethtool_ops->get_eth_phy_stats)
@@ -105,6 +114,9 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
	if (test_bit(ETHTOOL_STATS_ETH_MAC, req_info->stat_mask) &&
	    dev->ethtool_ops->get_eth_mac_stats)
		dev->ethtool_ops->get_eth_mac_stats(dev, &data->mac_stats);
	if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask) &&
	    dev->ethtool_ops->get_eth_ctrl_stats)
		dev->ethtool_ops->get_eth_ctrl_stats(dev, &data->ctrl_stats);

	ethnl_ops_complete(dev);
	return 0;
@@ -125,6 +137,10 @@ static int stats_reply_size(const struct ethnl_req_info *req_base,
		n_stats += sizeof(struct ethtool_eth_mac_stats) / sizeof(u64);
		n_grps++;
	}
	if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask)) {
		n_stats += sizeof(struct ethtool_eth_ctrl_stats) / sizeof(u64);
		n_grps++;
	}

	len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */
			 nla_total_size(4) + /* _A_STATS_GRP_ID */
@@ -229,6 +245,19 @@ static int stats_put_mac_stats(struct sk_buff *skb,
	return 0;
}

static int stats_put_ctrl_stats(struct sk_buff *skb,
				const struct stats_reply_data *data)
{
	if (stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_3_TX,
		     data->ctrl_stats.MACControlFramesTransmitted) ||
	    stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_4_RX,
		     data->ctrl_stats.MACControlFramesReceived) ||
	    stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP,
		     data->ctrl_stats.UnsupportedOpcodesReceived))
		return -EMSGSIZE;
	return 0;
}

static int stats_put_stats(struct sk_buff *skb,
			   const struct stats_reply_data *data,
			   u32 id, u32 ss_id,
@@ -272,6 +301,10 @@ static int stats_fill_reply(struct sk_buff *skb,
		ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_MAC,
				      ETH_SS_STATS_ETH_MAC,
				      stats_put_mac_stats);
	if (!ret && test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask))
		ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_CTRL,
				      ETH_SS_STATS_ETH_CTRL,
				      stats_put_ctrl_stats);

	return ret;
}
Loading