History

ethtool: provide EEE settings with EEE_GET request

Implement EEE_GET request to get EEE settings of a network device. These are traditionally available via ETHTOOL_GEEE ioctl request. The netlink interface allows reporting EEE status for all link modes supported by kernel but only first 32 link modes are provided at the moment as only those are reported by the ethtool_ops callback and drivers. v2: fix alignment (whitespace only)

Michal Kubecek committed 6 years ago

Commit b7eeefe1 parent bf37faa6 files · +192 −2Browse files

Unified · Split

6 files
  1. Documentation/networking/ethtool-netlink.rst +33 −1
  2. include/uapi/linux/ethtool_netlink.h +19 −0
  3. net/ethtool/Makefile +1 −1
  4. net/ethtool/eee.c +130 −0
  5. net/ethtool/netlink.c +8 −0
  6. net/ethtool/netlink.h +1 −0
Documentation/networking/ethtool-netlink.rst+33−1
@@ -201,6 +201,7 @@ Userspace to kernel: · 200 unmodified lines
201 ``ETHTOOL_MSG_COALESCE_SET`` set coalescing parameters201 ``ETHTOOL_MSG_COALESCE_SET`` set coalescing parameters
202 ``ETHTOOL_MSG_PAUSE_GET`` get pause parameters202 ``ETHTOOL_MSG_PAUSE_GET`` get pause parameters
203 ``ETHTOOL_MSG_PAUSE_SET`` set pause parameters203 ``ETHTOOL_MSG_PAUSE_SET`` set pause parameters
204 ``ETHTOOL_MSG_EEE_GET`` get EEE settings
204 ===================================== ================================205 ===================================== ================================
205 206
206Kernel to userspace:207Kernel to userspace:
@@ -229,6 +230,7 @@ Kernel to userspace: · 22 unmodified lines
229 ``ETHTOOL_MSG_COALESCE_NTF`` coalescing parameters230 ``ETHTOOL_MSG_COALESCE_NTF`` coalescing parameters
230 ``ETHTOOL_MSG_PAUSE_GET_REPLY`` pause parameters231 ``ETHTOOL_MSG_PAUSE_GET_REPLY`` pause parameters
231 ``ETHTOOL_MSG_PAUSE_NTF`` pause parameters232 ``ETHTOOL_MSG_PAUSE_NTF`` pause parameters
233 ``ETHTOOL_MSG_EEE_GET_REPLY`` EEE settings
232 ===================================== =================================234 ===================================== =================================
233 235
234``GET`` requests are sent by userspace applications to retrieve device236``GET`` requests are sent by userspace applications to retrieve device
@@ -872,6 +874,36 @@ Request contents: · 637 unmodified lines
872 ===================================== ====== ==========================874 ===================================== ====== ==========================
873 875
874 876
877EEE_GET
878=======
879
880Gets channel counts like ``ETHTOOL_GEEE`` ioctl request.
881
882Request contents:
883
884 ===================================== ====== ==========================
885 ``ETHTOOL_A_EEE_HEADER`` nested request header
886 ===================================== ====== ==========================
887
888Kernel response contents:
889
890 ===================================== ====== ==========================
891 ``ETHTOOL_A_EEE_HEADER`` nested request header
892 ``ETHTOOL_A_EEE_MODES_OURS`` bool supported/advertised modes
893 ``ETHTOOL_A_EEE_MODES_PEER`` bool peer advertised link modes
894 ``ETHTOOL_A_EEE_ACTIVE`` bool EEE is actively used
895 ``ETHTOOL_A_EEE_ENABLED`` bool EEE is enabled
896 ``ETHTOOL_A_EEE_TX_LPI_ENABLED`` bool Tx lpi enabled
897 ``ETHTOOL_A_EEE_TX_LPI_TIMER`` u32 Tx lpi timeout (in us)
898 ===================================== ====== ==========================
899
900In ``ETHTOOL_A_EEE_MODES_OURS``, mask consists of link modes for which EEE is
901enabled, value of link modes for which EEE is advertised. Link modes for which
902peer advertises EEE are listed in ``ETHTOOL_A_EEE_MODES_PEER`` (no mask). The
903netlink interface allows reporting EEE status for all link modes but only
904first 32 are provided by the ``ethtool_ops`` callback.
905
906
875Request translation907Request translation
876===================908===================
877 909
@@ -950,7 +982,7 @@ have their netlink replacement yet. · 72 unmodified lines
950 ``ETHTOOL_GET_TS_INFO`` n/a982 ``ETHTOOL_GET_TS_INFO`` n/a
951 ``ETHTOOL_GMODULEINFO`` n/a983 ``ETHTOOL_GMODULEINFO`` n/a
952 ``ETHTOOL_GMODULEEEPROM`` n/a984 ``ETHTOOL_GMODULEEEPROM`` n/a
953 ``ETHTOOL_GEEE`` n/a985 ``ETHTOOL_GEEE`` ``ETHTOOL_MSG_EEE_GET``
954 ``ETHTOOL_SEEE`` n/a986 ``ETHTOOL_SEEE`` n/a
955 ``ETHTOOL_GRSSH`` n/a987 ``ETHTOOL_GRSSH`` n/a
956 ``ETHTOOL_SRSSH`` n/a988 ``ETHTOOL_SRSSH`` n/a
include/uapi/linux/ethtool_netlink.h+19−0
@@ -36,6 +36,7 @@ enum { · 35 unmodified lines
36 ETHTOOL_MSG_COALESCE_SET,36 ETHTOOL_MSG_COALESCE_SET,
37 ETHTOOL_MSG_PAUSE_GET,37 ETHTOOL_MSG_PAUSE_GET,
38 ETHTOOL_MSG_PAUSE_SET,38 ETHTOOL_MSG_PAUSE_SET,
39 ETHTOOL_MSG_EEE_GET,
39 40
40 /* add new constants above here */41 /* add new constants above here */
41 __ETHTOOL_MSG_USER_CNT,42 __ETHTOOL_MSG_USER_CNT,
@@ -68,6 +69,7 @@ enum { · 26 unmodified lines
68 ETHTOOL_MSG_COALESCE_NTF,69 ETHTOOL_MSG_COALESCE_NTF,
69 ETHTOOL_MSG_PAUSE_GET_REPLY,70 ETHTOOL_MSG_PAUSE_GET_REPLY,
70 ETHTOOL_MSG_PAUSE_NTF,71 ETHTOOL_MSG_PAUSE_NTF,
72 ETHTOOL_MSG_EEE_GET_REPLY,
71 73
72 /* add new constants above here */74 /* add new constants above here */
73 __ETHTOOL_MSG_KERNEL_CNT,75 __ETHTOOL_MSG_KERNEL_CNT,
@@ -365,6 +367,23 @@ enum { · 291 unmodified lines
365 ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)367 ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
366};368};
367 369
370/* EEE */
371
372enum {
373 ETHTOOL_A_EEE_UNSPEC,
374 ETHTOOL_A_EEE_HEADER, /* nest - _A_HEADER_* */
375 ETHTOOL_A_EEE_MODES_OURS, /* bitset */
376 ETHTOOL_A_EEE_MODES_PEER, /* bitset */
377 ETHTOOL_A_EEE_ACTIVE, /* u8 */
378 ETHTOOL_A_EEE_ENABLED, /* u8 */
379 ETHTOOL_A_EEE_TX_LPI_ENABLED, /* u8 */
380 ETHTOOL_A_EEE_TX_LPI_TIMER, /* u32 */
381
382 /* add new constants above here */
383 __ETHTOOL_A_EEE_CNT,
384 ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1)
385};
386
368/* generic netlink info */387/* generic netlink info */
369#define ETHTOOL_GENL_NAME "ethtool"388#define ETHTOOL_GENL_NAME "ethtool"
370#define ETHTOOL_GENL_VERSION 1389#define ETHTOOL_GENL_VERSION 1
net/ethtool/Makefile+1−1
@@ -6,4 +6,4 @@ obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o · 5 unmodified lines
6 6
7ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \7ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
8 linkstate.o debug.o wol.o features.o privflags.o rings.o \8 linkstate.o debug.o wol.o features.o privflags.o rings.o \
9 channels.o coalesce.o pause.o9 channels.o coalesce.o pause.o eee.o
net/ethtool/eee.c+130−0
@@ -0,0 +1,130 @@
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include "netlink.h"
4#include "common.h"
5#include "bitset.h"
6
7#define EEE_MODES_COUNT \
8 (sizeof_field(struct ethtool_eee, supported) * BITS_PER_BYTE)
9
10struct eee_req_info {
11 struct ethnl_req_info base;
12};
13
14struct eee_reply_data {
15 struct ethnl_reply_data base;
16 struct ethtool_eee eee;
17};
18
19#define EEE_REPDATA(__reply_base) \
20 container_of(__reply_base, struct eee_reply_data, base)
21
22static const struct nla_policy
23eee_get_policy[ETHTOOL_A_EEE_MAX + 1] = {
24 [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT },
25 [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED },
26 [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_REJECT },
27 [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT },
28 [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT },
29 [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_REJECT },
30 [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_REJECT },
31 [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_REJECT },
32};
33
34static int eee_prepare_data(const struct ethnl_req_info *req_base,
35 struct ethnl_reply_data *reply_base,
36 struct genl_info *info)
37{
38 struct eee_reply_data *data = EEE_REPDATA(reply_base);
39 struct net_device *dev = reply_base->dev;
40 int ret;
41
42 if (!dev->ethtool_ops->get_eee)
43 return -EOPNOTSUPP;
44 ret = ethnl_ops_begin(dev);
45 if (ret < 0)
46 return ret;
47 ret = dev->ethtool_ops->get_eee(dev, &data->eee);
48 ethnl_ops_complete(dev);
49
50 return ret;
51}
52
53static int eee_reply_size(const struct ethnl_req_info *req_base,
54 const struct ethnl_reply_data *reply_base)
55{
56 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
57 const struct eee_reply_data *data = EEE_REPDATA(reply_base);
58 const struct ethtool_eee *eee = &data->eee;
59 int len = 0;
60 int ret;
61
62 BUILD_BUG_ON(sizeof(eee->advertised) * BITS_PER_BYTE !=
63 EEE_MODES_COUNT);
64 BUILD_BUG_ON(sizeof(eee->lp_advertised) * BITS_PER_BYTE !=
65 EEE_MODES_COUNT);
66
67 /* MODES_OURS */
68 ret = ethnl_bitset32_size(&eee->advertised, &eee->supported,
69 EEE_MODES_COUNT, link_mode_names, compact);
70 if (ret < 0)
71 return ret;
72 len += ret;
73 /* MODES_PEERS */
74 ret = ethnl_bitset32_size(&eee->lp_advertised, NULL,
75 EEE_MODES_COUNT, link_mode_names, compact);
76 if (ret < 0)
77 return ret;
78 len += ret;
79
80 len += nla_total_size(sizeof(u8)) + /* _EEE_ACTIVE */
81 nla_total_size(sizeof(u8)) + /* _EEE_ENABLED */
82 nla_total_size(sizeof(u8)) + /* _EEE_TX_LPI_ENABLED */
83 nla_total_size(sizeof(u32)); /* _EEE_TX_LPI_TIMER */
84
85 return len;
86}
87
88static int eee_fill_reply(struct sk_buff *skb,
89 const struct ethnl_req_info *req_base,
90 const struct ethnl_reply_data *reply_base)
91{
92 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
93 const struct eee_reply_data *data = EEE_REPDATA(reply_base);
94 const struct ethtool_eee *eee = &data->eee;
95 int ret;
96
97 ret = ethnl_put_bitset32(skb, ETHTOOL_A_EEE_MODES_OURS,
98 &eee->advertised, &eee->supported,
99 EEE_MODES_COUNT, link_mode_names, compact);
100 if (ret < 0)
101 return ret;
102 ret = ethnl_put_bitset32(skb, ETHTOOL_A_EEE_MODES_PEER,
103 &eee->lp_advertised, NULL, EEE_MODES_COUNT,
104 link_mode_names, compact);
105 if (ret < 0)
106 return ret;
107
108 if (nla_put_u8(skb, ETHTOOL_A_EEE_ACTIVE, !!eee->eee_active) ||
109 nla_put_u8(skb, ETHTOOL_A_EEE_ENABLED, !!eee->eee_enabled) ||
110 nla_put_u8(skb, ETHTOOL_A_EEE_TX_LPI_ENABLED,
111 !!eee->tx_lpi_enabled) ||
112 nla_put_u32(skb, ETHTOOL_A_EEE_TX_LPI_TIMER, eee->tx_lpi_timer))
113 return -EMSGSIZE;
114
115 return 0;
116}
117
118const struct ethnl_request_ops ethnl_eee_request_ops = {
119 .request_cmd = ETHTOOL_MSG_EEE_GET,
120 .reply_cmd = ETHTOOL_MSG_EEE_GET_REPLY,
121 .hdr_attr = ETHTOOL_A_EEE_HEADER,
122 .max_attr = ETHTOOL_A_EEE_MAX,
123 .req_info_size = sizeof(struct eee_req_info),
124 .reply_data_size = sizeof(struct eee_reply_data),
125 .request_policy = eee_get_policy,
126
127 .prepare_data = eee_prepare_data,
128 .reply_size = eee_reply_size,
129 .fill_reply = eee_fill_reply,
130};
net/ethtool/netlink.c+8−0
@@ -229,6 +229,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { · 228 unmodified lines
229 [ETHTOOL_MSG_CHANNELS_GET] = &ethnl_channels_request_ops,229 [ETHTOOL_MSG_CHANNELS_GET] = &ethnl_channels_request_ops,
230 [ETHTOOL_MSG_COALESCE_GET] = &ethnl_coalesce_request_ops,230 [ETHTOOL_MSG_COALESCE_GET] = &ethnl_coalesce_request_ops,
231 [ETHTOOL_MSG_PAUSE_GET] = &ethnl_pause_request_ops,231 [ETHTOOL_MSG_PAUSE_GET] = &ethnl_pause_request_ops,
232 [ETHTOOL_MSG_EEE_GET] = &ethnl_eee_request_ops,
232};233};
233 234
234static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)235static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -816,6 +817,13 @@ static const struct genl_ops ethtool_genl_ops[] = { · 581 unmodified lines
816 .flags = GENL_UNS_ADMIN_PERM,817 .flags = GENL_UNS_ADMIN_PERM,
817 .doit = ethnl_set_pause,818 .doit = ethnl_set_pause,
818 },819 },
820 {
821 .cmd = ETHTOOL_MSG_EEE_GET,
822 .doit = ethnl_default_doit,
823 .start = ethnl_default_start,
824 .dumpit = ethnl_default_dumpit,
825 .done = ethnl_default_done,
826 },
819};827};
820 828
821static const struct genl_multicast_group ethtool_nl_mcgrps[] = {829static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
net/ethtool/netlink.h+1−0
@@ -343,6 +343,7 @@ extern const struct ethnl_request_ops ethnl_rings_request_ops; · 342 unmodified lines
343extern const struct ethnl_request_ops ethnl_channels_request_ops;343extern const struct ethnl_request_ops ethnl_channels_request_ops;
344extern const struct ethnl_request_ops ethnl_coalesce_request_ops;344extern const struct ethnl_request_ops ethnl_coalesce_request_ops;
345extern const struct ethnl_request_ops ethnl_pause_request_ops;345extern const struct ethnl_request_ops ethnl_pause_request_ops;
346extern const struct ethnl_request_ops ethnl_eee_request_ops;
346 347
347int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);348int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
348int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);349int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);