Skip to content

Commit 1b3b289

Browse files
committed
Merge branch 'ethtool-netlink-part-one'
Michal Kubecek says: ==================== ethtool netlink interface, part 1 This is first part of netlink based alternative userspace interface for ethtool. It aims to address some long known issues with the ioctl interface, mainly lack of extensibility, raciness, limited error reporting and absence of notifications. The goal is to allow userspace ethtool utility to provide all features it currently does but without using the ioctl interface. However, some features provided by ethtool ioctl API will be available through other netlink interfaces (rtnetlink, devlink) if it's more appropriate. The interface uses generic netlink family "ethtool" and provides multicast group "monitor" which is used for notifications. Documentation for the interface is in Documentation/networking/ethtool-netlink.rst file. The netlink interface is optional, it is built when CONFIG_ETHTOOL_NETLINK (bool) option is enabled. There are three types of request messages distinguished by suffix "_GET" (query for information), "_SET" (modify parameters) and "_ACT" (perform an action). Kernel reply messages have name with additional suffix "_REPLY" (e.g. ETHTOOL_MSG_SETTINGS_GET_REPLY). Most "_SET" and "_ACT" message types do not have matching reply type as only some of them need additional reply data beyond numeric error code and extack. Kernel also broadcasts notification messages ("_NTF" suffix) on changes. Basic concepts: - make extensions easier not only by allowing new attributes but also by imposing as few artificial limits as possible, e.g. by using arbitrary size bit sets for most bitmap attributes or by not using fixed size strings - use extack for error reporting and warnings - send netlink notifications on changes (even if they were done using the ioctl interface) and actions - avoid the racy read/modify/write cycle between kernel and userspace by sending only attributes which userspace wants to change; there is still a read/modify/write cycle between generic kernel code and ethtool_ops handler in NIC driver but it is only in kernel and under RTNL lock - reduce the number of name lists that need to be kept in sync between kernel and userspace (e.g. recognized link modes) - where feasible, allow dump requests to query specific information for all network devices - as parsing and generating netlink messages is more complicated than simply copying data structures between userspace API and ethtool_ops handlers (which most ioctl commands do), split the code into multiple files in net/ethtool directory; move net/core/ethtool.c also to this directory and rename it to ioctl.c Changes between v8 and v9: - fix ethnl_update_u8() - fix description of ETHTOOL_A_LINKSTATE_LINK in rst file - add explanation of verbose vs. compact bitset usage to documentation - link ethtool-netlink.rst into toctree Main changes between v7 and v8: - preliminary patches sent as a separate series (already in net-next) - split notification related changes out of _SET patches - drop request specific flags from common header - use FLAG/flag rather than GFLAG/gflag for global flags (as there are only global flags now) - allow device names up to ALTIFNAMSIZ characters - rename ETHTOOL_A_BITSET_LIST to ETHTOOL_A_BITSET_NOMASK - rename ETHTOOL_A_BIT{,S}_* to ETHTOOL_A_BITSET_BIT{,S}_* - use standard bitset helpers for link modes (rather than in-place conversion) - use "default" rather than "standard" for unified _GET handlers - fixed 64-bit big endian bitset code Main changes between v6 and v7: - split complex messages into small single purpose ones (drop info and request masks and one level of nesting) - separate request information and reply data into two structures - refactor bitset handling (no simultaneous u32/ulong handling but avoid kmalloc() except for long bitmaps on 64-bit big endian architectures) - use only fixed size strings internally (will be replaced by char * eventually but that will require rewriting also existing ioctl code) - rework ethnl_update_* helpers to return error code - rename request flag constants (to ETHTOOL_[GR]FLAG_ prefix) - convert documentation to rst Main changes between v5 and v6: - use ETHTOOL_MSG_ prefix for message types - replace ETHA_ prefix for netlink attributes by ETHTOOL_A_ - replace ETH_x_IM_y for infomask bits by ETHTOOL_IM_x_y - split GET reply types from SET requests and notifications - split kernel and userspace message types into different enums - remove INFO_GET requests from submitted part - drop EVENT notifications (use rtnetlink and on-demand string set load) - reorganize patches to reduce the number of intermitent warnings - unify request/reply header and its processing - another nest around strings in a string set for consistency - more consistent identifier naming - coding style cleanup - get rid of some of the helpers - set bad attribute in extack where applicable - various bug fixes - improve documentation and code comments, more kerneldoc comments - more verbose commit messages Changes between v4 and v5: - do not panic on failed initialization, only WARN() Main changes between RFC v3 and v4: - use more kerneldoc style comments - strict attribute policy checking - use macros for tables of link mode names and parameters - provide permanent hardware address in rtnetlink - coding style cleanup - split too long patches, reorder - wrap more ETHA_SETTINGS_* attributes in nests - add also some SET_* implementation into submitted part Main changes between RFC v2 and RFC v3: - do not allow building as a module (no netdev notifiers needed) - drop some obsolete fields - add permanent hw address, timestamping and private flags support - rework bitset handling to get rid of variable length arrays - notify monitor on device renames - restructure GET_SETTINGS/SET_SETTINGS messages - split too long patches and submit only first part of the series Main changes between RFC v1 and RFC v2: - support dumps for all "get" requests - provide notifications for changes related to supported request types - support getting string sets (both global and per device) - support getting/setting device features - get rid of family specific header, everything passed as attributes - split netlink code into multiple files in net/ethtool/ directory ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 356b23c + 3d2b847 commit 1b3b289

File tree

19 files changed

+3683
-55
lines changed

19 files changed

+3683
-55
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 520 additions & 0 deletions
Large diffs are not rendered by default.

Documentation/networking/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Contents:
1616
devlink-info-versions
1717
devlink-trap
1818
devlink-trap-netdevsim
19+
ethtool-netlink
1920
ieee802154
2021
j1939
2122
kapi

include/linux/ethtool_netlink.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef _LINUX_ETHTOOL_NETLINK_H_
4+
#define _LINUX_ETHTOOL_NETLINK_H_
5+
6+
#include <uapi/linux/ethtool_netlink.h>
7+
#include <linux/ethtool.h>
8+
#include <linux/netdevice.h>
9+
10+
#define __ETHTOOL_LINK_MODE_MASK_NWORDS \
11+
DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32)
12+
13+
enum ethtool_multicast_groups {
14+
ETHNL_MCGRP_MONITOR,
15+
};
16+
17+
#endif /* _LINUX_ETHTOOL_NETLINK_H_ */

include/linux/netdevice.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4393,6 +4393,15 @@ struct netdev_notifier_bonding_info {
43934393
void netdev_bonding_info_change(struct net_device *dev,
43944394
struct netdev_bonding_info *bonding_info);
43954395

4396+
#if IS_ENABLED(CONFIG_ETHTOOL_NETLINK)
4397+
void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data);
4398+
#else
4399+
static inline void ethtool_notify(struct net_device *dev, unsigned int cmd,
4400+
const void *data)
4401+
{
4402+
}
4403+
#endif
4404+
43964405
static inline
43974406
struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
43984407
{

include/uapi/linux/ethtool.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,9 @@ enum ethtool_stringset {
606606
ETH_SS_PHY_STATS,
607607
ETH_SS_PHY_TUNABLES,
608608
ETH_SS_LINK_MODES,
609+
610+
/* add new constants above here */
611+
ETH_SS_COUNT
609612
};
610613

611614
/**

include/uapi/linux/ethtool_netlink.h

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
2+
/*
3+
* include/uapi/linux/ethtool_netlink.h - netlink interface for ethtool
4+
*
5+
* See Documentation/networking/ethtool-netlink.txt in kernel source tree for
6+
* doucumentation of the interface.
7+
*/
8+
9+
#ifndef _UAPI_LINUX_ETHTOOL_NETLINK_H_
10+
#define _UAPI_LINUX_ETHTOOL_NETLINK_H_
11+
12+
#include <linux/ethtool.h>
13+
14+
/* message types - userspace to kernel */
15+
enum {
16+
ETHTOOL_MSG_USER_NONE,
17+
ETHTOOL_MSG_STRSET_GET,
18+
ETHTOOL_MSG_LINKINFO_GET,
19+
ETHTOOL_MSG_LINKINFO_SET,
20+
ETHTOOL_MSG_LINKMODES_GET,
21+
ETHTOOL_MSG_LINKMODES_SET,
22+
ETHTOOL_MSG_LINKSTATE_GET,
23+
24+
/* add new constants above here */
25+
__ETHTOOL_MSG_USER_CNT,
26+
ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
27+
};
28+
29+
/* message types - kernel to userspace */
30+
enum {
31+
ETHTOOL_MSG_KERNEL_NONE,
32+
ETHTOOL_MSG_STRSET_GET_REPLY,
33+
ETHTOOL_MSG_LINKINFO_GET_REPLY,
34+
ETHTOOL_MSG_LINKINFO_NTF,
35+
ETHTOOL_MSG_LINKMODES_GET_REPLY,
36+
ETHTOOL_MSG_LINKMODES_NTF,
37+
ETHTOOL_MSG_LINKSTATE_GET_REPLY,
38+
39+
/* add new constants above here */
40+
__ETHTOOL_MSG_KERNEL_CNT,
41+
ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1
42+
};
43+
44+
/* request header */
45+
46+
/* use compact bitsets in reply */
47+
#define ETHTOOL_FLAG_COMPACT_BITSETS (1 << 0)
48+
/* provide optional reply for SET or ACT requests */
49+
#define ETHTOOL_FLAG_OMIT_REPLY (1 << 1)
50+
51+
#define ETHTOOL_FLAG_ALL (ETHTOOL_FLAG_COMPACT_BITSETS | \
52+
ETHTOOL_FLAG_OMIT_REPLY)
53+
54+
enum {
55+
ETHTOOL_A_HEADER_UNSPEC,
56+
ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */
57+
ETHTOOL_A_HEADER_DEV_NAME, /* string */
58+
ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */
59+
60+
/* add new constants above here */
61+
__ETHTOOL_A_HEADER_CNT,
62+
ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1
63+
};
64+
65+
/* bit sets */
66+
67+
enum {
68+
ETHTOOL_A_BITSET_BIT_UNSPEC,
69+
ETHTOOL_A_BITSET_BIT_INDEX, /* u32 */
70+
ETHTOOL_A_BITSET_BIT_NAME, /* string */
71+
ETHTOOL_A_BITSET_BIT_VALUE, /* flag */
72+
73+
/* add new constants above here */
74+
__ETHTOOL_A_BITSET_BIT_CNT,
75+
ETHTOOL_A_BITSET_BIT_MAX = __ETHTOOL_A_BITSET_BIT_CNT - 1
76+
};
77+
78+
enum {
79+
ETHTOOL_A_BITSET_BITS_UNSPEC,
80+
ETHTOOL_A_BITSET_BITS_BIT, /* nest - _A_BITSET_BIT_* */
81+
82+
/* add new constants above here */
83+
__ETHTOOL_A_BITSET_BITS_CNT,
84+
ETHTOOL_A_BITSET_BITS_MAX = __ETHTOOL_A_BITSET_BITS_CNT - 1
85+
};
86+
87+
enum {
88+
ETHTOOL_A_BITSET_UNSPEC,
89+
ETHTOOL_A_BITSET_NOMASK, /* flag */
90+
ETHTOOL_A_BITSET_SIZE, /* u32 */
91+
ETHTOOL_A_BITSET_BITS, /* nest - _A_BITSET_BITS_* */
92+
ETHTOOL_A_BITSET_VALUE, /* binary */
93+
ETHTOOL_A_BITSET_MASK, /* binary */
94+
95+
/* add new constants above here */
96+
__ETHTOOL_A_BITSET_CNT,
97+
ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1
98+
};
99+
100+
/* string sets */
101+
102+
enum {
103+
ETHTOOL_A_STRING_UNSPEC,
104+
ETHTOOL_A_STRING_INDEX, /* u32 */
105+
ETHTOOL_A_STRING_VALUE, /* string */
106+
107+
/* add new constants above here */
108+
__ETHTOOL_A_STRING_CNT,
109+
ETHTOOL_A_STRING_MAX = __ETHTOOL_A_STRING_CNT - 1
110+
};
111+
112+
enum {
113+
ETHTOOL_A_STRINGS_UNSPEC,
114+
ETHTOOL_A_STRINGS_STRING, /* nest - _A_STRINGS_* */
115+
116+
/* add new constants above here */
117+
__ETHTOOL_A_STRINGS_CNT,
118+
ETHTOOL_A_STRINGS_MAX = __ETHTOOL_A_STRINGS_CNT - 1
119+
};
120+
121+
enum {
122+
ETHTOOL_A_STRINGSET_UNSPEC,
123+
ETHTOOL_A_STRINGSET_ID, /* u32 */
124+
ETHTOOL_A_STRINGSET_COUNT, /* u32 */
125+
ETHTOOL_A_STRINGSET_STRINGS, /* nest - _A_STRINGS_* */
126+
127+
/* add new constants above here */
128+
__ETHTOOL_A_STRINGSET_CNT,
129+
ETHTOOL_A_STRINGSET_MAX = __ETHTOOL_A_STRINGSET_CNT - 1
130+
};
131+
132+
enum {
133+
ETHTOOL_A_STRINGSETS_UNSPEC,
134+
ETHTOOL_A_STRINGSETS_STRINGSET, /* nest - _A_STRINGSET_* */
135+
136+
/* add new constants above here */
137+
__ETHTOOL_A_STRINGSETS_CNT,
138+
ETHTOOL_A_STRINGSETS_MAX = __ETHTOOL_A_STRINGSETS_CNT - 1
139+
};
140+
141+
/* STRSET */
142+
143+
enum {
144+
ETHTOOL_A_STRSET_UNSPEC,
145+
ETHTOOL_A_STRSET_HEADER, /* nest - _A_HEADER_* */
146+
ETHTOOL_A_STRSET_STRINGSETS, /* nest - _A_STRINGSETS_* */
147+
ETHTOOL_A_STRSET_COUNTS_ONLY, /* flag */
148+
149+
/* add new constants above here */
150+
__ETHTOOL_A_STRSET_CNT,
151+
ETHTOOL_A_STRSET_MAX = __ETHTOOL_A_STRSET_CNT - 1
152+
};
153+
154+
/* LINKINFO */
155+
156+
enum {
157+
ETHTOOL_A_LINKINFO_UNSPEC,
158+
ETHTOOL_A_LINKINFO_HEADER, /* nest - _A_HEADER_* */
159+
ETHTOOL_A_LINKINFO_PORT, /* u8 */
160+
ETHTOOL_A_LINKINFO_PHYADDR, /* u8 */
161+
ETHTOOL_A_LINKINFO_TP_MDIX, /* u8 */
162+
ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, /* u8 */
163+
ETHTOOL_A_LINKINFO_TRANSCEIVER, /* u8 */
164+
165+
/* add new constants above here */
166+
__ETHTOOL_A_LINKINFO_CNT,
167+
ETHTOOL_A_LINKINFO_MAX = __ETHTOOL_A_LINKINFO_CNT - 1
168+
};
169+
170+
/* LINKMODES */
171+
172+
enum {
173+
ETHTOOL_A_LINKMODES_UNSPEC,
174+
ETHTOOL_A_LINKMODES_HEADER, /* nest - _A_HEADER_* */
175+
ETHTOOL_A_LINKMODES_AUTONEG, /* u8 */
176+
ETHTOOL_A_LINKMODES_OURS, /* bitset */
177+
ETHTOOL_A_LINKMODES_PEER, /* bitset */
178+
ETHTOOL_A_LINKMODES_SPEED, /* u32 */
179+
ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */
180+
181+
/* add new constants above here */
182+
__ETHTOOL_A_LINKMODES_CNT,
183+
ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1
184+
};
185+
186+
/* LINKSTATE */
187+
188+
enum {
189+
ETHTOOL_A_LINKSTATE_UNSPEC,
190+
ETHTOOL_A_LINKSTATE_HEADER, /* nest - _A_HEADER_* */
191+
ETHTOOL_A_LINKSTATE_LINK, /* u8 */
192+
193+
/* add new constants above here */
194+
__ETHTOOL_A_LINKSTATE_CNT,
195+
ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1
196+
};
197+
198+
/* generic netlink info */
199+
#define ETHTOOL_GENL_NAME "ethtool"
200+
#define ETHTOOL_GENL_VERSION 1
201+
202+
#define ETHTOOL_MCGRP_MONITOR_NAME "monitor"
203+
204+
#endif /* _UAPI_LINUX_ETHTOOL_NETLINK_H_ */

net/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,14 @@ config FAILOVER
449449
migration of VMs with direct attached VFs by failing over to the
450450
paravirtual datapath when the VF is unplugged.
451451

452+
config ETHTOOL_NETLINK
453+
bool "Netlink interface for ethtool"
454+
default y
455+
help
456+
An alternative userspace interface for ethtool based on generic
457+
netlink. It provides better extensibility and some new features,
458+
e.g. notification messages.
459+
452460
endif # if NET
453461

454462
# Used by archs to tell that they support BPF JIT compiler plus which flavour.

net/ethtool/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22

3-
obj-y += ioctl.o common.o
3+
obj-y += ioctl.o common.o
4+
5+
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
6+
7+
ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
8+
linkstate.o

0 commit comments

Comments
 (0)