History

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.

Jakub Kicinski committed 5 years ago

Commit bfad2b91 parent ca224456 files · +67 −0Browse files

Unified · Split

6 files
  1. include/linux/ethtool.h +12 −0
  2. include/uapi/linux/ethtool.h +2 −0
  3. include/uapi/linux/ethtool_netlink.h +14 −0
  4. net/ethtool/netlink.h +1 −0
  5. net/ethtool/stats.c +33 −0
  6. net/ethtool/strset.c +5 −0
include/linux/ethtool.h+12−0
@@ -285,6 +285,15 @@ struct ethtool_eth_phy_stats { · 284 unmodified lines
285 u64 SymbolErrorDuringCarrier;285 u64 SymbolErrorDuringCarrier;
286};286};
287 287
288/* Basic IEEE 802.3 MAC Ctrl statistics (30.3.3.*), not otherwise exposed
289 * via a more targeted API.
290 */
291struct ethtool_eth_ctrl_stats {
292 u64 MACControlFramesTransmitted;
293 u64 MACControlFramesReceived;
294 u64 UnsupportedOpcodesReceived;
295};
296
288/**297/**
289 * struct ethtool_pause_stats - statistics for IEEE 802.3x pause frames298 * struct ethtool_pause_stats - statistics for IEEE 802.3x pause frames
290 * @tx_pause_frames: transmitted pause frame count. Reported to user space299 * @tx_pause_frames: transmitted pause frame count. Reported to user space
@@ -524,6 +533,7 @@ struct ethtool_module_eeprom { · 233 unmodified lines
524 * read.533 * read.
525 * @get_eth_phy_stats: Query some of the IEEE 802.3 PHY statistics.534 * @get_eth_phy_stats: Query some of the IEEE 802.3 PHY statistics.
526 * @get_eth_mac_stats: Query some of the IEEE 802.3 MAC statistics.535 * @get_eth_mac_stats: Query some of the IEEE 802.3 MAC statistics.
536 * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics.
527 *537 *
528 * All operations are optional (i.e. the function pointer may be set538 * All operations are optional (i.e. the function pointer may be set
529 * to %NULL) and callers must take this into account. Callers must539 * to %NULL) and callers must take this into account. Callers must
@@ -638,6 +648,8 @@ struct ethtool_ops { · 108 unmodified lines
638 struct ethtool_eth_phy_stats *phy_stats);648 struct ethtool_eth_phy_stats *phy_stats);
639 void (*get_eth_mac_stats)(struct net_device *dev,649 void (*get_eth_mac_stats)(struct net_device *dev,
640 struct ethtool_eth_mac_stats *mac_stats);650 struct ethtool_eth_mac_stats *mac_stats);
651 void (*get_eth_ctrl_stats)(struct net_device *dev,
652 struct ethtool_eth_ctrl_stats *ctrl_stats);
641};653};
642 654
643int ethtool_check_ops(const struct ethtool_ops *ops);655int ethtool_check_ops(const struct ethtool_ops *ops);
include/uapi/linux/ethtool.h+2−0
@@ -672,6 +672,7 @@ enum ethtool_link_ext_substate_cable_issue { · 671 unmodified lines
672 * @ETH_SS_STATS_STD: standardized stats672 * @ETH_SS_STATS_STD: standardized stats
673 * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics673 * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics
674 * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics674 * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics
675 * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics
675 *676 *
676 * @ETH_SS_COUNT: number of defined string sets677 * @ETH_SS_COUNT: number of defined string sets
677 */678 */
@@ -695,6 +696,7 @@ enum ethtool_stringset { · 17 unmodified lines
695 ETH_SS_STATS_STD,696 ETH_SS_STATS_STD,
696 ETH_SS_STATS_ETH_PHY,697 ETH_SS_STATS_ETH_PHY,
697 ETH_SS_STATS_ETH_MAC,698 ETH_SS_STATS_ETH_MAC,
699 ETH_SS_STATS_ETH_CTRL,
698 700
699 /* add new constants above here */701 /* add new constants above here */
700 ETH_SS_COUNT702 ETH_SS_COUNT
include/uapi/linux/ethtool_netlink.h+14−0
@@ -699,6 +699,7 @@ enum { · 698 unmodified lines
699enum {699enum {
700 ETHTOOL_STATS_ETH_PHY,700 ETHTOOL_STATS_ETH_PHY,
701 ETHTOOL_STATS_ETH_MAC,701 ETHTOOL_STATS_ETH_MAC,
702 ETHTOOL_STATS_ETH_CTRL,
702 703
703 /* add new constants above here */704 /* add new constants above here */
704 __ETHTOOL_STATS_CNT705 __ETHTOOL_STATS_CNT
@@ -779,6 +780,19 @@ enum { · 74 unmodified lines
779 ETHTOOL_A_STATS_ETH_MAC_MAX = (__ETHTOOL_A_STATS_ETH_MAC_CNT - 1)780 ETHTOOL_A_STATS_ETH_MAC_MAX = (__ETHTOOL_A_STATS_ETH_MAC_CNT - 1)
780};781};
781 782
783enum {
784 /* 30.3.3.3 aMACControlFramesTransmitted */
785 ETHTOOL_A_STATS_ETH_CTRL_3_TX,
786 /* 30.3.3.4 aMACControlFramesReceived */
787 ETHTOOL_A_STATS_ETH_CTRL_4_RX,
788 /* 30.3.3.5 aUnsupportedOpcodesReceived */
789 ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP,
790
791 /* add new constants above here */
792 __ETHTOOL_A_STATS_ETH_CTRL_CNT,
793 ETHTOOL_A_STATS_ETH_CTRL_MAX = (__ETHTOOL_A_STATS_ETH_CTRL_CNT - 1)
794};
795
782/* generic netlink info */796/* generic netlink info */
783#define ETHTOOL_GENL_NAME "ethtool"797#define ETHTOOL_GENL_NAME "ethtool"
784#define ETHTOOL_GENL_VERSION 1798#define ETHTOOL_GENL_VERSION 1
net/ethtool/netlink.h+1−0
@@ -404,5 +404,6 @@ int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info); · 403 unmodified lines
404extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];404extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
405extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];405extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
406extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN];406extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN];
407extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN];
407 408
408#endif /* _NET_ETHTOOL_NETLINK_H */409#endif /* _NET_ETHTOOL_NETLINK_H */
net/ethtool/stats.c+33−0
@@ -16,6 +16,7 @@ struct stats_reply_data { · 15 unmodified lines
16 struct ethnl_reply_data base;16 struct ethnl_reply_data base;
17 struct ethtool_eth_phy_stats phy_stats;17 struct ethtool_eth_phy_stats phy_stats;
18 struct ethtool_eth_mac_stats mac_stats;18 struct ethtool_eth_mac_stats mac_stats;
19 struct ethtool_eth_ctrl_stats ctrl_stats;
19};20};
20 21
21#define STATS_REPDATA(__reply_base) \22#define STATS_REPDATA(__reply_base) \
@@ -24,6 +25,7 @@ struct stats_reply_data { · 2 unmodified lines
24const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {25const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
25 [ETHTOOL_STATS_ETH_PHY] = "eth-phy",26 [ETHTOOL_STATS_ETH_PHY] = "eth-phy",
26 [ETHTOOL_STATS_ETH_MAC] = "eth-mac",27 [ETHTOOL_STATS_ETH_MAC] = "eth-mac",
28 [ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl",
27};29};
28 30
29const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = {31const 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] = · 25 unmodified lines
55 [ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR] = "FrameTooLongErrors",57 [ETHTOOL_A_STATS_ETH_MAC_25_TOO_LONG_ERR] = "FrameTooLongErrors",
56};58};
57 59
60const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN] = {
61 [ETHTOOL_A_STATS_ETH_CTRL_3_TX] = "MACControlFramesTransmitted",
62 [ETHTOOL_A_STATS_ETH_CTRL_4_RX] = "MACControlFramesReceived",
63 [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP] = "UnsupportedOpcodesReceived",
64};
65
58const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1] = {66const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1] = {
59 [ETHTOOL_A_STATS_HEADER] =67 [ETHTOOL_A_STATS_HEADER] =
60 NLA_POLICY_NESTED(ethnl_header_policy),68 NLA_POLICY_NESTED(ethnl_header_policy),
@@ -98,6 +106,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, · 37 unmodified lines
98 106
99 memset(&data->phy_stats, 0xff, sizeof(data->phy_stats));107 memset(&data->phy_stats, 0xff, sizeof(data->phy_stats));
100 memset(&data->mac_stats, 0xff, sizeof(data->mac_stats));108 memset(&data->mac_stats, 0xff, sizeof(data->mac_stats));
109 memset(&data->ctrl_stats, 0xff, sizeof(data->mac_stats));
101 110
102 if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&111 if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
103 dev->ethtool_ops->get_eth_phy_stats)112 dev->ethtool_ops->get_eth_phy_stats)
@@ -105,6 +114,9 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, · 1 unmodified line
105 if (test_bit(ETHTOOL_STATS_ETH_MAC, req_info->stat_mask) &&114 if (test_bit(ETHTOOL_STATS_ETH_MAC, req_info->stat_mask) &&
106 dev->ethtool_ops->get_eth_mac_stats)115 dev->ethtool_ops->get_eth_mac_stats)
107 dev->ethtool_ops->get_eth_mac_stats(dev, &data->mac_stats);116 dev->ethtool_ops->get_eth_mac_stats(dev, &data->mac_stats);
117 if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask) &&
118 dev->ethtool_ops->get_eth_ctrl_stats)
119 dev->ethtool_ops->get_eth_ctrl_stats(dev, &data->ctrl_stats);
108 120
109 ethnl_ops_complete(dev);121 ethnl_ops_complete(dev);
110 return 0;122 return 0;
@@ -125,6 +137,10 @@ static int stats_reply_size(const struct ethnl_req_info *req_base, · 14 unmodified lines
125 n_stats += sizeof(struct ethtool_eth_mac_stats) / sizeof(u64);137 n_stats += sizeof(struct ethtool_eth_mac_stats) / sizeof(u64);
126 n_grps++;138 n_grps++;
127 }139 }
140 if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask)) {
141 n_stats += sizeof(struct ethtool_eth_ctrl_stats) / sizeof(u64);
142 n_grps++;
143 }
128 144
129 len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */145 len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */
130 nla_total_size(4) + /* _A_STATS_GRP_ID */146 nla_total_size(4) + /* _A_STATS_GRP_ID */
@@ -229,6 +245,19 @@ static int stats_put_mac_stats(struct sk_buff *skb, · 98 unmodified lines
229 return 0;245 return 0;
230}246}
231 247
248static int stats_put_ctrl_stats(struct sk_buff *skb,
249 const struct stats_reply_data *data)
250{
251 if (stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_3_TX,
252 data->ctrl_stats.MACControlFramesTransmitted) ||
253 stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_4_RX,
254 data->ctrl_stats.MACControlFramesReceived) ||
255 stat_put(skb, ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP,
256 data->ctrl_stats.UnsupportedOpcodesReceived))
257 return -EMSGSIZE;
258 return 0;
259}
260
232static int stats_put_stats(struct sk_buff *skb,261static int stats_put_stats(struct sk_buff *skb,
233 const struct stats_reply_data *data,262 const struct stats_reply_data *data,
234 u32 id, u32 ss_id,263 u32 id, u32 ss_id,
@@ -272,6 +301,10 @@ static int stats_fill_reply(struct sk_buff *skb, · 37 unmodified lines
272 ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_MAC,301 ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_MAC,
273 ETH_SS_STATS_ETH_MAC,302 ETH_SS_STATS_ETH_MAC,
274 stats_put_mac_stats);303 stats_put_mac_stats);
304 if (!ret && test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask))
305 ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_CTRL,
306 ETH_SS_STATS_ETH_CTRL,
307 stats_put_ctrl_stats);
275 308
276 return ret;309 return ret;
277}310}
net/ethtool/strset.c+5−0
@@ -95,6 +95,11 @@ static const struct strset_info info_template[] = { · 94 unmodified lines
95 .count = __ETHTOOL_A_STATS_ETH_MAC_CNT,95 .count = __ETHTOOL_A_STATS_ETH_MAC_CNT,
96 .strings = stats_eth_mac_names,96 .strings = stats_eth_mac_names,
97 },97 },
98 [ETH_SS_STATS_ETH_CTRL] = {
99 .per_dev = false,
100 .count = __ETHTOOL_A_STATS_ETH_CTRL_CNT,
101 .strings = stats_eth_ctrl_names,
102 },
98};103};
99 104
100struct strset_req_info {105struct strset_req_info {