History

ethtool: provide WoL settings with WOL_GET request

Implement WOL_GET request to get wake-on-lan settings for a device, traditionally available via ETHTOOL_GWOL ioctl request. As part of the implementation, provide symbolic names for wake-on-line modes as ETH_SS_WOL_MODES string set.

Michal Kubecek committed 6 years ago

Commit 51ea22b1 parent 0bda7af10 files · +176 −2Browse files

Unified · Split

10 files
  1. Documentation/networking/ethtool-netlink.rst +29 −1
  2. include/uapi/linux/ethtool.h +4 −0
  3. include/uapi/linux/ethtool_netlink.h +15 −0
  4. net/ethtool/Makefile +1 −1
  5. net/ethtool/common.c +12 −0
  6. net/ethtool/common.h +1 −0
  7. net/ethtool/netlink.c +9 −0
  8. net/ethtool/netlink.h +1 −0
  9. net/ethtool/strset.c +5 −0
  10. net/ethtool/wol.c +99 −0
Documentation/networking/ethtool-netlink.rst+29−1
@@ -187,6 +187,7 @@ Userspace to kernel: · 186 unmodified lines
187 ``ETHTOOL_MSG_LINKSTATE_GET`` get link state187 ``ETHTOOL_MSG_LINKSTATE_GET`` get link state
188 ``ETHTOOL_MSG_DEBUG_GET`` get debugging settings188 ``ETHTOOL_MSG_DEBUG_GET`` get debugging settings
189 ``ETHTOOL_MSG_DEBUG_SET`` set debugging settings189 ``ETHTOOL_MSG_DEBUG_SET`` set debugging settings
190 ``ETHTOOL_MSG_WOL_GET`` get wake-on-lan settings
190 ===================================== ================================191 ===================================== ================================
191 192
192Kernel to userspace:193Kernel to userspace:
@@ -200,6 +201,7 @@ Kernel to userspace: · 7 unmodified lines
200 ``ETHTOOL_MSG_LINKSTATE_GET_REPLY`` link state info201 ``ETHTOOL_MSG_LINKSTATE_GET_REPLY`` link state info
201 ``ETHTOOL_MSG_DEBUG_GET_REPLY`` debugging settings202 ``ETHTOOL_MSG_DEBUG_GET_REPLY`` debugging settings
202 ``ETHTOOL_MSG_DEBUG_NTF`` debugging settings notification203 ``ETHTOOL_MSG_DEBUG_NTF`` debugging settings notification
204 ``ETHTOOL_MSG_WOL_GET_REPLY`` wake-on-lan settings
203 ===================================== ================================205 ===================================== ================================
204 206
205``GET`` requests are sent by userspace applications to retrieve device207``GET`` requests are sent by userspace applications to retrieve device
@@ -474,6 +476,32 @@ Request contents: · 268 unmodified lines
474enabled debugging message types for the device.476enabled debugging message types for the device.
475 477
476 478
479WOL_GET
480=======
481
482Query device wake-on-lan settings. Unlike most "GET" type requests,
483``ETHTOOL_MSG_WOL_GET`` requires (netns) ``CAP_NET_ADMIN`` privileges as it
484(potentially) provides SecureOn(tm) password which is confidential.
485
486Request contents:
487
488 ==================================== ====== ==========================
489 ``ETHTOOL_A_WOL_HEADER`` nested request header
490 ==================================== ====== ==========================
491
492Kernel response contents:
493
494 ==================================== ====== ==========================
495 ``ETHTOOL_A_WOL_HEADER`` nested reply header
496 ``ETHTOOL_A_WOL_MODES`` bitset mask of enabled WoL modes
497 ``ETHTOOL_A_WOL_SOPASS`` binary SecureOn(tm) password
498 ==================================== ====== ==========================
499
500In reply, ``ETHTOOL_A_WOL_MODES`` mask consists of modes supported by the
501device, value of modes which are enabled. ``ETHTOOL_A_WOL_SOPASS`` is only
502included in reply if ``WAKE_MAGICSECURE`` mode is supported.
503
504
477Request translation505Request translation
478===================506===================
479 507
@@ -490,7 +518,7 @@ have their netlink replacement yet. · 10 unmodified lines
490 ``ETHTOOL_MSG_LINKMODES_SET``518 ``ETHTOOL_MSG_LINKMODES_SET``
491 ``ETHTOOL_GDRVINFO`` n/a519 ``ETHTOOL_GDRVINFO`` n/a
492 ``ETHTOOL_GREGS`` n/a520 ``ETHTOOL_GREGS`` n/a
493 ``ETHTOOL_GWOL`` n/a521 ``ETHTOOL_GWOL`` ``ETHTOOL_MSG_WOL_GET``
494 ``ETHTOOL_SWOL`` n/a522 ``ETHTOOL_SWOL`` n/a
495 ``ETHTOOL_GMSGLVL`` ``ETHTOOL_MSG_DEBUG_GET``523 ``ETHTOOL_GMSGLVL`` ``ETHTOOL_MSG_DEBUG_GET``
496 ``ETHTOOL_SMSGLVL`` ``ETHTOOL_MSG_DEBUG_SET``524 ``ETHTOOL_SMSGLVL`` ``ETHTOOL_MSG_DEBUG_SET``
include/uapi/linux/ethtool.h+4−0
@@ -595,6 +595,7 @@ struct ethtool_pauseparam { · 594 unmodified lines
595 * @ETH_SS_PHY_TUNABLES: PHY tunable names595 * @ETH_SS_PHY_TUNABLES: PHY tunable names
596 * @ETH_SS_LINK_MODES: link mode names596 * @ETH_SS_LINK_MODES: link mode names
597 * @ETH_SS_MSG_CLASSES: debug message class names597 * @ETH_SS_MSG_CLASSES: debug message class names
598 * @ETH_SS_WOL_MODES: wake-on-lan modes
598 */599 */
599enum ethtool_stringset {600enum ethtool_stringset {
600 ETH_SS_TEST = 0,601 ETH_SS_TEST = 0,
@@ -608,6 +609,7 @@ enum ethtool_stringset { · 7 unmodified lines
608 ETH_SS_PHY_TUNABLES,609 ETH_SS_PHY_TUNABLES,
609 ETH_SS_LINK_MODES,610 ETH_SS_LINK_MODES,
610 ETH_SS_MSG_CLASSES,611 ETH_SS_MSG_CLASSES,
612 ETH_SS_WOL_MODES,
611 613
612 /* add new constants above here */614 /* add new constants above here */
613 ETH_SS_COUNT615 ETH_SS_COUNT
@@ -1695,6 +1697,8 @@ static inline int ethtool_validate_duplex(__u8 duplex) · 1081 unmodified lines
1695#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */1697#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
1696#define WAKE_FILTER (1 << 7)1698#define WAKE_FILTER (1 << 7)
1697 1699
1700#define WOL_MODE_COUNT 8
1701
1698/* L2-L4 network traffic flow types */1702/* L2-L4 network traffic flow types */
1699#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */1703#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */
1700#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */1704#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */
include/uapi/linux/ethtool_netlink.h+15−0
@@ -22,6 +22,7 @@ enum { · 21 unmodified lines
22 ETHTOOL_MSG_LINKSTATE_GET,22 ETHTOOL_MSG_LINKSTATE_GET,
23 ETHTOOL_MSG_DEBUG_GET,23 ETHTOOL_MSG_DEBUG_GET,
24 ETHTOOL_MSG_DEBUG_SET,24 ETHTOOL_MSG_DEBUG_SET,
25 ETHTOOL_MSG_WOL_GET,
25 26
26 /* add new constants above here */27 /* add new constants above here */
27 __ETHTOOL_MSG_USER_CNT,28 __ETHTOOL_MSG_USER_CNT,
@@ -39,6 +40,7 @@ enum { · 11 unmodified lines
39 ETHTOOL_MSG_LINKSTATE_GET_REPLY,40 ETHTOOL_MSG_LINKSTATE_GET_REPLY,
40 ETHTOOL_MSG_DEBUG_GET_REPLY,41 ETHTOOL_MSG_DEBUG_GET_REPLY,
41 ETHTOOL_MSG_DEBUG_NTF,42 ETHTOOL_MSG_DEBUG_NTF,
43 ETHTOOL_MSG_WOL_GET_REPLY,
42 44
43 /* add new constants above here */45 /* add new constants above here */
44 __ETHTOOL_MSG_KERNEL_CNT,46 __ETHTOOL_MSG_KERNEL_CNT,
@@ -211,6 +213,19 @@ enum { · 166 unmodified lines
211 ETHTOOL_A_DEBUG_MAX = __ETHTOOL_A_DEBUG_CNT - 1213 ETHTOOL_A_DEBUG_MAX = __ETHTOOL_A_DEBUG_CNT - 1
212};214};
213 215
216/* WOL */
217
218enum {
219 ETHTOOL_A_WOL_UNSPEC,
220 ETHTOOL_A_WOL_HEADER, /* nest - _A_HEADER_* */
221 ETHTOOL_A_WOL_MODES, /* bitset */
222 ETHTOOL_A_WOL_SOPASS, /* binary */
223
224 /* add new constants above here */
225 __ETHTOOL_A_WOL_CNT,
226 ETHTOOL_A_WOL_MAX = __ETHTOOL_A_WOL_CNT - 1
227};
228
214/* generic netlink info */229/* generic netlink info */
215#define ETHTOOL_GENL_NAME "ethtool"230#define ETHTOOL_GENL_NAME "ethtool"
216#define ETHTOOL_GENL_VERSION 1231#define ETHTOOL_GENL_VERSION 1
net/ethtool/Makefile+1−1
@@ -5,4 +5,4 @@ obj-y += ioctl.o common.o · 4 unmodified lines
5obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o5obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
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.o8 linkstate.o debug.o wol.o
net/ethtool/common.c+12−0
@@ -190,6 +190,18 @@ const char netif_msg_class_names[][ETH_GSTRING_LEN] = { · 189 unmodified lines
190};190};
191static_assert(ARRAY_SIZE(netif_msg_class_names) == NETIF_MSG_CLASS_COUNT);191static_assert(ARRAY_SIZE(netif_msg_class_names) == NETIF_MSG_CLASS_COUNT);
192 192
193const char wol_mode_names[][ETH_GSTRING_LEN] = {
194 [const_ilog2(WAKE_PHY)] = "phy",
195 [const_ilog2(WAKE_UCAST)] = "ucast",
196 [const_ilog2(WAKE_MCAST)] = "mcast",
197 [const_ilog2(WAKE_BCAST)] = "bcast",
198 [const_ilog2(WAKE_ARP)] = "arp",
199 [const_ilog2(WAKE_MAGIC)] = "magic",
200 [const_ilog2(WAKE_MAGICSECURE)] = "magicsecure",
201 [const_ilog2(WAKE_FILTER)] = "filter",
202};
203static_assert(ARRAY_SIZE(wol_mode_names) == WOL_MODE_COUNT);
204
193/* return false if legacy contained non-0 deprecated fields205/* return false if legacy contained non-0 deprecated fields
194 * maxtxpkt/maxrxpkt. rest of ksettings always updated206 * maxtxpkt/maxrxpkt. rest of ksettings always updated
195 */207 */
net/ethtool/common.h+1−0
@@ -20,6 +20,7 @@ extern const char · 19 unmodified lines
20phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];20phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
21extern const char link_mode_names[][ETH_GSTRING_LEN];21extern const char link_mode_names[][ETH_GSTRING_LEN];
22extern const char netif_msg_class_names[][ETH_GSTRING_LEN];22extern const char netif_msg_class_names[][ETH_GSTRING_LEN];
23extern const char wol_mode_names[][ETH_GSTRING_LEN];
23 24
24int __ethtool_get_link(struct net_device *dev);25int __ethtool_get_link(struct net_device *dev);
25 26
net/ethtool/netlink.c+9−0
@@ -214,6 +214,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { · 213 unmodified lines
214 [ETHTOOL_MSG_LINKMODES_GET] = &ethnl_linkmodes_request_ops,214 [ETHTOOL_MSG_LINKMODES_GET] = &ethnl_linkmodes_request_ops,
215 [ETHTOOL_MSG_LINKSTATE_GET] = &ethnl_linkstate_request_ops,215 [ETHTOOL_MSG_LINKSTATE_GET] = &ethnl_linkstate_request_ops,
216 [ETHTOOL_MSG_DEBUG_GET] = &ethnl_debug_request_ops,216 [ETHTOOL_MSG_DEBUG_GET] = &ethnl_debug_request_ops,
217 [ETHTOOL_MSG_WOL_GET] = &ethnl_wol_request_ops,
217};218};
218 219
219static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)220static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -679,6 +680,14 @@ static const struct genl_ops ethtool_genl_ops[] = { · 459 unmodified lines
679 .flags = GENL_UNS_ADMIN_PERM,680 .flags = GENL_UNS_ADMIN_PERM,
680 .doit = ethnl_set_debug,681 .doit = ethnl_set_debug,
681 },682 },
683 {
684 .cmd = ETHTOOL_MSG_WOL_GET,
685 .flags = GENL_UNS_ADMIN_PERM,
686 .doit = ethnl_default_doit,
687 .start = ethnl_default_start,
688 .dumpit = ethnl_default_dumpit,
689 .done = ethnl_default_done,
690 },
682};691};
683 692
684static const struct genl_multicast_group ethtool_nl_mcgrps[] = {693static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
net/ethtool/netlink.h+1−0
@@ -335,6 +335,7 @@ extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; · 334 unmodified lines
335extern const struct ethnl_request_ops ethnl_linkmodes_request_ops;335extern const struct ethnl_request_ops ethnl_linkmodes_request_ops;
336extern const struct ethnl_request_ops ethnl_linkstate_request_ops;336extern const struct ethnl_request_ops ethnl_linkstate_request_ops;
337extern const struct ethnl_request_ops ethnl_debug_request_ops;337extern const struct ethnl_request_ops ethnl_debug_request_ops;
338extern const struct ethnl_request_ops ethnl_wol_request_ops;
338 339
339int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);340int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
340int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);341int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
net/ethtool/strset.c+5−0
@@ -55,6 +55,11 @@ static const struct strset_info info_template[] = { · 54 unmodified lines
55 .count = NETIF_MSG_CLASS_COUNT,55 .count = NETIF_MSG_CLASS_COUNT,
56 .strings = netif_msg_class_names,56 .strings = netif_msg_class_names,
57 },57 },
58 [ETH_SS_WOL_MODES] = {
59 .per_dev = false,
60 .count = WOL_MODE_COUNT,
61 .strings = wol_mode_names,
62 },
58};63};
59 64
60struct strset_req_info {65struct strset_req_info {
net/ethtool/wol.c+99−0
@@ -0,0 +1,99 @@
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include "netlink.h"
4#include "common.h"
5#include "bitset.h"
6
7struct wol_req_info {
8 struct ethnl_req_info base;
9};
10
11struct wol_reply_data {
12 struct ethnl_reply_data base;
13 struct ethtool_wolinfo wol;
14 bool show_sopass;
15};
16
17#define WOL_REPDATA(__reply_base) \
18 container_of(__reply_base, struct wol_reply_data, base)
19
20static const struct nla_policy
21wol_get_policy[ETHTOOL_A_WOL_MAX + 1] = {
22 [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT },
23 [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED },
24 [ETHTOOL_A_WOL_MODES] = { .type = NLA_REJECT },
25 [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_REJECT },
26};
27
28static int wol_prepare_data(const struct ethnl_req_info *req_base,
29 struct ethnl_reply_data *reply_base,
30 struct genl_info *info)
31{
32 struct wol_reply_data *data = WOL_REPDATA(reply_base);
33 struct net_device *dev = reply_base->dev;
34 int ret;
35
36 if (!dev->ethtool_ops->get_wol)
37 return -EOPNOTSUPP;
38
39 ret = ethnl_ops_begin(dev);
40 if (ret < 0)
41 return ret;
42 dev->ethtool_ops->get_wol(dev, &data->wol);
43 ethnl_ops_complete(dev);
44 data->show_sopass = data->wol.supported & WAKE_MAGICSECURE;
45
46 return 0;
47}
48
49static int wol_reply_size(const struct ethnl_req_info *req_base,
50 const struct ethnl_reply_data *reply_base)
51{
52 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
53 const struct wol_reply_data *data = WOL_REPDATA(reply_base);
54 int len;
55
56 len = ethnl_bitset32_size(&data->wol.wolopts, &data->wol.supported,
57 WOL_MODE_COUNT, wol_mode_names, compact);
58 if (len < 0)
59 return len;
60 if (data->show_sopass)
61 len += nla_total_size(sizeof(data->wol.sopass));
62
63 return len;
64}
65
66static int wol_fill_reply(struct sk_buff *skb,
67 const struct ethnl_req_info *req_base,
68 const struct ethnl_reply_data *reply_base)
69{
70 bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
71 const struct wol_reply_data *data = WOL_REPDATA(reply_base);
72 int ret;
73
74 ret = ethnl_put_bitset32(skb, ETHTOOL_A_WOL_MODES, &data->wol.wolopts,
75 &data->wol.supported, WOL_MODE_COUNT,
76 wol_mode_names, compact);
77 if (ret < 0)
78 return ret;
79 if (data->show_sopass &&
80 nla_put(skb, ETHTOOL_A_WOL_SOPASS, sizeof(data->wol.sopass),
81 data->wol.sopass))
82 return -EMSGSIZE;
83
84 return 0;
85}
86
87const struct ethnl_request_ops ethnl_wol_request_ops = {
88 .request_cmd = ETHTOOL_MSG_WOL_GET,
89 .reply_cmd = ETHTOOL_MSG_WOL_GET_REPLY,
90 .hdr_attr = ETHTOOL_A_WOL_HEADER,
91 .max_attr = ETHTOOL_A_WOL_MAX,
92 .req_info_size = sizeof(struct wol_req_info),
93 .reply_data_size = sizeof(struct wol_reply_data),
94 .request_policy = wol_get_policy,
95
96 .prepare_data = wol_prepare_data,
97 .reply_size = wol_reply_size,
98 .fill_reply = wol_fill_reply,
99};