All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH ethtool 00/21] netlink interface update for 5.7 release
@ 2020-05-28 23:21 Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 01/21] netlink: fix build warnings Michal Kubecek
                   ` (20 more replies)
  0 siblings, 21 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

This series adds supports for netlink interface features supported in
kernel 5.7:

  - get/set netdev features (-k / -K)
  - get/set device private flags (--show-priv-flags / --set-priv-flags)
  - get/set ring sizes (-g / -G)
  - get/set channel counts (-l / -L)
  - get/set coalescing parameters (-c / -C)
  - get/set pause parameters (-a / -A)
  - get/set EEE settings (--show-eee / --set-eee)
  - get timestamping information (-T)
 
First three patches fix bugs found in existing code.

Michal Kubecek (21):
  netlink: fix build warnings
  netlink: fix nest type grouping in parser
  netlink: fix msgbuff_append() helper
  update UAPI header copies
  netlink: add more ethtool netlink message format descriptions
  selftest: omit test-features if netlink is enabled
  netlink: add netlink handler for gfeatures (-k)
  netlink: add netlink handler for sfeatures (-K)
  netlink: add netlink handler for gprivflags (--show-priv-flags)
  netlink: add netlink handler for sprivflags (--set-priv-flags)
  netlink: add netlink handler for gring (-g)
  netlink: add netlink handler for sring (-G)
  netlink: add netlink handler for gchannels (-l)
  netlink: add netlink handler for schannels (-L)
  netlink: add netlink handler for gcoalesce (-c)
  netlink: add netlink handler for scoalesce (-C)
  netlink: add netlink handler for gpause (-a)
  netlink: add netlink handler for spause (-A)
  netlink: add netlink handler for geee (--show-eee)
  netlink: add netlink handler for seee (--set-eee)
  netlink: add netlink handler for tsinfo (-T)

 Makefile.am                  |  11 +-
 common.c                     |  30 ++
 common.h                     |  19 ++
 ethtool.c                    |  79 ++----
 netlink/bitset.c             |  31 +++
 netlink/bitset.h             |   2 +
 netlink/channels.c           | 141 ++++++++++
 netlink/coalesce.c           | 269 ++++++++++++++++++
 netlink/desc-ethtool.c       | 129 ++++++++-
 netlink/eee.c                | 189 +++++++++++++
 netlink/extapi.h             |  30 ++
 netlink/features.c           | 526 +++++++++++++++++++++++++++++++++++
 netlink/monitor.c            |  56 ++++
 netlink/msgbuff.c            |   1 +
 netlink/netlink.h            |  46 +++
 netlink/parser.c             |  10 +-
 netlink/pause.c              | 222 +++++++++++++++
 netlink/privflags.c          | 158 +++++++++++
 netlink/rings.c              | 141 ++++++++++
 netlink/settings.c           |  17 +-
 netlink/tsinfo.c             | 124 +++++++++
 uapi/linux/ethtool.h         |   9 +-
 uapi/linux/ethtool_netlink.h | 175 ++++++++++++
 uapi/linux/if_link.h         |   6 +-
 uapi/linux/net_tstamp.h      |   6 +
 25 files changed, 2347 insertions(+), 80 deletions(-)
 create mode 100644 netlink/channels.c
 create mode 100644 netlink/coalesce.c
 create mode 100644 netlink/eee.c
 create mode 100644 netlink/features.c
 create mode 100644 netlink/pause.c
 create mode 100644 netlink/privflags.c
 create mode 100644 netlink/rings.c
 create mode 100644 netlink/tsinfo.c

-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH ethtool 01/21] netlink: fix build warnings
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-06-06 18:47   ` Heiko Thiery
  2020-05-28 23:21 ` [PATCH ethtool 02/21] netlink: fix nest type grouping in parser Michal Kubecek
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Depending on compiler version and options, some of these warnings may
result in build failure.

- gcc 4.8 wants __KERNEL_DIV_ROUND_UP defined before including ethtool.h
- avoid pointer arithmetic on void *

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 netlink/desc-ethtool.c | 2 +-
 netlink/parser.c       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 76c6f13e4648..423479dfc6a9 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -4,9 +4,9 @@
  * Descriptions of ethtool netlink messages and attributes for pretty print.
  */
 
+#include "../internal.h"
 #include <linux/ethtool_netlink.h>
 
-#include "../internal.h"
 #include "prettymsg.h"
 
 static const struct pretty_nla_desc __header_desc[] = {
diff --git a/netlink/parser.c b/netlink/parser.c
index fff23f2425e9..d790abedd482 100644
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -1016,7 +1016,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
 			buff = tmp_buff_find(buffs, parser->group);
 		msgbuff = buff ? &buff->msgbuff : &nlsk->msgbuff;
 
-		param_dest = dest ? (dest + parser->dest_offset) : NULL;
+		param_dest = dest ? ((char *)dest + parser->dest_offset) : NULL;
 		ret = parser->handler(nlctx, parser->type, parser->handler_data,
 				      msgbuff, param_dest);
 		if (ret < 0)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 02/21] netlink: fix nest type grouping in parser
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 01/21] netlink: fix build warnings Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-29 14:28   ` Andrew Lunn
  2020-05-28 23:21 ` [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper Michal Kubecek
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Even if we are only interested in one nested attribute when using
PARSER_GROUP_NEST group type, the temporary buffer must contain proper
netlink header and have pointer to it and payload set up correctly for
libmnl composition functions to be able to track current message size.

Fixes: 9ee9d9517542 ("netlink: add basic command line parsing helpers")
Reported-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 netlink/parser.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/netlink/parser.c b/netlink/parser.c
index d790abedd482..bd3526f31113 100644
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -957,6 +957,10 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
 		if (!buff)
 			goto out_free_buffs;
 		msgbuff = &buff->msgbuff;
+		ret = msg_init(nlctx, msgbuff, parser->group,
+			       NLM_F_REQUEST | NLM_F_ACK);
+		if (ret < 0)
+			goto out_free_buffs;
 
 		switch (group_style) {
 		case PARSER_GROUP_NEST:
@@ -966,10 +970,6 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
 				goto out_free_buffs;
 			break;
 		case PARSER_GROUP_MSG:
-			ret = msg_init(nlctx, msgbuff, parser->group,
-				       NLM_F_REQUEST | NLM_F_ACK);
-			if (ret < 0)
-				goto out_free_buffs;
 			if (ethnla_fill_header(msgbuff,
 					       ETHTOOL_A_LINKINFO_HEADER,
 					       nlctx->devname, 0))
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 01/21] netlink: fix build warnings Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 02/21] netlink: fix nest type grouping in parser Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-29 14:29   ` Andrew Lunn
  2020-05-28 23:21 ` [PATCH ethtool 04/21] update UAPI header copies Michal Kubecek
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

As msgbuff_append() only copies protocol payload, i.e. part of the buffer
without netlink and genetlink header, and mnl_nlmsg_get_payload_len() only
subtracts netlink header length, we need to subtract genetlink header
length manually to get correct length of appended data block.

Fixes: 5050607946b6 ("netlink: message buffer and composition helpers")
Reported-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 netlink/msgbuff.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/netlink/msgbuff.c b/netlink/msgbuff.c
index 74065709ef7d..216f5b946236 100644
--- a/netlink/msgbuff.c
+++ b/netlink/msgbuff.c
@@ -79,6 +79,7 @@ int msgbuff_append(struct nl_msg_buff *dest, struct nl_msg_buff *src)
 	unsigned int dest_len = MNL_ALIGN(msgbuff_len(dest));
 	int ret;
 
+	src_len -= GENL_HDRLEN;
 	ret = msgbuff_realloc(dest, dest_len + src_len);
 	if (ret < 0)
 		return ret;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 04/21] update UAPI header copies
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (2 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 05/21] netlink: add more ethtool netlink message format descriptions Michal Kubecek
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Update to kernel v5.7-rc7.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 uapi/linux/ethtool.h         |   9 +-
 uapi/linux/ethtool_netlink.h | 175 +++++++++++++++++++++++++++++++++++
 uapi/linux/if_link.h         |   6 +-
 uapi/linux/net_tstamp.h      |   6 ++
 4 files changed, 193 insertions(+), 3 deletions(-)

diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index d3dcb459195c..c5c394899270 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -594,6 +594,9 @@ struct ethtool_pauseparam {
  * @ETH_SS_LINK_MODES: link mode names
  * @ETH_SS_MSG_CLASSES: debug message class names
  * @ETH_SS_WOL_MODES: wake-on-lan modes
+ * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags
+ * @ETH_SS_TS_TX_TYPES: timestamping Tx types
+ * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters
  */
 enum ethtool_stringset {
 	ETH_SS_TEST		= 0,
@@ -608,6 +611,9 @@ enum ethtool_stringset {
 	ETH_SS_LINK_MODES,
 	ETH_SS_MSG_CLASSES,
 	ETH_SS_WOL_MODES,
+	ETH_SS_SOF_TIMESTAMPING,
+	ETH_SS_TS_TX_TYPES,
+	ETH_SS_TS_RX_FILTERS,
 
 	/* add new constants above here */
 	ETH_SS_COUNT
@@ -1521,8 +1527,7 @@ enum ethtool_link_mode_bit_indices {
 	ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71,
 	ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT	 = 72,
 	ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT	 = 73,
-	ETHTOOL_LINK_MODE_FEC_LLRS_BIT                   = 74,
-
+	ETHTOOL_LINK_MODE_FEC_LLRS_BIT			 = 74,
 	/* must be last entry */
 	__ETHTOOL_LINK_MODE_MASK_NBITS
 };
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index ad6d3a00019d..10061e4b16d9 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -24,6 +24,21 @@ enum {
 	ETHTOOL_MSG_DEBUG_SET,
 	ETHTOOL_MSG_WOL_GET,
 	ETHTOOL_MSG_WOL_SET,
+	ETHTOOL_MSG_FEATURES_GET,
+	ETHTOOL_MSG_FEATURES_SET,
+	ETHTOOL_MSG_PRIVFLAGS_GET,
+	ETHTOOL_MSG_PRIVFLAGS_SET,
+	ETHTOOL_MSG_RINGS_GET,
+	ETHTOOL_MSG_RINGS_SET,
+	ETHTOOL_MSG_CHANNELS_GET,
+	ETHTOOL_MSG_CHANNELS_SET,
+	ETHTOOL_MSG_COALESCE_GET,
+	ETHTOOL_MSG_COALESCE_SET,
+	ETHTOOL_MSG_PAUSE_GET,
+	ETHTOOL_MSG_PAUSE_SET,
+	ETHTOOL_MSG_EEE_GET,
+	ETHTOOL_MSG_EEE_SET,
+	ETHTOOL_MSG_TSINFO_GET,
 
 	/* add new constants above here */
 	__ETHTOOL_MSG_USER_CNT,
@@ -43,6 +58,22 @@ enum {
 	ETHTOOL_MSG_DEBUG_NTF,
 	ETHTOOL_MSG_WOL_GET_REPLY,
 	ETHTOOL_MSG_WOL_NTF,
+	ETHTOOL_MSG_FEATURES_GET_REPLY,
+	ETHTOOL_MSG_FEATURES_SET_REPLY,
+	ETHTOOL_MSG_FEATURES_NTF,
+	ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
+	ETHTOOL_MSG_PRIVFLAGS_NTF,
+	ETHTOOL_MSG_RINGS_GET_REPLY,
+	ETHTOOL_MSG_RINGS_NTF,
+	ETHTOOL_MSG_CHANNELS_GET_REPLY,
+	ETHTOOL_MSG_CHANNELS_NTF,
+	ETHTOOL_MSG_COALESCE_GET_REPLY,
+	ETHTOOL_MSG_COALESCE_NTF,
+	ETHTOOL_MSG_PAUSE_GET_REPLY,
+	ETHTOOL_MSG_PAUSE_NTF,
+	ETHTOOL_MSG_EEE_GET_REPLY,
+	ETHTOOL_MSG_EEE_NTF,
+	ETHTOOL_MSG_TSINFO_GET_REPLY,
 
 	/* add new constants above here */
 	__ETHTOOL_MSG_KERNEL_CNT,
@@ -228,6 +259,150 @@ enum {
 	ETHTOOL_A_WOL_MAX = __ETHTOOL_A_WOL_CNT - 1
 };
 
+/* FEATURES */
+
+enum {
+	ETHTOOL_A_FEATURES_UNSPEC,
+	ETHTOOL_A_FEATURES_HEADER,			/* nest - _A_HEADER_* */
+	ETHTOOL_A_FEATURES_HW,				/* bitset */
+	ETHTOOL_A_FEATURES_WANTED,			/* bitset */
+	ETHTOOL_A_FEATURES_ACTIVE,			/* bitset */
+	ETHTOOL_A_FEATURES_NOCHANGE,			/* bitset */
+
+	/* add new constants above here */
+	__ETHTOOL_A_FEATURES_CNT,
+	ETHTOOL_A_FEATURES_MAX = __ETHTOOL_A_FEATURES_CNT - 1
+};
+
+/* PRIVFLAGS */
+
+enum {
+	ETHTOOL_A_PRIVFLAGS_UNSPEC,
+	ETHTOOL_A_PRIVFLAGS_HEADER,			/* nest - _A_HEADER_* */
+	ETHTOOL_A_PRIVFLAGS_FLAGS,			/* bitset */
+
+	/* add new constants above here */
+	__ETHTOOL_A_PRIVFLAGS_CNT,
+	ETHTOOL_A_PRIVFLAGS_MAX = __ETHTOOL_A_PRIVFLAGS_CNT - 1
+};
+
+/* RINGS */
+
+enum {
+	ETHTOOL_A_RINGS_UNSPEC,
+	ETHTOOL_A_RINGS_HEADER,				/* nest - _A_HEADER_* */
+	ETHTOOL_A_RINGS_RX_MAX,				/* u32 */
+	ETHTOOL_A_RINGS_RX_MINI_MAX,			/* u32 */
+	ETHTOOL_A_RINGS_RX_JUMBO_MAX,			/* u32 */
+	ETHTOOL_A_RINGS_TX_MAX,				/* u32 */
+	ETHTOOL_A_RINGS_RX,				/* u32 */
+	ETHTOOL_A_RINGS_RX_MINI,			/* u32 */
+	ETHTOOL_A_RINGS_RX_JUMBO,			/* u32 */
+	ETHTOOL_A_RINGS_TX,				/* u32 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_RINGS_CNT,
+	ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
+};
+
+/* CHANNELS */
+
+enum {
+	ETHTOOL_A_CHANNELS_UNSPEC,
+	ETHTOOL_A_CHANNELS_HEADER,			/* nest - _A_HEADER_* */
+	ETHTOOL_A_CHANNELS_RX_MAX,			/* u32 */
+	ETHTOOL_A_CHANNELS_TX_MAX,			/* u32 */
+	ETHTOOL_A_CHANNELS_OTHER_MAX,			/* u32 */
+	ETHTOOL_A_CHANNELS_COMBINED_MAX,		/* u32 */
+	ETHTOOL_A_CHANNELS_RX_COUNT,			/* u32 */
+	ETHTOOL_A_CHANNELS_TX_COUNT,			/* u32 */
+	ETHTOOL_A_CHANNELS_OTHER_COUNT,			/* u32 */
+	ETHTOOL_A_CHANNELS_COMBINED_COUNT,		/* u32 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_CHANNELS_CNT,
+	ETHTOOL_A_CHANNELS_MAX = (__ETHTOOL_A_CHANNELS_CNT - 1)
+};
+
+/* COALESCE */
+
+enum {
+	ETHTOOL_A_COALESCE_UNSPEC,
+	ETHTOOL_A_COALESCE_HEADER,			/* nest - _A_HEADER_* */
+	ETHTOOL_A_COALESCE_RX_USECS,			/* u32 */
+	ETHTOOL_A_COALESCE_RX_MAX_FRAMES,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_USECS_IRQ,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_USECS,			/* u32 */
+	ETHTOOL_A_COALESCE_TX_MAX_FRAMES,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_USECS_IRQ,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ,		/* u32 */
+	ETHTOOL_A_COALESCE_STATS_BLOCK_USECS,		/* u32 */
+	ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX,		/* u8 */
+	ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX,		/* u8 */
+	ETHTOOL_A_COALESCE_PKT_RATE_LOW,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_USECS_LOW,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_USECS_LOW,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW,		/* u32 */
+	ETHTOOL_A_COALESCE_PKT_RATE_HIGH,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_USECS_HIGH,		/* u32 */
+	ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_USECS_HIGH,		/* u32 */
+	ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH,		/* u32 */
+	ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL,	/* u32 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_COALESCE_CNT,
+	ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
+};
+
+/* PAUSE */
+
+enum {
+	ETHTOOL_A_PAUSE_UNSPEC,
+	ETHTOOL_A_PAUSE_HEADER,				/* nest - _A_HEADER_* */
+	ETHTOOL_A_PAUSE_AUTONEG,			/* u8 */
+	ETHTOOL_A_PAUSE_RX,				/* u8 */
+	ETHTOOL_A_PAUSE_TX,				/* u8 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_PAUSE_CNT,
+	ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
+};
+
+/* EEE */
+
+enum {
+	ETHTOOL_A_EEE_UNSPEC,
+	ETHTOOL_A_EEE_HEADER,				/* nest - _A_HEADER_* */
+	ETHTOOL_A_EEE_MODES_OURS,			/* bitset */
+	ETHTOOL_A_EEE_MODES_PEER,			/* bitset */
+	ETHTOOL_A_EEE_ACTIVE,				/* u8 */
+	ETHTOOL_A_EEE_ENABLED,				/* u8 */
+	ETHTOOL_A_EEE_TX_LPI_ENABLED,			/* u8 */
+	ETHTOOL_A_EEE_TX_LPI_TIMER,			/* u32 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_EEE_CNT,
+	ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1)
+};
+
+/* TSINFO */
+
+enum {
+	ETHTOOL_A_TSINFO_UNSPEC,
+	ETHTOOL_A_TSINFO_HEADER,			/* nest - _A_HEADER_* */
+	ETHTOOL_A_TSINFO_TIMESTAMPING,			/* bitset */
+	ETHTOOL_A_TSINFO_TX_TYPES,			/* bitset */
+	ETHTOOL_A_TSINFO_RX_FILTERS,			/* bitset */
+	ETHTOOL_A_TSINFO_PHC_INDEX,			/* u32 */
+
+	/* add new constants above here */
+	__ETHTOOL_A_TSINFO_CNT,
+	ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
+};
+
 /* generic netlink info */
 #define ETHTOOL_GENL_NAME "ethtool"
 #define ETHTOOL_GENL_VERSION 1
diff --git a/uapi/linux/if_link.h b/uapi/linux/if_link.h
index cb88bcb47287..978f98c76be1 100644
--- a/uapi/linux/if_link.h
+++ b/uapi/linux/if_link.h
@@ -461,6 +461,7 @@ enum {
 	IFLA_MACSEC_REPLAY_PROTECT,
 	IFLA_MACSEC_VALIDATION,
 	IFLA_MACSEC_PAD,
+	IFLA_MACSEC_OFFLOAD,
 	__IFLA_MACSEC_MAX,
 };
 
@@ -487,6 +488,7 @@ enum macsec_validation_type {
 enum macsec_offload {
 	MACSEC_OFFLOAD_OFF = 0,
 	MACSEC_OFFLOAD_PHY = 1,
+	MACSEC_OFFLOAD_MAC = 2,
 	__MACSEC_OFFLOAD_END,
 	MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
 };
@@ -970,11 +972,12 @@ enum {
 #define XDP_FLAGS_SKB_MODE		(1U << 1)
 #define XDP_FLAGS_DRV_MODE		(1U << 2)
 #define XDP_FLAGS_HW_MODE		(1U << 3)
+#define XDP_FLAGS_REPLACE		(1U << 4)
 #define XDP_FLAGS_MODES			(XDP_FLAGS_SKB_MODE | \
 					 XDP_FLAGS_DRV_MODE | \
 					 XDP_FLAGS_HW_MODE)
 #define XDP_FLAGS_MASK			(XDP_FLAGS_UPDATE_IF_NOEXIST | \
-					 XDP_FLAGS_MODES)
+					 XDP_FLAGS_MODES | XDP_FLAGS_REPLACE)
 
 /* These are stored into IFLA_XDP_ATTACHED on dump. */
 enum {
@@ -994,6 +997,7 @@ enum {
 	IFLA_XDP_DRV_PROG_ID,
 	IFLA_XDP_SKB_PROG_ID,
 	IFLA_XDP_HW_PROG_ID,
+	IFLA_XDP_EXPECTED_FD,
 	__IFLA_XDP_MAX,
 };
 
diff --git a/uapi/linux/net_tstamp.h b/uapi/linux/net_tstamp.h
index f96e650d0af9..7ed0b3d1c00a 100644
--- a/uapi/linux/net_tstamp.h
+++ b/uapi/linux/net_tstamp.h
@@ -98,6 +98,9 @@ enum hwtstamp_tx_types {
 	 * receive a time stamp via the socket error queue.
 	 */
 	HWTSTAMP_TX_ONESTEP_P2P,
+
+	/* add new constants above here */
+	__HWTSTAMP_TX_CNT
 };
 
 /* possible values for hwtstamp_config->rx_filter */
@@ -140,6 +143,9 @@ enum hwtstamp_rx_filters {
 
 	/* NTP, UDP, all versions and packet modes */
 	HWTSTAMP_FILTER_NTP_ALL,
+
+	/* add new constants above here */
+	__HWTSTAMP_FILTER_CNT
 };
 
 /* SCM_TIMESTAMPING_PKTINFO control message */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 05/21] netlink: add more ethtool netlink message format descriptions
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (3 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 04/21] update UAPI header copies Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 06/21] selftest: omit test-features if netlink is enabled Michal Kubecek
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Add message format descriptions for pretty printing of messages related to
netdev features, private flags, ring sizes, channel counts, coalescing,
pause and EEE parameters and timestamping information.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 netlink/desc-ethtool.c | 127 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 423479dfc6a9..9d7493307397 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -106,6 +106,102 @@ static const struct pretty_nla_desc __wol_desc[] = {
 	NLATTR_DESC_BINARY(ETHTOOL_A_WOL_SOPASS),
 };
 
+static const struct pretty_nla_desc __features_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_FEATURES_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_FEATURES_HEADER, header),
+	NLATTR_DESC_NESTED(ETHTOOL_A_FEATURES_HW, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_FEATURES_WANTED, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_FEATURES_ACTIVE, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_FEATURES_NOCHANGE, bitset),
+};
+
+static const struct pretty_nla_desc __privflags_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_PRIVFLAGS_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_PRIVFLAGS_HEADER, header),
+	NLATTR_DESC_NESTED(ETHTOOL_A_PRIVFLAGS_FLAGS, bitset),
+};
+
+static const struct pretty_nla_desc __rings_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_RINGS_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_RINGS_HEADER, header),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX_MINI_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX_JUMBO_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_TX_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX_MINI),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_RX_JUMBO),
+	NLATTR_DESC_U32(ETHTOOL_A_RINGS_TX),
+};
+
+static const struct pretty_nla_desc __channels_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_CHANNELS_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_CHANNELS_HEADER, header),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_RX_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_TX_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_OTHER_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_COMBINED_MAX),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_RX_COUNT),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_TX_COUNT),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_OTHER_COUNT),
+	NLATTR_DESC_U32(ETHTOOL_A_CHANNELS_COMBINED_COUNT),
+};
+
+static const struct pretty_nla_desc __coalesce_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_COALESCE_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_COALESCE_HEADER, header),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_USECS),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_MAX_FRAMES),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_USECS_IRQ),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_USECS),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_MAX_FRAMES),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_USECS_IRQ),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_STATS_BLOCK_USECS),
+	NLATTR_DESC_BOOL(ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX),
+	NLATTR_DESC_BOOL(ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_PKT_RATE_LOW),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_USECS_LOW),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_USECS_LOW),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_PKT_RATE_HIGH),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_USECS_HIGH),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_USECS_HIGH),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH),
+	NLATTR_DESC_U32(ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL),
+};
+
+static const struct pretty_nla_desc __pause_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_PAUSE_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_PAUSE_HEADER, header),
+	NLATTR_DESC_BOOL(ETHTOOL_A_PAUSE_AUTONEG),
+	NLATTR_DESC_BOOL(ETHTOOL_A_PAUSE_RX),
+	NLATTR_DESC_BOOL(ETHTOOL_A_PAUSE_TX),
+};
+
+static const struct pretty_nla_desc __eee_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_EEE_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_EEE_HEADER, header),
+	NLATTR_DESC_NESTED(ETHTOOL_A_EEE_MODES_OURS, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_EEE_MODES_PEER, bitset),
+	NLATTR_DESC_BOOL(ETHTOOL_A_EEE_ACTIVE),
+	NLATTR_DESC_BOOL(ETHTOOL_A_EEE_ENABLED),
+	NLATTR_DESC_BOOL(ETHTOOL_A_EEE_TX_LPI_ENABLED),
+	NLATTR_DESC_U32(ETHTOOL_A_EEE_TX_LPI_TIMER),
+};
+
+static const struct pretty_nla_desc __tsinfo_desc[] = {
+	NLATTR_DESC_INVALID(ETHTOOL_A_TSINFO_UNSPEC),
+	NLATTR_DESC_NESTED(ETHTOOL_A_TSINFO_HEADER, header),
+	NLATTR_DESC_NESTED(ETHTOOL_A_TSINFO_TIMESTAMPING, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_TSINFO_TX_TYPES, bitset),
+	NLATTR_DESC_NESTED(ETHTOOL_A_TSINFO_RX_FILTERS, bitset),
+	NLATTR_DESC_U32(ETHTOOL_A_TSINFO_PHC_INDEX),
+};
+
 const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
 	NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE),
 	NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset),
@@ -118,6 +214,21 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
 	NLMSG_DESC(ETHTOOL_MSG_DEBUG_SET, debug),
 	NLMSG_DESC(ETHTOOL_MSG_WOL_GET, wol),
 	NLMSG_DESC(ETHTOOL_MSG_WOL_SET, wol),
+	NLMSG_DESC(ETHTOOL_MSG_FEATURES_GET, features),
+	NLMSG_DESC(ETHTOOL_MSG_FEATURES_SET, features),
+	NLMSG_DESC(ETHTOOL_MSG_PRIVFLAGS_GET, privflags),
+	NLMSG_DESC(ETHTOOL_MSG_PRIVFLAGS_SET, privflags),
+	NLMSG_DESC(ETHTOOL_MSG_RINGS_GET, rings),
+	NLMSG_DESC(ETHTOOL_MSG_RINGS_SET, rings),
+	NLMSG_DESC(ETHTOOL_MSG_CHANNELS_GET, channels),
+	NLMSG_DESC(ETHTOOL_MSG_CHANNELS_SET, channels),
+	NLMSG_DESC(ETHTOOL_MSG_COALESCE_GET, coalesce),
+	NLMSG_DESC(ETHTOOL_MSG_COALESCE_SET, coalesce),
+	NLMSG_DESC(ETHTOOL_MSG_PAUSE_GET, pause),
+	NLMSG_DESC(ETHTOOL_MSG_PAUSE_SET, pause),
+	NLMSG_DESC(ETHTOOL_MSG_EEE_GET, eee),
+	NLMSG_DESC(ETHTOOL_MSG_EEE_SET, eee),
+	NLMSG_DESC(ETHTOOL_MSG_TSINFO_GET, tsinfo),
 };
 
 const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc);
@@ -134,6 +245,22 @@ const struct pretty_nlmsg_desc ethnl_kmsg_desc[] = {
 	NLMSG_DESC(ETHTOOL_MSG_DEBUG_NTF, debug),
 	NLMSG_DESC(ETHTOOL_MSG_WOL_GET_REPLY, wol),
 	NLMSG_DESC(ETHTOOL_MSG_WOL_NTF, wol),
+	NLMSG_DESC(ETHTOOL_MSG_FEATURES_GET_REPLY, features),
+	NLMSG_DESC(ETHTOOL_MSG_FEATURES_SET_REPLY, features),
+	NLMSG_DESC(ETHTOOL_MSG_FEATURES_NTF, features),
+	NLMSG_DESC(ETHTOOL_MSG_PRIVFLAGS_GET_REPLY, privflags),
+	NLMSG_DESC(ETHTOOL_MSG_PRIVFLAGS_NTF, privflags),
+	NLMSG_DESC(ETHTOOL_MSG_RINGS_GET_REPLY, rings),
+	NLMSG_DESC(ETHTOOL_MSG_RINGS_NTF, rings),
+	NLMSG_DESC(ETHTOOL_MSG_CHANNELS_GET_REPLY, channels),
+	NLMSG_DESC(ETHTOOL_MSG_CHANNELS_NTF, channels),
+	NLMSG_DESC(ETHTOOL_MSG_COALESCE_GET_REPLY, coalesce),
+	NLMSG_DESC(ETHTOOL_MSG_COALESCE_NTF, coalesce),
+	NLMSG_DESC(ETHTOOL_MSG_PAUSE_GET_REPLY, pause),
+	NLMSG_DESC(ETHTOOL_MSG_PAUSE_NTF, pause),
+	NLMSG_DESC(ETHTOOL_MSG_EEE_GET_REPLY, eee),
+	NLMSG_DESC(ETHTOOL_MSG_EEE_NTF, eee),
+	NLMSG_DESC(ETHTOOL_MSG_TSINFO_GET_REPLY, tsinfo),
 };
 
 const unsigned int ethnl_kmsg_n_desc = ARRAY_SIZE(ethnl_kmsg_desc);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 06/21] selftest: omit test-features if netlink is enabled
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (4 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 05/21] netlink: add more ethtool netlink message format descriptions Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 07/21] netlink: add netlink handler for gfeatures (-k) Michal Kubecek
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

The test-features selftest is checking data structures passed to ioctl()
syscall. Therefore a complete rework of the test framework will be needed
to be able to perform an equivalent selftest for netlink interface. Until
such framework is implemented, disable test-features when building ethtool
with netlink support.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 0f8465f7ada9..b3ffae52f1e9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,12 +40,16 @@ AM_CPPFLAGS += @MNL_CFLAGS@
 LDADD += @MNL_LIBS@
 endif
 
-TESTS = test-cmdline test-features
-check_PROGRAMS = test-cmdline test-features
+TESTS = test-cmdline
+check_PROGRAMS = test-cmdline
 test_cmdline_SOURCES = test-cmdline.c test-common.c $(ethtool_SOURCES) 
 test_cmdline_CFLAGS = -DTEST_ETHTOOL
+if !ETHTOOL_ENABLE_NETLINK
+TESTS += test-features
+check_PROGRAMS += test-features
 test_features_SOURCES = test-features.c test-common.c $(ethtool_SOURCES) 
 test_features_CFLAGS = -DTEST_ETHTOOL
+endif
 
 dist-hook:
 	cp $(top_srcdir)/ethtool.spec $(distdir)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 07/21] netlink: add netlink handler for gfeatures (-k)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (5 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 06/21] selftest: omit test-features if netlink is enabled Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 08/21] netlink: add netlink handler for sfeatures (-K) Michal Kubecek
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -k <dev>" subcommand using ETHTOOL_MSG_FEATURES_GET
netlink message. This retrieves and displays names and values of netdev
feature flags, traditionally provided by ioctl request ETHTOOL_GFEATURES
(and some older ones).

Unlike ioctl, the netlink code does not query kernel for values of legacy
flags (ETH_FLAG_*) and computes their value from features grouped under
such flag instead so that it can get slightly different results than ioctl
implementation in cases where some new feature is not considered by kernel
code (kernel fix is going to be submitted soon).

This commit also registers the callback with monitor code so that the
monitor can display ETHTOOL_MSG_FEATURES_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am        |   1 +
 common.c           |  30 ++++++
 common.h           |  19 ++++
 ethtool.c          |  65 ++----------
 netlink/bitset.c   |  18 ++++
 netlink/bitset.h   |   1 +
 netlink/extapi.h   |   2 +
 netlink/features.c | 241 +++++++++++++++++++++++++++++++++++++++++++++
 netlink/monitor.c  |   8 ++
 netlink/netlink.h  |   1 +
 10 files changed, 331 insertions(+), 55 deletions(-)
 create mode 100644 netlink/features.c

diff --git a/Makefile.am b/Makefile.am
index b3ffae52f1e9..36ee50a9dd0c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,7 @@ ethtool_SOURCES += \
 		  netlink/monitor.c netlink/bitset.c netlink/bitset.h \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
+		  netlink/features.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/common.c b/common.c
index f9c41a32d3a3..2630e73aa601 100644
--- a/common.c
+++ b/common.c
@@ -47,6 +47,36 @@ const struct flag_info flags_msglvl[] = {
 };
 const unsigned int n_flags_msglvl = ARRAY_SIZE(flags_msglvl) - 1;
 
+const struct off_flag_def off_flag_def[] = {
+	{ "rx",     "rx-checksumming",		    "rx-checksum",
+	  ETHTOOL_GRXCSUM, ETHTOOL_SRXCSUM, ETH_FLAG_RXCSUM,	0 },
+	{ "tx",     "tx-checksumming",		    "tx-checksum-*",
+	  ETHTOOL_GTXCSUM, ETHTOOL_STXCSUM, ETH_FLAG_TXCSUM,	0 },
+	{ "sg",     "scatter-gather",		    "tx-scatter-gather*",
+	  ETHTOOL_GSG,	   ETHTOOL_SSG,     ETH_FLAG_SG,	0 },
+	{ "tso",    "tcp-segmentation-offload",	    "tx-tcp*-segmentation",
+	  ETHTOOL_GTSO,	   ETHTOOL_STSO,    ETH_FLAG_TSO,	0 },
+	{ "ufo",    "udp-fragmentation-offload",    "tx-udp-fragmentation",
+	  ETHTOOL_GUFO,	   ETHTOOL_SUFO,    ETH_FLAG_UFO,	0 },
+	{ "gso",    "generic-segmentation-offload", "tx-generic-segmentation",
+	  ETHTOOL_GGSO,	   ETHTOOL_SGSO,    ETH_FLAG_GSO,	0 },
+	{ "gro",    "generic-receive-offload",	    "rx-gro",
+	  ETHTOOL_GGRO,	   ETHTOOL_SGRO,    ETH_FLAG_GRO,	0 },
+	{ "lro",    "large-receive-offload",	    "rx-lro",
+	  0,		   0,		    ETH_FLAG_LRO,
+	  KERNEL_VERSION(2,6,24) },
+	{ "rxvlan", "rx-vlan-offload",		    "rx-vlan-hw-parse",
+	  0,		   0,		    ETH_FLAG_RXVLAN,
+	  KERNEL_VERSION(2,6,37) },
+	{ "txvlan", "tx-vlan-offload",		    "tx-vlan-hw-insert",
+	  0,		   0,		    ETH_FLAG_TXVLAN,
+	  KERNEL_VERSION(2,6,37) },
+	{ "ntuple", "ntuple-filters",		    "rx-ntuple-filter",
+	  0,		   0,		    ETH_FLAG_NTUPLE,	0 },
+	{ "rxhash", "receive-hashing",		    "rx-hashing",
+	  0,		   0,		    ETH_FLAG_RXHASH,	0 },
+};
+
 void print_flags(const struct flag_info *info, unsigned int n_info, u32 value)
 {
 	const char *sep = "";
diff --git a/common.h b/common.h
index 3a680114a7c2..b74fdfa030b3 100644
--- a/common.h
+++ b/common.h
@@ -19,6 +19,25 @@ struct flag_info {
 extern const struct flag_info flags_msglvl[];
 extern const unsigned int n_flags_msglvl;
 
+struct off_flag_def {
+	const char *short_name;
+	const char *long_name;
+	const char *kernel_name;
+	u32 get_cmd, set_cmd;
+	u32 value;
+	/* For features exposed through ETHTOOL_GFLAGS, the oldest
+	 * kernel version for which we can trust the result.  Where
+	 * the flag was added at the same time the kernel started
+	 * supporting the feature, this is 0 (to allow for backports).
+	 * Where the feature was supported before the flag was added,
+	 * it is the version that introduced the flag.
+	 */
+	u32 min_kernel_ver;
+};
+
+#define OFF_FLAG_DEF_SIZE 12
+extern const struct off_flag_def off_flag_def[OFF_FLAG_DEF_SIZE];
+
 void print_flags(const struct flag_info *info, unsigned int n_info, u32 value);
 int dump_wol(struct ethtool_wolinfo *wol);
 void dump_mdix(u8 mdix, u8 mdix_ctrl);
diff --git a/ethtool.c b/ethtool.c
index 900880aff8d6..4749f3ae52a5 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -102,51 +102,6 @@ struct cmdline_info {
 	void *seen_val;
 };
 
-struct off_flag_def {
-	const char *short_name;
-	const char *long_name;
-	const char *kernel_name;
-	u32 get_cmd, set_cmd;
-	u32 value;
-	/* For features exposed through ETHTOOL_GFLAGS, the oldest
-	 * kernel version for which we can trust the result.  Where
-	 * the flag was added at the same time the kernel started
-	 * supporting the feature, this is 0 (to allow for backports).
-	 * Where the feature was supported before the flag was added,
-	 * it is the version that introduced the flag.
-	 */
-	u32 min_kernel_ver;
-};
-static const struct off_flag_def off_flag_def[] = {
-	{ "rx",     "rx-checksumming",		    "rx-checksum",
-	  ETHTOOL_GRXCSUM, ETHTOOL_SRXCSUM, ETH_FLAG_RXCSUM,	0 },
-	{ "tx",     "tx-checksumming",		    "tx-checksum-*",
-	  ETHTOOL_GTXCSUM, ETHTOOL_STXCSUM, ETH_FLAG_TXCSUM,	0 },
-	{ "sg",     "scatter-gather",		    "tx-scatter-gather*",
-	  ETHTOOL_GSG,	   ETHTOOL_SSG,     ETH_FLAG_SG,	0 },
-	{ "tso",    "tcp-segmentation-offload",	    "tx-tcp*-segmentation",
-	  ETHTOOL_GTSO,	   ETHTOOL_STSO,    ETH_FLAG_TSO,	0 },
-	{ "ufo",    "udp-fragmentation-offload",    "tx-udp-fragmentation",
-	  ETHTOOL_GUFO,	   ETHTOOL_SUFO,    ETH_FLAG_UFO,	0 },
-	{ "gso",    "generic-segmentation-offload", "tx-generic-segmentation",
-	  ETHTOOL_GGSO,	   ETHTOOL_SGSO,    ETH_FLAG_GSO,	0 },
-	{ "gro",    "generic-receive-offload",	    "rx-gro",
-	  ETHTOOL_GGRO,	   ETHTOOL_SGRO,    ETH_FLAG_GRO,	0 },
-	{ "lro",    "large-receive-offload",	    "rx-lro",
-	  0,		   0,		    ETH_FLAG_LRO,
-	  KERNEL_VERSION(2,6,24) },
-	{ "rxvlan", "rx-vlan-offload",		    "rx-vlan-hw-parse",
-	  0,		   0,		    ETH_FLAG_RXVLAN,
-	  KERNEL_VERSION(2,6,37) },
-	{ "txvlan", "tx-vlan-offload",		    "tx-vlan-hw-insert",
-	  0,		   0,		    ETH_FLAG_TXVLAN,
-	  KERNEL_VERSION(2,6,37) },
-	{ "ntuple", "ntuple-filters",		    "rx-ntuple-filter",
-	  0,		   0,		    ETH_FLAG_NTUPLE,	0 },
-	{ "rxhash", "receive-hashing",		    "rx-hashing",
-	  0,		   0,		    ETH_FLAG_RXHASH,	0 },
-};
-
 struct feature_def {
 	char name[ETH_GSTRING_LEN];
 	int off_flag_index; /* index in off_flag_def; negative if none match */
@@ -155,7 +110,7 @@ struct feature_def {
 struct feature_defs {
 	size_t n_features;
 	/* Number of features each offload flag is associated with */
-	unsigned int off_flag_matched[ARRAY_SIZE(off_flag_def)];
+	unsigned int off_flag_matched[OFF_FLAG_DEF_SIZE];
 	/* Name and offload flag index for each feature */
 	struct feature_def def[0];
 };
@@ -1423,7 +1378,7 @@ static void dump_features(const struct feature_defs *defs,
 	int indent;
 	int i, j;
 
-	for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
+	for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
 		/* Don't show features whose state is unknown on this
 		 * kernel version
 		 */
@@ -1742,7 +1697,7 @@ static struct feature_defs *get_feature_defs(struct cmd_context *ctx)
 		defs->def[i].off_flag_index = -1;
 
 		for (j = 0;
-		     j < ARRAY_SIZE(off_flag_def) &&
+		     j < OFF_FLAG_DEF_SIZE &&
 			     defs->def[i].off_flag_index < 0;
 		     j++) {
 			const char *pattern =
@@ -2190,7 +2145,7 @@ get_features(struct cmd_context *ctx, const struct feature_defs *defs)
 
 	state->off_flags = 0;
 
-	for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
+	for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
 		value = off_flag_def[i].value;
 		if (!off_flag_def[i].get_cmd)
 			continue;
@@ -2306,8 +2261,7 @@ static int do_sfeatures(struct cmd_context *ctx)
 	/* Generate cmdline_info for legacy flags and kernel-named
 	 * features, and parse our arguments.
 	 */
-	cmdline_features = calloc(2 * ARRAY_SIZE(off_flag_def) +
-				  defs->n_features,
+	cmdline_features = calloc(2 * OFF_FLAG_DEF_SIZE + defs->n_features,
 				  sizeof(cmdline_features[0]));
 	if (!cmdline_features) {
 		perror("Cannot parse arguments");
@@ -2315,7 +2269,7 @@ static int do_sfeatures(struct cmd_context *ctx)
 		goto err;
 	}
 	j = 0;
-	for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
+	for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
 		flag_to_cmdline_info(off_flag_def[i].short_name,
 				     off_flag_def[i].value,
 				     &off_flags_wanted, &off_flags_mask,
@@ -2332,7 +2286,7 @@ static int do_sfeatures(struct cmd_context *ctx)
 			&FEATURE_WORD(efeatures->features, i, valid),
 			&cmdline_features[j++]);
 	parse_generic_cmdline(ctx, &any_changed, cmdline_features,
-			      2 * ARRAY_SIZE(off_flag_def) + defs->n_features);
+			      2 * OFF_FLAG_DEF_SIZE + defs->n_features);
 	free(cmdline_features);
 
 	if (!any_changed) {
@@ -2352,7 +2306,7 @@ static int do_sfeatures(struct cmd_context *ctx)
 		 * related features that the user did not specify and that
 		 * are not fixed.  Warn if all related features are fixed.
 		 */
-		for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
+		for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
 			int fixed = 1;
 
 			if (!(off_flags_mask & off_flag_def[i].value))
@@ -2393,7 +2347,7 @@ static int do_sfeatures(struct cmd_context *ctx)
 			goto err;
 		}
 	} else {
-		for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
+		for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
 			if (!off_flag_def[i].set_cmd)
 				continue;
 			if (off_flags_mask & off_flag_def[i].value) {
@@ -5259,6 +5213,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-k|--show-features|--show-offload",
 		.func	= do_gfeatures,
+		.nlfunc	= nl_gfeatures,
 		.help	= "Get state of protocol offload and other features"
 	},
 	{
diff --git a/netlink/bitset.c b/netlink/bitset.c
index ed109ec1d2c0..291ac7170272 100644
--- a/netlink/bitset.c
+++ b/netlink/bitset.c
@@ -153,6 +153,24 @@ err:
 	return true;
 }
 
+uint32_t *get_compact_bitset_value(const struct nlattr *bitset)
+{
+	const struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	unsigned int count;
+	int ret;
+
+	ret = mnl_attr_parse_nested(bitset, attr_cb, &tb_info);
+	if (ret < 0 ||
+	    !tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE])
+		return NULL;
+	count = mnl_attr_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
+	if (8 * mnl_attr_get_payload_len(tb[ETHTOOL_A_BITSET_VALUE]) < count)
+		return NULL;
+
+	return mnl_attr_get_payload(tb[ETHTOOL_A_BITSET_VALUE]);
+}
+
 int walk_bitset(const struct nlattr *bitset, const struct stringset *labels,
 		bitset_walk_callback cb, void *data)
 {
diff --git a/netlink/bitset.h b/netlink/bitset.h
index 4b587d2c8a04..9f3230981e40 100644
--- a/netlink/bitset.h
+++ b/netlink/bitset.h
@@ -20,6 +20,7 @@ bool bitset_get_bit(const struct nlattr *bitset, bool mask, unsigned int idx,
 		    int *retptr);
 bool bitset_is_compact(const struct nlattr *bitset);
 bool bitset_is_empty(const struct nlattr *bitset, bool mask, int *retptr);
+uint32_t *get_compact_bitset_value(const struct nlattr *bitset);
 int walk_bitset(const struct nlattr *bitset, const struct stringset *labels,
 		bitset_walk_callback cb, void *data);
 
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 9484b4c5ae7e..81c1de0df1e6 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -20,6 +20,7 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
 int nl_gset(struct cmd_context *ctx);
 int nl_sset(struct cmd_context *ctx);
 int nl_permaddr(struct cmd_context *ctx);
+int nl_gfeatures(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -44,6 +45,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gset			NULL
 #define nl_sset			NULL
 #define nl_permaddr		NULL
+#define nl_gfeatures		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/features.c b/netlink/features.c
new file mode 100644
index 000000000000..76c16dbf2e13
--- /dev/null
+++ b/netlink/features.c
@@ -0,0 +1,241 @@
+/*
+ * features.c - netlink implementation of netdev features commands
+ *
+ * Implementation of "ethtool -k <dev>".
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "strset.h"
+#include "bitset.h"
+
+/* FEATURES_GET */
+
+struct feature_results {
+	uint32_t	*hw;
+	uint32_t	*wanted;
+	uint32_t	*active;
+	uint32_t	*nochange;
+	unsigned int	count;
+	unsigned int	words;
+};
+
+static int prepare_feature_results(const struct nlattr *const *tb,
+				   struct feature_results *dest)
+{
+	unsigned int count;
+	int ret;
+
+	memset(dest, '\0', sizeof(*dest));
+	if (!tb[ETHTOOL_A_FEATURES_HW] || !tb[ETHTOOL_A_FEATURES_WANTED] ||
+	    !tb[ETHTOOL_A_FEATURES_ACTIVE] || !tb[ETHTOOL_A_FEATURES_NOCHANGE])
+		return -EFAULT;
+	count = bitset_get_count(tb[ETHTOOL_A_FEATURES_HW], &ret);
+	if (ret < 0)
+		return -EFAULT;
+	if ((bitset_get_count(tb[ETHTOOL_A_FEATURES_WANTED], &ret) != count) ||
+	    (bitset_get_count(tb[ETHTOOL_A_FEATURES_ACTIVE], &ret) != count) ||
+	    (bitset_get_count(tb[ETHTOOL_A_FEATURES_NOCHANGE], &ret) != count))
+		return -EFAULT;
+	dest->hw = get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_HW]);
+	dest->wanted = get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_WANTED]);
+	dest->active = get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_ACTIVE]);
+	dest->nochange =
+		get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_NOCHANGE]);
+	if (!dest->hw || !dest->wanted || !dest->active || !dest->nochange)
+		return -EFAULT;
+	dest->count = count;
+	dest->words = (count + 31) / 32;
+
+	return 0;
+}
+
+static bool feature_on(const uint32_t *bitmap, unsigned int idx)
+{
+	return bitmap[idx / 32] & (1 << (idx % 32));
+}
+
+static void dump_feature(const struct feature_results *results,
+			 const uint32_t *ref, const uint32_t *ref_mask,
+			 unsigned int idx, const char *name, const char *prefix)
+{
+	const char *suffix = "";
+
+	if (!name || !*name)
+		return;
+	if (ref) {
+		if (ref_mask && !feature_on(ref_mask, idx))
+			return;
+		if ((!ref_mask || feature_on(ref_mask, idx)) &&
+		    (feature_on(results->active, idx) == feature_on(ref, idx)))
+			return;
+	}
+
+	if (!feature_on(results->hw, idx) || feature_on(results->nochange, idx))
+		suffix = " [fixed]";
+	else if (feature_on(results->active, idx) !=
+		 feature_on(results->wanted, idx))
+		suffix = feature_on(results->wanted, idx) ?
+			" [requested on]" : " [requested off]";
+	printf("%s%s: %s%s\n", prefix, name,
+	       feature_on(results->active, idx) ? "on" : "off", suffix);
+}
+
+/* this assumes pattern contains no more than one asterisk */
+static bool flag_pattern_match(const char *name, const char *pattern)
+{
+	const char *p_ast = strchr(pattern, '*');
+
+	if (p_ast) {
+		size_t name_len = strlen(name);
+		size_t pattern_len = strlen(pattern);
+
+		if (name_len + 1 < pattern_len)
+			return false;
+		if (strncmp(name, pattern, p_ast - pattern))
+			return false;
+		pattern_len -= (p_ast - pattern) + 1;
+		name += name_len  - pattern_len;
+		pattern = p_ast + 1;
+	}
+	return !strcmp(name, pattern);
+}
+
+int dump_features(const struct nlattr *const *tb,
+		  const struct stringset *feature_names)
+{
+	struct feature_results results;
+	unsigned int i, j;
+	int *feature_flags = NULL;
+	int ret;
+
+	ret = prepare_feature_results(tb, &results);
+	if (ret < 0)
+		return -EFAULT;
+
+	ret = -ENOMEM;
+	feature_flags = calloc(results.count, sizeof(feature_flags[0]));
+	if (!feature_flags)
+		goto out_free;
+
+	/* map netdev features to legacy flags */
+	for (i = 0; i < results.count; i++) {
+		const char *name = get_string(feature_names, i);
+		feature_flags[i] = -1;
+
+		if (!name || !*name)
+			continue;
+		for (j = 0; j < OFF_FLAG_DEF_SIZE; j++) {
+			const char *flag_name = off_flag_def[j].kernel_name;
+
+			if (flag_pattern_match(name, flag_name)) {
+				feature_flags[i] = j;
+				break;
+			}
+		}
+	}
+	/* show legacy flags and their matching features first */
+	for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
+		unsigned int n_match = 0;
+		bool flag_value = false;
+
+		/* no kernel with netlink interface supports UFO */
+		if (off_flag_def[i].value == ETH_FLAG_UFO)
+			continue;
+
+		for (j = 0; j < results.count; j++) {
+			if (feature_flags[j] == i) {
+				n_match++;
+				flag_value = flag_value ||
+					feature_on(results.active, j);
+			}
+		}
+		if (n_match != 1)
+			printf("%s: %s\n", off_flag_def[i].long_name,
+			       flag_value ? "on" : "off");
+		if (n_match == 0)
+			continue;
+		for (j = 0; j < results.count; j++) {
+			const char *name = get_string(feature_names, j);
+
+			if (feature_flags[j] != i)
+				continue;
+			if (n_match == 1)
+				dump_feature(&results, NULL, NULL, j,
+					     off_flag_def[i].long_name, "");
+			else
+				dump_feature(&results, NULL, NULL, j, name,
+					     "\t");
+		}
+	}
+	/* and, finally, remaining netdev_features not matching legacy flags */
+	for (i = 0; i < results.count; i++) {
+		const char *name = get_string(feature_names, i);
+
+		if (!name || !*name || feature_flags[i] >= 0)
+			continue;
+		dump_feature(&results, NULL, NULL, i, name, "");
+	}
+
+out_free:
+	free(feature_flags);
+	return 0;
+}
+
+int features_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	const struct stringset *feature_names;
+	struct nl_context *nlctx = data;
+	bool silent;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	if (!nlctx->is_monitor) {
+		ret = netlink_init_ethnl2_socket(nlctx);
+		if (ret < 0)
+			return MNL_CB_ERROR;
+	}
+	feature_names = global_stringset(ETH_SS_FEATURES, nlctx->ethnl2_socket);
+
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return silent ? MNL_CB_OK : MNL_CB_ERROR;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_FEATURES_HEADER]);
+	if (!dev_ok(nlctx))
+		return MNL_CB_OK;
+
+	if (silent)
+		putchar('\n');
+	printf("Features for %s:\n", nlctx->devname);
+	ret = dump_features(tb, feature_names);
+	return (silent || !ret) ? MNL_CB_OK : MNL_CB_ERROR;
+}
+
+int nl_gfeatures(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_FEATURES_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_FEATURES_GET,
+				      ETHTOOL_A_FEATURES_HEADER,
+				      ETHTOOL_FLAG_COMPACT_BITSETS);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, features_reply_cb);
+}
diff --git a/netlink/monitor.c b/netlink/monitor.c
index e20db5fc79d4..a572e3c38463 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -31,6 +31,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_DEBUG_NTF,
 		.cb	= debug_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_FEATURES_NTF,
+		.cb	= features_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -102,6 +106,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-s|--change",
 		.cmd		= ETHTOOL_MSG_DEBUG_NTF,
 	},
+	{
+		.pattern	= "-k|--show-features|--show-offload|-K|--features|--offload",
+		.cmd		= ETHTOOL_MSG_FEATURES_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 4419be0f751a..98e38ff2d7b0 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -62,6 +62,7 @@ int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int features_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 static inline void copy_devname(char *dst, const char *src)
 {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 08/21] netlink: add netlink handler for sfeatures (-K)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (6 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 07/21] netlink: add netlink handler for gfeatures (-k) Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 09/21] netlink: add netlink handler for gprivflags (--show-priv-flags) Michal Kubecek
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -K <dev> ..." subcommand to set netdev feature flags
using ETHTOOL_MSG_FEATURES_SET netlink message. These are traditionally set
using ETHTOOL_SFEATURES ioctl request (and some older ones).

Unlike with ioctl, an attempt to set a value of a "group flag" (e.g. "tso"
or "txcsum") translates to a request to set all features in that group
(rather than letting kernel to do that); this can be a different set of
features than kernel uses (kernel fix is going to be submitted soon).

Output of the command also explicitly marks features with values changed
without being requested (e.g. because of dependencies).

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c          |   1 +
 netlink/bitset.c   |  23 +++-
 netlink/bitset.h   |   1 +
 netlink/extapi.h   |   2 +
 netlink/features.c | 285 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 307 insertions(+), 5 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index 4749f3ae52a5..7fbf159baf69 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5219,6 +5219,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-K|--features|--offload",
 		.func	= do_sfeatures,
+		.nlfunc	= nl_sfeatures,
 		.help	= "Set protocol offload and other features",
 		.xhelp	= "		FEATURE on|off ...\n"
 	},
diff --git a/netlink/bitset.c b/netlink/bitset.c
index 291ac7170272..130bcdb5b52c 100644
--- a/netlink/bitset.c
+++ b/netlink/bitset.c
@@ -153,7 +153,8 @@ err:
 	return true;
 }
 
-uint32_t *get_compact_bitset_value(const struct nlattr *bitset)
+static uint32_t *get_compact_bitset_attr(const struct nlattr *bitset,
+					 uint16_t type)
 {
 	const struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1] = {};
 	DECLARE_ATTR_TB_INFO(tb);
@@ -161,14 +162,26 @@ uint32_t *get_compact_bitset_value(const struct nlattr *bitset)
 	int ret;
 
 	ret = mnl_attr_parse_nested(bitset, attr_cb, &tb_info);
-	if (ret < 0 ||
-	    !tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE])
+	if (ret < 0)
+		return NULL;
+	if (!tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE] ||
+	    !tb[type])
 		return NULL;
 	count = mnl_attr_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
-	if (8 * mnl_attr_get_payload_len(tb[ETHTOOL_A_BITSET_VALUE]) < count)
+	if (8 * mnl_attr_get_payload_len(tb[type]) < count)
 		return NULL;
 
-	return mnl_attr_get_payload(tb[ETHTOOL_A_BITSET_VALUE]);
+	return mnl_attr_get_payload(tb[type]);
+}
+
+uint32_t *get_compact_bitset_value(const struct nlattr *bitset)
+{
+	return get_compact_bitset_attr(bitset, ETHTOOL_A_BITSET_VALUE);
+}
+
+uint32_t *get_compact_bitset_mask(const struct nlattr *bitset)
+{
+	return get_compact_bitset_attr(bitset, ETHTOOL_A_BITSET_MASK);
 }
 
 int walk_bitset(const struct nlattr *bitset, const struct stringset *labels,
diff --git a/netlink/bitset.h b/netlink/bitset.h
index 9f3230981e40..4c9cdac0e8d8 100644
--- a/netlink/bitset.h
+++ b/netlink/bitset.h
@@ -21,6 +21,7 @@ bool bitset_get_bit(const struct nlattr *bitset, bool mask, unsigned int idx,
 bool bitset_is_compact(const struct nlattr *bitset);
 bool bitset_is_empty(const struct nlattr *bitset, bool mask, int *retptr);
 uint32_t *get_compact_bitset_value(const struct nlattr *bitset);
+uint32_t *get_compact_bitset_mask(const struct nlattr *bitset);
 int walk_bitset(const struct nlattr *bitset, const struct stringset *labels,
 		bitset_walk_callback cb, void *data);
 
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 81c1de0df1e6..0dbcc8eb2e7b 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -21,6 +21,7 @@ int nl_gset(struct cmd_context *ctx);
 int nl_sset(struct cmd_context *ctx);
 int nl_permaddr(struct cmd_context *ctx);
 int nl_gfeatures(struct cmd_context *ctx);
+int nl_sfeatures(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -46,6 +47,7 @@ static inline void nl_monitor_usage(void)
 #define nl_sset			NULL
 #define nl_permaddr		NULL
 #define nl_gfeatures		NULL
+#define nl_sfeatures		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/features.c b/netlink/features.c
index 76c16dbf2e13..8b5b8588ca23 100644
--- a/netlink/features.c
+++ b/netlink/features.c
@@ -239,3 +239,288 @@ int nl_gfeatures(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, features_reply_cb);
 }
+
+/* FEATURES_SET */
+
+struct sfeatures_context {
+	uint32_t		req_mask[0];
+};
+
+static int find_feature(const char *name,
+			const struct stringset *feature_names)
+{
+	const unsigned int count = get_count(feature_names);
+	unsigned int i;
+
+	for (i = 0; i < count; i++)
+		if (!strcmp(name, get_string(feature_names, i)))
+			return i;
+
+	return -1;
+}
+
+static int fill_feature(struct nl_msg_buff *msgbuff, const char *name, bool val)
+{
+	struct nlattr *bit_attr;
+
+	bit_attr = ethnla_nest_start(msgbuff, ETHTOOL_A_BITSET_BITS_BIT);
+	if (!bit_attr)
+		return -EMSGSIZE;
+	if (ethnla_put_strz(msgbuff, ETHTOOL_A_BITSET_BIT_NAME, name))
+		return -EMSGSIZE;
+	if (ethnla_put_flag(msgbuff, ETHTOOL_A_BITSET_BIT_VALUE, val))
+		return -EMSGSIZE;
+	mnl_attr_nest_end(msgbuff->nlhdr, bit_attr);
+
+	return 0;
+}
+
+static void set_sf_req_mask(struct nl_context *nlctx, unsigned int idx)
+{
+	struct sfeatures_context *sfctx = nlctx->cmd_private;
+
+	sfctx->req_mask[idx / 32] |= (1 << (idx % 32));
+}
+
+static int fill_legacy_flag(struct nl_context *nlctx, const char *flag_name,
+			    const struct stringset *feature_names, bool val)
+{
+	struct nl_msg_buff *msgbuff = &nlctx->ethnl_socket->msgbuff;
+	const unsigned int count = get_count(feature_names);
+	unsigned int i, j;
+	int ret;
+
+	for (i = 0; i < OFF_FLAG_DEF_SIZE; i++) {
+		const char *pattern;
+
+		if (strcmp(flag_name, off_flag_def[i].short_name) &&
+		    strcmp(flag_name, off_flag_def[i].long_name))
+			continue;
+		pattern = off_flag_def[i].kernel_name;
+
+		for (j = 0; j < count; j++) {
+			const char *name = get_string(feature_names, j);
+
+			if (flag_pattern_match(name, pattern)) {
+				ret = fill_feature(msgbuff, name, val);
+				if (ret < 0)
+					return ret;
+				set_sf_req_mask(nlctx, j);
+			}
+		}
+
+		return 0;
+	}
+
+	return 1;
+}
+
+int fill_sfeatures_bitmap(struct nl_context *nlctx,
+			  const struct stringset *feature_names)
+{
+	struct nl_msg_buff *msgbuff = &nlctx->ethnl_socket->msgbuff;
+	struct nlattr *bitset_attr;
+	struct nlattr *bits_attr;
+	int ret;
+
+	ret = -EMSGSIZE;
+	bitset_attr = ethnla_nest_start(msgbuff, ETHTOOL_A_FEATURES_WANTED);
+	if (!bitset_attr)
+		return ret;
+	bits_attr = ethnla_nest_start(msgbuff, ETHTOOL_A_BITSET_BITS);
+	if (!bits_attr)
+		goto err;
+
+	while (nlctx->argc > 0) {
+		bool val;
+
+		if (!strcmp(*nlctx->argp, "--")) {
+			nlctx->argp++;
+			nlctx->argc--;
+			break;
+		}
+		ret = -EINVAL;
+		if (nlctx->argc < 2 ||
+		    (strcmp(nlctx->argp[1], "on") &&
+		     strcmp(nlctx->argp[1], "off"))) {
+			fprintf(stderr,
+				"ethtool (%s): flag '%s' for parameter '%s' is"
+				" not followed by 'on' or 'off'\n",
+				nlctx->cmd, nlctx->argp[1], nlctx->param);
+			goto err;
+		}
+
+		val = !strcmp(nlctx->argp[1], "on");
+		ret = fill_legacy_flag(nlctx, nlctx->argp[0], feature_names,
+				       val);
+		if (ret > 0) {
+			ret = fill_feature(msgbuff, nlctx->argp[0], val);
+			if (ret == 0) {
+				int idx = find_feature(nlctx->argp[0],
+						       feature_names);
+
+				if (idx >= 0)
+					set_sf_req_mask(nlctx, idx);
+			}
+		}
+		if (ret < 0)
+			goto err;
+
+		nlctx->argp += 2;
+		nlctx->argc -= 2;
+	}
+
+	ethnla_nest_end(msgbuff, bits_attr);
+	ethnla_nest_end(msgbuff, bitset_attr);
+	return 0;
+err:
+	ethnla_nest_cancel(msgbuff, bitset_attr);
+	return ret;
+}
+
+static void show_feature_changes(struct nl_context *nlctx,
+				 const struct nlattr *const *tb)
+{
+	struct sfeatures_context *sfctx = nlctx->cmd_private;
+	const struct stringset *feature_names;
+	const uint32_t *wanted_mask;
+	const uint32_t *active_mask;
+	const uint32_t *wanted_val;
+	const uint32_t *active_val;
+	unsigned int count, words;
+	unsigned int i;
+	bool diff;
+	int ret;
+
+	feature_names = global_stringset(ETH_SS_FEATURES, nlctx->ethnl_socket);
+	count = get_count(feature_names);
+	words = DIV_ROUND_UP(count, 32);
+
+	if (!tb[ETHTOOL_A_FEATURES_WANTED] || !tb[ETHTOOL_A_FEATURES_ACTIVE])
+		goto err;
+	if (bitset_get_count(tb[ETHTOOL_A_FEATURES_WANTED], &ret) != count ||
+	    ret < 0)
+		goto err;
+	if (bitset_get_count(tb[ETHTOOL_A_FEATURES_ACTIVE], &ret) != count ||
+	    ret < 0)
+		goto err;
+	wanted_val = get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_WANTED]);
+	wanted_mask = get_compact_bitset_mask(tb[ETHTOOL_A_FEATURES_WANTED]);
+	active_val = get_compact_bitset_value(tb[ETHTOOL_A_FEATURES_ACTIVE]);
+	active_mask = get_compact_bitset_mask(tb[ETHTOOL_A_FEATURES_ACTIVE]);
+	if (!wanted_val || !wanted_mask || !active_val || !active_mask)
+		goto err;
+
+	diff = false;
+	for (i = 0; i < words; i++)
+		if (wanted_mask[i] || active_mask[i])
+			diff = true;
+	if (!diff)
+		return;
+
+	/* result is not exactly as requested, show differences */
+	printf("Actual changes:\n");
+	for (i = 0; i < count; i++) {
+		const char *name = get_string(feature_names, i);
+
+		if (!name)
+			continue;
+		if (!feature_on(wanted_mask, i) && !feature_on(active_mask, i))
+			continue;
+		printf("%s: ", name);
+		if (feature_on(wanted_mask, i))
+			/* we requested a value but result is different */
+			printf("%s [requested %s]",
+			       feature_on(wanted_val, i) ? "off" : "on",
+			       feature_on(wanted_val, i) ? "on" : "off");
+		else if (!feature_on(sfctx->req_mask, i))
+			/* not requested but changed anyway */
+			printf("%s [not requested]",
+			       feature_on(active_val, i) ? "on" : "off");
+		else
+			printf("%s", feature_on(active_val, i) ? "on" : "off");
+		fputc('\n', stdout);
+	}
+
+	return;
+err:
+	fprintf(stderr, "malformed diff info from kernel\n");
+}
+
+int sfeatures_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct genlmsghdr *ghdr = (const struct genlmsghdr *)(nlhdr + 1);
+	const struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	const char *devname;
+	int ret;
+
+	if (ghdr->cmd != ETHTOOL_MSG_FEATURES_SET_REPLY) {
+		fprintf(stderr, "warning: unexpected reply message type %u\n",
+			ghdr->cmd);
+		return MNL_CB_OK;
+	}
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return ret;
+	devname = get_dev_name(tb[ETHTOOL_A_FEATURES_HEADER]);
+	if (strcmp(devname, nlctx->devname)) {
+		fprintf(stderr, "warning: unexpected message for device %s\n",
+			devname);
+		return MNL_CB_OK;
+	}
+
+	show_feature_changes(nlctx, tb);
+	return MNL_CB_OK;
+}
+
+int nl_sfeatures(struct cmd_context *ctx)
+{
+	const struct stringset *feature_names;
+	struct nl_context *nlctx = ctx->nlctx;
+	struct sfeatures_context *sfctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	unsigned int words;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_FEATURES_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "-K";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->cmd_private = &sfctx;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	feature_names = global_stringset(ETH_SS_FEATURES, nlctx->ethnl_socket);
+	words = (get_count(feature_names) + 31) / 32;
+	sfctx = malloc(sizeof(*sfctx) + words * sizeof(sfctx->req_mask[0]));
+	if (!sfctx)
+		return -ENOMEM;
+	memset(sfctx, '\0',
+	       sizeof(*sfctx) + words * sizeof(sfctx->req_mask[0]));
+	nlctx->cmd_private = sfctx;
+
+	nlctx->devname = ctx->devname;
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_FEATURES_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_FEATURES_HEADER, ctx->devname,
+			       ETHTOOL_FLAG_COMPACT_BITSETS))
+		return -EMSGSIZE;
+	ret = fill_sfeatures_bitmap(nlctx, feature_names);
+	if (ret < 0)
+		return ret;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 92;
+	ret = nlsock_process_reply(nlsk, sfeatures_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	return nlctx->exit_code ?: 92;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 09/21] netlink: add netlink handler for gprivflags (--show-priv-flags)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (7 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 08/21] netlink: add netlink handler for sfeatures (-K) Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:21 ` [PATCH ethtool 10/21] netlink: add netlink handler for sprivflags (--set-priv-flags) Michal Kubecek
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool --show-priv-flags <dev>" subcommand using
ETHTOOL_MSG_PRIVFLAGS_GET netlink message. This retrieves and displays
values of device private flags, traditionally provided by ETHTOOL_GPFLAGS
ioctl request.

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_PRIVFLAGS_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am         |   2 +-
 ethtool.c           |   1 +
 netlink/extapi.h    |   2 +
 netlink/monitor.c   |   8 ++++
 netlink/netlink.h   |   1 +
 netlink/privflags.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 netlink/privflags.c

diff --git a/Makefile.am b/Makefile.am
index 36ee50a9dd0c..0a4c4e810c1c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,7 @@ ethtool_SOURCES += \
 		  netlink/monitor.c netlink/bitset.c netlink/bitset.h \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
-		  netlink/features.c \
+		  netlink/features.c netlink/privflags.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index 7fbf159baf69..843c710eb408 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5377,6 +5377,7 @@ static const struct option args[] = {
 	{
 		.opts	= "--show-priv-flags",
 		.func	= do_gprivflags,
+		.nlfunc	= nl_gprivflags,
 		.help	= "Query private flags"
 	},
 	{
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 0dbcc8eb2e7b..1bbe3fc21271 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -22,6 +22,7 @@ int nl_sset(struct cmd_context *ctx);
 int nl_permaddr(struct cmd_context *ctx);
 int nl_gfeatures(struct cmd_context *ctx);
 int nl_sfeatures(struct cmd_context *ctx);
+int nl_gprivflags(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -48,6 +49,7 @@ static inline void nl_monitor_usage(void)
 #define nl_permaddr		NULL
 #define nl_gfeatures		NULL
 #define nl_sfeatures		NULL
+#define nl_gprivflags		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index a572e3c38463..ca2654bad71f 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -35,6 +35,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_FEATURES_NTF,
 		.cb	= features_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_PRIVFLAGS_NTF,
+		.cb	= privflags_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -110,6 +114,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-k|--show-features|--show-offload|-K|--features|--offload",
 		.cmd		= ETHTOOL_MSG_FEATURES_NTF,
 	},
+	{
+		.pattern	= "--show-priv-flags|--set-priv-flags",
+		.cmd		= ETHTOOL_MSG_PRIVFLAGS_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 98e38ff2d7b0..2e90dbe095c9 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -63,6 +63,7 @@ int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int features_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 static inline void copy_devname(char *dst, const char *src)
 {
diff --git a/netlink/privflags.c b/netlink/privflags.c
new file mode 100644
index 000000000000..b552c21ed191
--- /dev/null
+++ b/netlink/privflags.c
@@ -0,0 +1,109 @@
+/*
+ * privflags.c - netlink implementation of private flags commands
+ *
+ * Implementation of "ethtool --show-priv-flags <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "strset.h"
+#include "bitset.h"
+
+/* PRIVFLAGS_GET */
+
+static void privflags_maxlen_walk_cb(unsigned int idx, const char *name,
+				     bool val, void *data)
+{
+	unsigned int *maxlen = data;
+	unsigned int len, n;
+
+	if (name)
+		len = strlen(name);
+	else {
+		len = 3; /* strlen("bit") */
+		for (n = idx ?: 1; n; n /= 10)
+			len++; /* plus number of ditigs */
+	}
+	if (len > *maxlen)
+		*maxlen = len;
+}
+
+static void privflags_dump_walk_cb(unsigned int idx, const char *name, bool val,
+				   void *data)
+{
+	unsigned int *maxlen = data;
+	char buff[16];
+
+	if (!name) {
+		snprintf(buff, sizeof(buff) - 1, "bit%u", idx);
+		name = buff;
+	}
+	printf("%-*s: %s\n", *maxlen, name, val ? "on" : "off");
+}
+
+int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	const struct stringset *flag_names = NULL;
+	struct nl_context *nlctx = data;
+	unsigned int maxlen = 0;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0 || !tb[ETHTOOL_A_PRIVFLAGS_FLAGS])
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_PRIVFLAGS_HEADER]);
+	if (!dev_ok(nlctx))
+		return MNL_CB_OK;
+
+	if (bitset_is_compact(tb[ETHTOOL_A_PRIVFLAGS_FLAGS])) {
+		ret = netlink_init_ethnl2_socket(nlctx);
+		if (ret < 0)
+			return err_ret;
+		flag_names = perdev_stringset(nlctx->devname, ETH_SS_PRIV_FLAGS,
+					      nlctx->ethnl2_socket);
+	}
+
+	ret = walk_bitset(tb[ETHTOOL_A_PRIVFLAGS_FLAGS], flag_names,
+			  privflags_maxlen_walk_cb, &maxlen);
+	if (ret < 0)
+		return err_ret;
+	if (silent)
+		putchar('\n');
+	printf("Private flags for %s:\n", nlctx->devname);
+	ret = walk_bitset(tb[ETHTOOL_A_PRIVFLAGS_FLAGS], flag_names,
+			  privflags_dump_walk_cb, &maxlen);
+	return (ret < 0) ? err_ret : MNL_CB_OK;
+}
+
+int nl_gprivflags(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_PRIVFLAGS_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PRIVFLAGS_GET,
+				      ETHTOOL_A_PRIVFLAGS_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, privflags_reply_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 10/21] netlink: add netlink handler for sprivflags (--set-priv-flags)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (8 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 09/21] netlink: add netlink handler for gprivflags (--show-priv-flags) Michal Kubecek
@ 2020-05-28 23:21 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 11/21] netlink: add netlink handler for gring (-g) Michal Kubecek
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:21 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool --set-priv-flags <dev> ..." subcommand to set device
private flags using ETHTOOL_MSG_PRIVFLAGS_SET netlink message. These are
traditionally set using ETHTOOL_SPFLAGS ioctl request.

Unlike ioctl implementation, netlink does not retrieve private flag names
first so that names provided on command line are validated by kernel rather
than by parser. Unrecognized names are therefore interpreted as a failed
request rather than a parser error.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c           |  1 +
 netlink/extapi.h    |  2 ++
 netlink/privflags.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index 843c710eb408..81472ad40a5b 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5383,6 +5383,7 @@ static const struct option args[] = {
 	{
 		.opts	= "--set-priv-flags",
 		.func	= do_sprivflags,
+		.nlfunc	= nl_sprivflags,
 		.help	= "Set private flags",
 		.xhelp	= "		FLAG on|off ...\n"
 	},
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 1bbe3fc21271..ec5d086f05df 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -23,6 +23,7 @@ int nl_permaddr(struct cmd_context *ctx);
 int nl_gfeatures(struct cmd_context *ctx);
 int nl_sfeatures(struct cmd_context *ctx);
 int nl_gprivflags(struct cmd_context *ctx);
+int nl_sprivflags(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -50,6 +51,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gfeatures		NULL
 #define nl_sfeatures		NULL
 #define nl_gprivflags		NULL
+#define nl_sprivflags		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/privflags.c b/netlink/privflags.c
index b552c21ed191..a06cd6d88d9d 100644
--- a/netlink/privflags.c
+++ b/netlink/privflags.c
@@ -1,7 +1,8 @@
 /*
  * privflags.c - netlink implementation of private flags commands
  *
- * Implementation of "ethtool --show-priv-flags <dev>"
+ * Implementation of "ethtool --show-priv-flags <dev>" and
+ * "ethtool --set-priv-flags <dev> ..."
  */
 
 #include <errno.h>
@@ -13,6 +14,7 @@
 #include "netlink.h"
 #include "strset.h"
 #include "bitset.h"
+#include "parser.h"
 
 /* PRIVFLAGS_GET */
 
@@ -107,3 +109,50 @@ int nl_gprivflags(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, privflags_reply_cb);
 }
+
+/* PRIVFLAGS_SET */
+
+static const struct bitset_parser_data privflags_parser_data = {
+	.force_hex	= false,
+	.no_mask	= false,
+};
+
+int nl_sprivflags(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_PRIVFLAGS_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "--set-priv-flags";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_PRIVFLAGS_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_PRIVFLAGS_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parse_bitset(nlctx, ETHTOOL_A_PRIVFLAGS_FLAGS,
+			      &privflags_parser_data, msgbuff, NULL);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 2;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 1;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 11/21] netlink: add netlink handler for gring (-g)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (9 preceding siblings ...)
  2020-05-28 23:21 ` [PATCH ethtool 10/21] netlink: add netlink handler for sprivflags (--set-priv-flags) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 12/21] netlink: add netlink handler for sring (-G) Michal Kubecek
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -g <dev>" subcommand using ETHTOOL_MSG_RINGS_GET netlink
message. This retrieves and displays device ring sizes, traditionally
provided by ETHTOOL_GRINGPARAM ioctl request.

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_RINGS_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am       |  2 +-
 ethtool.c         |  1 +
 netlink/extapi.h  |  2 ++
 netlink/monitor.c |  8 ++++++
 netlink/netlink.h | 13 +++++++++
 netlink/rings.c   | 71 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 netlink/rings.c

diff --git a/Makefile.am b/Makefile.am
index 0a4c4e810c1c..f7d7b44a438d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,7 @@ ethtool_SOURCES += \
 		  netlink/monitor.c netlink/bitset.c netlink/bitset.h \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
-		  netlink/features.c netlink/privflags.c \
+		  netlink/features.c netlink/privflags.c netlink/rings.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index 81472ad40a5b..fc3fb11a6a19 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5199,6 +5199,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-g|--show-ring",
 		.func	= do_gring,
+		.nlfunc	= nl_gring,
 		.help	= "Query RX/TX ring parameters"
 	},
 	{
diff --git a/netlink/extapi.h b/netlink/extapi.h
index ec5d086f05df..3b3579d53b59 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -24,6 +24,7 @@ int nl_gfeatures(struct cmd_context *ctx);
 int nl_sfeatures(struct cmd_context *ctx);
 int nl_gprivflags(struct cmd_context *ctx);
 int nl_sprivflags(struct cmd_context *ctx);
+int nl_gring(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -52,6 +53,7 @@ static inline void nl_monitor_usage(void)
 #define nl_sfeatures		NULL
 #define nl_gprivflags		NULL
 #define nl_sprivflags		NULL
+#define nl_gring		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index ca2654bad71f..c89e6138dbec 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -39,6 +39,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_PRIVFLAGS_NTF,
 		.cb	= privflags_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_RINGS_NTF,
+		.cb	= rings_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -118,6 +122,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "--show-priv-flags|--set-priv-flags",
 		.cmd		= ETHTOOL_MSG_PRIVFLAGS_NTF,
 	},
+	{
+		.pattern	= "-g|--show-ring|-G|--set-ring",
+		.cmd		= ETHTOOL_MSG_RINGS_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 2e90dbe095c9..fe68e23cccb3 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -64,6 +64,19 @@ int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int features_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+
+/* dump helpers */
+
+static inline void show_u32(const struct nlattr *attr, const char *label)
+{
+	if (attr)
+		printf("%s%u\n", label, mnl_attr_get_u32(attr));
+	else
+		printf("%sn/a\n", label);
+}
+
+/* misc */
 
 static inline void copy_devname(char *dst, const char *src)
 {
diff --git a/netlink/rings.c b/netlink/rings.c
new file mode 100644
index 000000000000..98ee5dbedb17
--- /dev/null
+++ b/netlink/rings.c
@@ -0,0 +1,71 @@
+/*
+ * rings.c - netlink implementation of ring commands
+ *
+ * Implementation of "ethtool -g <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+
+/* RINGS_GET */
+
+int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_RINGS_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		putchar('\n');
+	printf("Ring parameters for %s:\n", nlctx->devname);
+	printf("Pre-set maximums:\n");
+	show_u32(tb[ETHTOOL_A_RINGS_RX_MAX], "RX:\t\t");
+	show_u32(tb[ETHTOOL_A_RINGS_RX_MINI_MAX], "RX Mini:\t");
+	show_u32(tb[ETHTOOL_A_RINGS_RX_JUMBO_MAX], "RX Jumbo:\t");
+	show_u32(tb[ETHTOOL_A_RINGS_TX_MAX], "TX:\t\t");
+	printf("Current hardware settings:\n");
+	show_u32(tb[ETHTOOL_A_RINGS_RX], "RX:\t\t");
+	show_u32(tb[ETHTOOL_A_RINGS_RX_MINI], "RX Mini:\t");
+	show_u32(tb[ETHTOOL_A_RINGS_RX_JUMBO], "RX Jumbo:\t");
+	show_u32(tb[ETHTOOL_A_RINGS_TX], "TX:\t\t");
+
+	return MNL_CB_OK;
+}
+
+int nl_gring(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RINGS_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_RINGS_GET,
+				      ETHTOOL_A_RINGS_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, rings_reply_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 12/21] netlink: add netlink handler for sring (-G)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (10 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 11/21] netlink: add netlink handler for gring (-g) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 13/21] netlink: add netlink handler for gchannels (-l) Michal Kubecek
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -G <dev> ..." subcommand to set network device ring
sizes using ETHTOOL_MSG_RINGS_SET netlink request. These are traditionally
set using ETHTOOL_SRINGPARAM ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c        |  1 +
 netlink/extapi.h |  2 ++
 netlink/rings.c  | 72 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index fc3fb11a6a19..bddde6d9f7c0 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5205,6 +5205,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-G|--set-ring",
 		.func	= do_sring,
+		.nlfunc	= nl_sring,
 		.help	= "Set RX/TX ring parameters",
 		.xhelp	= "		[ rx N ]\n"
 			  "		[ rx-mini N ]\n"
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 3b3579d53b59..8a3e72bc75e6 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -25,6 +25,7 @@ int nl_sfeatures(struct cmd_context *ctx);
 int nl_gprivflags(struct cmd_context *ctx);
 int nl_sprivflags(struct cmd_context *ctx);
 int nl_gring(struct cmd_context *ctx);
+int nl_sring(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -54,6 +55,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gprivflags		NULL
 #define nl_sprivflags		NULL
 #define nl_gring		NULL
+#define nl_sring		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/rings.c b/netlink/rings.c
index 98ee5dbedb17..4061520212d5 100644
--- a/netlink/rings.c
+++ b/netlink/rings.c
@@ -1,7 +1,7 @@
 /*
  * rings.c - netlink implementation of ring commands
  *
- * Implementation of "ethtool -g <dev>"
+ * Implementation of "ethtool -g <dev>" and "ethtool -G <dev> ..."
  */
 
 #include <errno.h>
@@ -11,6 +11,7 @@
 #include "../internal.h"
 #include "../common.h"
 #include "netlink.h"
+#include "parser.h"
 
 /* RINGS_GET */
 
@@ -69,3 +70,72 @@ int nl_gring(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, rings_reply_cb);
 }
+
+/* RINGS_SET */
+
+static const struct param_parser sring_params[] = {
+	{
+		.arg		= "rx",
+		.type		= ETHTOOL_A_RINGS_RX,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-mini",
+		.type		= ETHTOOL_A_RINGS_RX_MINI,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-jumbo",
+		.type		= ETHTOOL_A_RINGS_RX_JUMBO,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx",
+		.type		= ETHTOOL_A_RINGS_TX,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_sring(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RINGS_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "-G";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_RINGS_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_RINGS_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 81;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 81;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 13/21] netlink: add netlink handler for gchannels (-l)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (11 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 12/21] netlink: add netlink handler for sring (-G) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 14/21] netlink: add netlink handler for schannels (-L) Michal Kubecek
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -l <dev>" subcommand using ETHTOOL_MSG_CHANNELS_GET
netlink message. This retrieves and displays device channel counts,
traditionally provided by ETHTOOL_GCHANNELS ioctl request.

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_CHANNELS_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am        |  1 +
 ethtool.c          |  1 +
 netlink/channels.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++
 netlink/extapi.h   |  2 ++
 netlink/monitor.c  |  8 ++++++
 netlink/netlink.h  |  1 +
 6 files changed, 84 insertions(+)
 create mode 100644 netlink/channels.c

diff --git a/Makefile.am b/Makefile.am
index f7d7b44a438d..b5e32bec68f1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,6 +32,7 @@ ethtool_SOURCES += \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
 		  netlink/features.c netlink/privflags.c netlink/rings.c \
+		  netlink/channels.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index bddde6d9f7c0..eff97f4dfe70 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5365,6 +5365,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-l|--show-channels",
 		.func	= do_gchannels,
+		.nlfunc	= nl_gchannels,
 		.help	= "Query Channels"
 	},
 	{
diff --git a/netlink/channels.c b/netlink/channels.c
new file mode 100644
index 000000000000..ddea17b4d670
--- /dev/null
+++ b/netlink/channels.c
@@ -0,0 +1,71 @@
+/*
+ * channels.c - netlink implementation of channel commands
+ *
+ * Implementation of "ethtool -l <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+
+/* CHANNELS_GET */
+
+int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_CHANNELS_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		putchar('\n');
+	printf("Channel parameters for %s:\n", nlctx->devname);
+	printf("Pre-set maximums:\n");
+	show_u32(tb[ETHTOOL_A_CHANNELS_RX_MAX], "RX:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_TX_MAX], "TX:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_OTHER_MAX], "Other:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_COMBINED_MAX], "Combined:\t");
+	printf("Current hardware settings:\n");
+	show_u32(tb[ETHTOOL_A_CHANNELS_RX_COUNT], "RX:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_TX_COUNT], "TX:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_OTHER_COUNT], "Other:\t\t");
+	show_u32(tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], "Combined:\t");
+
+	return MNL_CB_OK;
+}
+
+int nl_gchannels(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_CHANNELS_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_CHANNELS_GET,
+				      ETHTOOL_A_CHANNELS_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, channels_reply_cb);
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 8a3e72bc75e6..9438dcd3aa0f 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -26,6 +26,7 @@ int nl_gprivflags(struct cmd_context *ctx);
 int nl_sprivflags(struct cmd_context *ctx);
 int nl_gring(struct cmd_context *ctx);
 int nl_sring(struct cmd_context *ctx);
+int nl_gchannels(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -56,6 +57,7 @@ static inline void nl_monitor_usage(void)
 #define nl_sprivflags		NULL
 #define nl_gring		NULL
 #define nl_sring		NULL
+#define nl_gchannels		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index c89e6138dbec..5dada99168b0 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -43,6 +43,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_RINGS_NTF,
 		.cb	= rings_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_CHANNELS_NTF,
+		.cb	= channels_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -126,6 +130,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-g|--show-ring|-G|--set-ring",
 		.cmd		= ETHTOOL_MSG_RINGS_NTF,
 	},
+	{
+		.pattern	= "-l|--show-channels|-L|--set-channels",
+		.cmd		= ETHTOOL_MSG_CHANNELS_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index fe68e23cccb3..511bcb2f2098 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -65,6 +65,7 @@ int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int features_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 /* dump helpers */
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 14/21] netlink: add netlink handler for schannels (-L)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (12 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 13/21] netlink: add netlink handler for gchannels (-l) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 15/21] netlink: add netlink handler for gcoalesce (-c) Michal Kubecek
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -L <dev> ..." subcommand to set network device channel
counts using ETHTOOL_MSG_CHANNELS_SET netlink message. These are
traditionally set using ETHTOOL_SCHANNELS ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c          |  1 +
 netlink/channels.c | 72 +++++++++++++++++++++++++++++++++++++++++++++-
 netlink/extapi.h   |  2 ++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index eff97f4dfe70..cf888e08b5a4 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5371,6 +5371,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-L|--set-channels",
 		.func	= do_schannels,
+		.nlfunc	= nl_schannels,
 		.help	= "Set Channels",
 		.xhelp	= "               [ rx N ]\n"
 			  "               [ tx N ]\n"
diff --git a/netlink/channels.c b/netlink/channels.c
index ddea17b4d670..c6002ceeb121 100644
--- a/netlink/channels.c
+++ b/netlink/channels.c
@@ -1,7 +1,7 @@
 /*
  * channels.c - netlink implementation of channel commands
  *
- * Implementation of "ethtool -l <dev>"
+ * Implementation of "ethtool -l <dev>" and "ethtool -L <dev> ..."
  */
 
 #include <errno.h>
@@ -11,6 +11,7 @@
 #include "../internal.h"
 #include "../common.h"
 #include "netlink.h"
+#include "parser.h"
 
 /* CHANNELS_GET */
 
@@ -69,3 +70,72 @@ int nl_gchannels(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, channels_reply_cb);
 }
+
+/* CHANNELS_SET */
+
+static const struct param_parser schannels_params[] = {
+	{
+		.arg		= "rx",
+		.type		= ETHTOOL_A_CHANNELS_RX_COUNT,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx",
+		.type		= ETHTOOL_A_CHANNELS_TX_COUNT,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "other",
+		.type		= ETHTOOL_A_CHANNELS_OTHER_COUNT,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "combined",
+		.type		= ETHTOOL_A_CHANNELS_COMBINED_COUNT,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_schannels(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_CHANNELS_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "-L";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_CHANNELS_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_CHANNELS_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 1;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 1;
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 9438dcd3aa0f..9cea57ac040a 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -27,6 +27,7 @@ int nl_sprivflags(struct cmd_context *ctx);
 int nl_gring(struct cmd_context *ctx);
 int nl_sring(struct cmd_context *ctx);
 int nl_gchannels(struct cmd_context *ctx);
+int nl_schannels(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -58,6 +59,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gring		NULL
 #define nl_sring		NULL
 #define nl_gchannels		NULL
+#define nl_schannels		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 15/21] netlink: add netlink handler for gcoalesce (-c)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (13 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 14/21] netlink: add netlink handler for schannels (-L) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 16/21] netlink: add netlink handler for scoalesce (-C) Michal Kubecek
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -c <dev>" subcommand using ETHTOOL_MSG_COALESCE_GET
netlink message. This retrieves and displays device coalescing parameters,
traditionally provided by ETHTOOL_GCOALESCE ioctl request.

Unlike the ioctl code, netlink can distinguish between unsupported
parameter (shown as "n/a") and zero value ("0" or "off").

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_COALESCE_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am        |  2 +-
 ethtool.c          |  1 +
 netlink/coalesce.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++
 netlink/extapi.h   |  2 +
 netlink/monitor.c  |  8 ++++
 netlink/netlink.h  |  9 +++++
 6 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 netlink/coalesce.c

diff --git a/Makefile.am b/Makefile.am
index b5e32bec68f1..19cef636286f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,7 +32,7 @@ ethtool_SOURCES += \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
 		  netlink/features.c netlink/privflags.c netlink/rings.c \
-		  netlink/channels.c \
+		  netlink/channels.c netlink/coalesce.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index cf888e08b5a4..97280cb676db 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5167,6 +5167,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-c|--show-coalesce",
 		.func	= do_gcoalesce,
+		.nlfunc	= nl_gcoalesce,
 		.help	= "Show coalesce options"
 	},
 	{
diff --git a/netlink/coalesce.c b/netlink/coalesce.c
new file mode 100644
index 000000000000..f1ad671c3bd4
--- /dev/null
+++ b/netlink/coalesce.c
@@ -0,0 +1,91 @@
+/*
+ * coalesce.c - netlink implementation of coalescing commands
+ *
+ * Implementation of "ethtool -c <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+
+/* COALESCE_GET */
+
+int coalesce_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_COALESCE_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_COALESCE_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		putchar('\n');
+	printf("Coalesce parameters for %s:\n", nlctx->devname);
+	printf("Adaptive RX: %s  TX: %s\n",
+	       u8_to_bool(tb[ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX]),
+	       u8_to_bool(tb[ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX]));
+	show_u32(tb[ETHTOOL_A_COALESCE_STATS_BLOCK_USECS],
+		 "stats-block-usecs: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL],
+		 "sample-interval: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_PKT_RATE_LOW], "pkt-rate-low: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_PKT_RATE_HIGH], "pkt-rate-high: ");
+	putchar('\n');
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS], "rx-usecs: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES], "rx-frames: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_IRQ], "rx-usecs-irq: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ], "rx-frames-irq: ");
+	putchar('\n');
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS], "tx-usecs: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES], "tx-frames: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_IRQ], "tx-usecs-irq: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ], "tx-frames-irq: ");
+	putchar('\n');
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_LOW], "rx-usecs-low: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW], "rx-frame-low: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_LOW], "tx-usecs-low: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW], "tx-frame-low: ");
+	putchar('\n');
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_USECS_HIGH], "rx-usecs-high: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH], "rx-frame-high: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_USECS_HIGH], "tx-usecs-high: ");
+	show_u32(tb[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH], "tx-frame-high: ");
+	putchar('\n');
+
+	return MNL_CB_OK;
+}
+
+int nl_gcoalesce(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_COALESCE_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_COALESCE_GET,
+				      ETHTOOL_A_COALESCE_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, coalesce_reply_cb);
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 9cea57ac040a..f25fc6e4389f 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -28,6 +28,7 @@ int nl_gring(struct cmd_context *ctx);
 int nl_sring(struct cmd_context *ctx);
 int nl_gchannels(struct cmd_context *ctx);
 int nl_schannels(struct cmd_context *ctx);
+int nl_gcoalesce(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -60,6 +61,7 @@ static inline void nl_monitor_usage(void)
 #define nl_sring		NULL
 #define nl_gchannels		NULL
 #define nl_schannels		NULL
+#define nl_gcoalesce		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index 5dada99168b0..ef9cc7a6923a 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -47,6 +47,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_CHANNELS_NTF,
 		.cb	= channels_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_COALESCE_NTF,
+		.cb	= coalesce_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -134,6 +138,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-l|--show-channels|-L|--set-channels",
 		.cmd		= ETHTOOL_MSG_CHANNELS_NTF,
 	},
+	{
+		.pattern	= "-c|--show-coalesce|-C|--coalesce",
+		.cmd		= ETHTOOL_MSG_COALESCE_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 511bcb2f2098..d35048583f5e 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -66,6 +66,7 @@ int features_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int coalesce_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 /* dump helpers */
 
@@ -77,6 +78,14 @@ static inline void show_u32(const struct nlattr *attr, const char *label)
 		printf("%sn/a\n", label);
 }
 
+static inline const char *u8_to_bool(const struct nlattr *attr)
+{
+	if (attr)
+		return mnl_attr_get_u8(attr) ? "on" : "off";
+	else
+		return "n/a";
+}
+
 /* misc */
 
 static inline void copy_devname(char *dst, const char *src)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 16/21] netlink: add netlink handler for scoalesce (-C)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (14 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 15/21] netlink: add netlink handler for gcoalesce (-c) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 17/21] netlink: add netlink handler for gpause (-a) Michal Kubecek
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -C <dev> ..." subcommand to set network device
coalescing parameters using ETHTOOL_MSG_COALESCE_SET netlink message. These
are traditionally set using ETHTOOL_SCOALESCE ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c          |   1 +
 netlink/coalesce.c | 180 ++++++++++++++++++++++++++++++++++++++++++++-
 netlink/extapi.h   |   2 +
 3 files changed, 182 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index 97280cb676db..6a28307004d5 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5173,6 +5173,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-C|--coalesce",
 		.func	= do_scoalesce,
+		.nlfunc	= nl_scoalesce,
 		.help	= "Set coalesce options",
 		.xhelp	= "		[adaptive-rx on|off]\n"
 			  "		[adaptive-tx on|off]\n"
diff --git a/netlink/coalesce.c b/netlink/coalesce.c
index f1ad671c3bd4..65f75cf9a8dd 100644
--- a/netlink/coalesce.c
+++ b/netlink/coalesce.c
@@ -1,7 +1,7 @@
 /*
  * coalesce.c - netlink implementation of coalescing commands
  *
- * Implementation of "ethtool -c <dev>"
+ * Implementation of "ethtool -c <dev>" and "ethtool -C <dev> ..."
  */
 
 #include <errno.h>
@@ -11,6 +11,7 @@
 #include "../internal.h"
 #include "../common.h"
 #include "netlink.h"
+#include "parser.h"
 
 /* COALESCE_GET */
 
@@ -89,3 +90,180 @@ int nl_gcoalesce(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, coalesce_reply_cb);
 }
+
+/* COALESCE_SET */
+
+static const struct param_parser scoalesce_params[] = {
+	{
+		.arg		= "adaptive-rx",
+		.type		= ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "adaptive-tx",
+		.type		= ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "sample-interval",
+		.type		= ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "stats-block-usecs",
+		.type		= ETHTOOL_A_COALESCE_STATS_BLOCK_USECS,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "pkt-rate-low",
+		.type		= ETHTOOL_A_COALESCE_PKT_RATE_LOW,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "pkt-rate-high",
+		.type		= ETHTOOL_A_COALESCE_PKT_RATE_HIGH,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-usecs",
+		.type		= ETHTOOL_A_COALESCE_RX_USECS,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-frames",
+		.type		= ETHTOOL_A_COALESCE_RX_MAX_FRAMES,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-usecs-irq",
+		.type		= ETHTOOL_A_COALESCE_RX_USECS_IRQ,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-frames-irq",
+		.type		= ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-usecs",
+		.type		= ETHTOOL_A_COALESCE_TX_USECS,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-frames",
+		.type		= ETHTOOL_A_COALESCE_TX_MAX_FRAMES,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-usecs-irq",
+		.type		= ETHTOOL_A_COALESCE_TX_USECS_IRQ,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-frames-irq",
+		.type		= ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-usecs-low",
+		.type		= ETHTOOL_A_COALESCE_RX_USECS_LOW,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-frames-low",
+		.type		= ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-usecs-low",
+		.type		= ETHTOOL_A_COALESCE_TX_USECS_LOW,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-frames-low",
+		.type		= ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-usecs-high",
+		.type		= ETHTOOL_A_COALESCE_RX_USECS_HIGH,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx-frames-high",
+		.type		= ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-usecs-high",
+		.type		= ETHTOOL_A_COALESCE_TX_USECS_HIGH,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-frames-high",
+		.type		= ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_scoalesce(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_COALESCE_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "-C";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_COALESCE_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_COALESCE_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, scoalesce_params, NULL, PARSER_GROUP_NONE);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 1;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 1;
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index f25fc6e4389f..d35029576d5c 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -29,6 +29,7 @@ int nl_sring(struct cmd_context *ctx);
 int nl_gchannels(struct cmd_context *ctx);
 int nl_schannels(struct cmd_context *ctx);
 int nl_gcoalesce(struct cmd_context *ctx);
+int nl_scoalesce(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -62,6 +63,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gchannels		NULL
 #define nl_schannels		NULL
 #define nl_gcoalesce		NULL
+#define nl_scoalesce		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 17/21] netlink: add netlink handler for gpause (-a)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (15 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 16/21] netlink: add netlink handler for scoalesce (-C) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 18/21] netlink: add netlink handler for spause (-A) Michal Kubecek
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -a <dev>" subcommand using ETHTOOL_MSG_PAUSE_GET netlink
message. This retrieves and diaplays device pause parameters, traditionally
provided by ETHTOOL_GPAUSEPARAM ioctl request.

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_PAUSE_NTF notifications. When in monitor mode,
negotiated status is not displayed.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am       |   2 +-
 ethtool.c         |   1 +
 netlink/extapi.h  |   2 +
 netlink/monitor.c |   8 +++
 netlink/netlink.h |   6 ++
 netlink/pause.c   | 158 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 netlink/pause.c

diff --git a/Makefile.am b/Makefile.am
index 19cef636286f..5d6c4e9571d0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,7 +32,7 @@ ethtool_SOURCES += \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
 		  netlink/features.c netlink/privflags.c netlink/rings.c \
-		  netlink/channels.c netlink/coalesce.c \
+		  netlink/channels.c netlink/coalesce.c netlink/pause.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index 6a28307004d5..b5b7ddab813d 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5154,6 +5154,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-a|--show-pause",
 		.func	= do_gpause,
+		.nlfunc	= nl_gpause,
 		.help	= "Show pause options"
 	},
 	{
diff --git a/netlink/extapi.h b/netlink/extapi.h
index d35029576d5c..00ad74010d2c 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -30,6 +30,7 @@ int nl_gchannels(struct cmd_context *ctx);
 int nl_schannels(struct cmd_context *ctx);
 int nl_gcoalesce(struct cmd_context *ctx);
 int nl_scoalesce(struct cmd_context *ctx);
+int nl_gpause(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -64,6 +65,7 @@ static inline void nl_monitor_usage(void)
 #define nl_schannels		NULL
 #define nl_gcoalesce		NULL
 #define nl_scoalesce		NULL
+#define nl_gpause		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index ef9cc7a6923a..f02b462ff102 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -51,6 +51,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_COALESCE_NTF,
 		.cb	= coalesce_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_PAUSE_NTF,
+		.cb	= pause_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -142,6 +146,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-c|--show-coalesce|-C|--coalesce",
 		.cmd		= ETHTOOL_MSG_COALESCE_NTF,
 	},
+	{
+		.pattern	= "-a|--show-pause|-A|--pause",
+		.cmd		= ETHTOOL_MSG_PAUSE_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index d35048583f5e..7cbb23733f88 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -67,6 +67,7 @@ int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int coalesce_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 /* dump helpers */
 
@@ -86,6 +87,11 @@ static inline const char *u8_to_bool(const struct nlattr *attr)
 		return "n/a";
 }
 
+static inline void show_bool(const struct nlattr *attr, const char *label)
+{
+	printf("%s%s\n", label, u8_to_bool(attr));
+}
+
 /* misc */
 
 static inline void copy_devname(char *dst, const char *src)
diff --git a/netlink/pause.c b/netlink/pause.c
new file mode 100644
index 000000000000..c9fdaeeaa0bc
--- /dev/null
+++ b/netlink/pause.c
@@ -0,0 +1,158 @@
+/*
+ * pause.c - netlink implementation of pause commands
+ *
+ * Implementation of "ethtool -a <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "bitset.h"
+
+/* PAUSE_GET */
+
+struct pause_autoneg_status {
+	bool	pause;
+	bool	asym_pause;
+};
+
+static void pause_autoneg_walker(unsigned int idx, const char *name, bool val,
+				 void *data)
+{
+	struct pause_autoneg_status *status = data;
+
+	if (idx == ETHTOOL_LINK_MODE_Pause_BIT)
+		status->pause = val;
+	if (idx == ETHTOOL_LINK_MODE_Asym_Pause_BIT)
+		status->asym_pause = val;
+}
+
+static int pause_autoneg_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct pause_autoneg_status ours = {};
+	struct pause_autoneg_status peer = {};
+	struct nl_context *nlctx = data;
+	bool rx_status = false;
+	bool tx_status = false;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+
+	if (!tb[ETHTOOL_A_LINKMODES_OURS] || !tb[ETHTOOL_A_LINKMODES_PEER])
+		return MNL_CB_OK;
+	ret = walk_bitset(tb[ETHTOOL_A_LINKMODES_OURS], NULL,
+			  pause_autoneg_walker, &ours);
+	if (ret < 0)
+		return err_ret;
+	ret = walk_bitset(tb[ETHTOOL_A_LINKMODES_PEER], NULL,
+			  pause_autoneg_walker, &peer);
+	if (ret < 0)
+		return err_ret;
+
+	if (ours.pause && peer.pause) {
+		rx_status = true;
+		tx_status = true;
+	} else if (ours.asym_pause && peer.asym_pause) {
+		if (ours.pause)
+			rx_status = true;
+		else if (peer.pause)
+			tx_status = true;
+	}
+	printf("RX negotiated: %s\nTX negotiated: %s\n",
+	       rx_status ? "on" : "off", tx_status ? "on" : "off");
+
+	return MNL_CB_OK;
+}
+
+static int show_pause_autoneg_status(struct nl_context *nlctx)
+{
+	const char *saved_devname;
+	int ret;
+
+	saved_devname = nlctx->ctx->devname;
+	nlctx->ctx->devname = nlctx->devname;
+	ret = netlink_init_ethnl2_socket(nlctx);
+	if (ret < 0)
+		goto out;
+
+	ret = nlsock_prep_get_request(nlctx->ethnl2_socket,
+				      ETHTOOL_MSG_LINKMODES_GET,
+				      ETHTOOL_A_LINKMODES_HEADER,
+				      ETHTOOL_FLAG_COMPACT_BITSETS);
+	if (ret < 0)
+		goto out;
+	ret = nlsock_send_get_request(nlctx->ethnl2_socket, pause_autoneg_cb);
+
+out:
+	nlctx->ctx->devname = saved_devname;
+	return ret;
+}
+
+int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_PAUSE_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		putchar('\n');
+	printf("Pause parameters for %s:\n", nlctx->devname);
+	show_bool(tb[ETHTOOL_A_PAUSE_AUTONEG], "Autonegotiate:\t");
+	show_bool(tb[ETHTOOL_A_PAUSE_RX], "RX:\t\t");
+	show_bool(tb[ETHTOOL_A_PAUSE_TX], "TX:\t\t");
+	if (!nlctx->is_monitor && tb[ETHTOOL_A_PAUSE_AUTONEG] &&
+	    mnl_attr_get_u8(tb[ETHTOOL_A_PAUSE_AUTONEG])) {
+		ret = show_pause_autoneg_status(nlctx);
+		if (ret < 0)
+			return err_ret;
+	}
+	if (!silent)
+		putchar('\n');
+
+	return MNL_CB_OK;
+}
+
+int nl_gpause(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_PAUSE_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PAUSE_GET,
+				      ETHTOOL_A_PAUSE_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, pause_reply_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 18/21] netlink: add netlink handler for spause (-A)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (16 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 17/21] netlink: add netlink handler for gpause (-a) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 19/21] netlink: add netlink handler for geee (--show-eee) Michal Kubecek
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -A <dev> ..." subcommand to set network device pause
parameters using ETHTOOL_MSG_PAUSE_SET netlink message. These are
traditionally set using ETHTOOL_SPAUSEPARAM ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c        |  1 +
 netlink/extapi.h |  2 ++
 netlink/pause.c  | 66 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index b5b7ddab813d..2005e9523f93 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5160,6 +5160,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-A|--pause",
 		.func	= do_spause,
+		.nlfunc	= nl_spause,
 		.help	= "Set pause options",
 		.xhelp	= "		[ autoneg on|off ]\n"
 			  "		[ rx on|off ]\n"
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 00ad74010d2c..b86595763c9d 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -31,6 +31,7 @@ int nl_schannels(struct cmd_context *ctx);
 int nl_gcoalesce(struct cmd_context *ctx);
 int nl_scoalesce(struct cmd_context *ctx);
 int nl_gpause(struct cmd_context *ctx);
+int nl_spause(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -66,6 +67,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gcoalesce		NULL
 #define nl_scoalesce		NULL
 #define nl_gpause		NULL
+#define nl_spause		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/pause.c b/netlink/pause.c
index c9fdaeeaa0bc..48215d29aa34 100644
--- a/netlink/pause.c
+++ b/netlink/pause.c
@@ -1,7 +1,7 @@
 /*
  * pause.c - netlink implementation of pause commands
  *
- * Implementation of "ethtool -a <dev>"
+ * Implementation of "ethtool -a <dev>" and "ethtool -A <dev> ..."
  */
 
 #include <errno.h>
@@ -12,6 +12,7 @@
 #include "../common.h"
 #include "netlink.h"
 #include "bitset.h"
+#include "parser.h"
 
 /* PAUSE_GET */
 
@@ -156,3 +157,66 @@ int nl_gpause(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, pause_reply_cb);
 }
+
+/* PAUSE_SET */
+
+static const struct param_parser spause_params[] = {
+	{
+		.arg		= "autoneg",
+		.type		= ETHTOOL_A_PAUSE_AUTONEG,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "rx",
+		.type		= ETHTOOL_A_PAUSE_RX,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx",
+		.type		= ETHTOOL_A_PAUSE_TX,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_spause(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_PAUSE_SET, false))
+		return -EOPNOTSUPP;
+
+	nlctx->cmd = "-A";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_PAUSE_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_PAUSE_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, spause_params, NULL, PARSER_GROUP_NONE);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 76;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 76;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 19/21] netlink: add netlink handler for geee (--show-eee)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (17 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 18/21] netlink: add netlink handler for spause (-A) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 20/21] netlink: add netlink handler for seee (--set-eee) Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 21/21] netlink: add netlink handler for tsinfo (-T) Michal Kubecek
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool --show-eee <dev>" subcommand using ETHTOOL_MSG_EEE_GET
netlink message. This retrieves and displays device coalescing parameters,
traditionally provided by ETHTOOL_GEEE ioctl request.

Also register the callback with monitor code so that the monitor can
display ETHTOOL_MSG_EEE_NTF notifications.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am        |   1 +
 ethtool.c          |   1 +
 netlink/eee.c      | 108 +++++++++++++++++++++++++++++++++++++++++++++
 netlink/extapi.h   |   2 +
 netlink/monitor.c  |   8 ++++
 netlink/netlink.h  |  15 +++++++
 netlink/settings.c |  17 ++-----
 7 files changed, 138 insertions(+), 14 deletions(-)
 create mode 100644 netlink/eee.c

diff --git a/Makefile.am b/Makefile.am
index 5d6c4e9571d0..95babcdc8eae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,7 @@ ethtool_SOURCES += \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
 		  netlink/features.c netlink/privflags.c netlink/rings.c \
 		  netlink/channels.c netlink/coalesce.c netlink/pause.c \
+		  netlink/eee.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index 2005e9523f93..f4aaab58aa5b 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5407,6 +5407,7 @@ static const struct option args[] = {
 	{
 		.opts	= "--show-eee",
 		.func	= do_geee,
+		.nlfunc	= nl_geee,
 		.help	= "Show EEE settings",
 	},
 	{
diff --git a/netlink/eee.c b/netlink/eee.c
new file mode 100644
index 000000000000..c9a9fcfba1f5
--- /dev/null
+++ b/netlink/eee.c
@@ -0,0 +1,108 @@
+/*
+ * eee.c - netlink implementation of eee commands
+ *
+ * Implementation of "ethtool --show-eee <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "bitset.h"
+
+/* EEE_GET */
+
+int eee_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	bool enabled, active, tx_lpi_enabled;
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump || nlctx->is_monitor;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_EEE_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (!tb[ETHTOOL_A_EEE_MODES_OURS] ||
+	    !tb[ETHTOOL_A_EEE_ACTIVE] || !tb[ETHTOOL_A_EEE_ENABLED] ||
+	    !tb[ETHTOOL_A_EEE_TX_LPI_ENABLED] ||
+	    !tb[ETHTOOL_A_EEE_TX_LPI_TIMER]) {
+		fprintf(stderr, "Malformed response from kernel\n");
+		return err_ret;
+	}
+	active = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_ACTIVE]);
+	enabled = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_ENABLED]);
+	tx_lpi_enabled = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_TX_LPI_ENABLED]);
+
+	if (silent)
+		putchar('\n');
+	printf("EEE settings for %s:\n", nlctx->devname);
+	printf("\tEEE status: ");
+	if (bitset_is_empty(tb[ETHTOOL_A_EEE_MODES_OURS], true, &ret)) {
+		printf("not supported\n");
+		return MNL_CB_OK;
+	}
+	if (!enabled)
+		printf("disabled\n");
+	else
+		printf("enabled - %s\n", active ? "active" : "inactive");
+	printf("\tTx LPI: ");
+	if (tx_lpi_enabled)
+		printf("%u (us)\n",
+		       mnl_attr_get_u32(tb[ETHTOOL_A_EEE_TX_LPI_TIMER]));
+	else
+		printf("disabled\n");
+
+	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_OURS], true,
+			      LM_CLASS_REAL,
+			      "Supported EEE link modes:  ", NULL, "\n",
+			      "Not reported");
+	if (ret < 0)
+		return err_ret;
+	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_OURS], false,
+			      LM_CLASS_REAL,
+			      "Advertised EEE link modes:  ", NULL, "\n",
+			      "Not reported");
+	if (ret < 0)
+		return err_ret;
+	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_PEER], false,
+			      LM_CLASS_REAL,
+			      "Link partner advertised EEE link modes:  ", NULL,
+			      "\n", "Not reported");
+	if (ret < 0)
+		return err_ret;
+
+	return MNL_CB_OK;
+}
+
+int nl_geee(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_EEE_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_EEE_GET,
+				      ETHTOOL_A_EEE_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, eee_reply_cb);
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index b86595763c9d..f16dd5ed25b4 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -32,6 +32,7 @@ int nl_gcoalesce(struct cmd_context *ctx);
 int nl_scoalesce(struct cmd_context *ctx);
 int nl_gpause(struct cmd_context *ctx);
 int nl_spause(struct cmd_context *ctx);
+int nl_geee(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -68,6 +69,7 @@ static inline void nl_monitor_usage(void)
 #define nl_scoalesce		NULL
 #define nl_gpause		NULL
 #define nl_spause		NULL
+#define nl_geee			NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/monitor.c b/netlink/monitor.c
index f02b462ff102..18d4efd07bd2 100644
--- a/netlink/monitor.c
+++ b/netlink/monitor.c
@@ -55,6 +55,10 @@ static struct {
 		.cmd	= ETHTOOL_MSG_PAUSE_NTF,
 		.cb	= pause_reply_cb,
 	},
+	{
+		.cmd	= ETHTOOL_MSG_EEE_NTF,
+		.cb	= eee_reply_cb,
+	},
 };
 
 static void clear_filter(struct nl_context *nlctx)
@@ -150,6 +154,10 @@ static struct monitor_option monitor_opts[] = {
 		.pattern	= "-a|--show-pause|-A|--pause",
 		.cmd		= ETHTOOL_MSG_PAUSE_NTF,
 	},
+	{
+		.pattern	= "--show-eee|--set-eee",
+		.cmd		= ETHTOOL_MSG_EEE_NTF,
+	},
 };
 
 static bool pattern_match(const char *s, const char *pattern)
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 7cbb23733f88..fe53fd066c95 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -16,6 +16,15 @@
 #define WILDCARD_DEVNAME "*"
 #define CMDMASK_WORDS DIV_ROUND_UP(__ETHTOOL_MSG_KERNEL_CNT, 32)
 
+enum link_mode_class {
+	LM_CLASS_UNKNOWN,
+	LM_CLASS_REAL,
+	LM_CLASS_AUTONEG,
+	LM_CLASS_PORT,
+	LM_CLASS_PAUSE,
+	LM_CLASS_FEC,
+};
+
 struct nl_context {
 	struct cmd_context	*ctx;
 	void			*cmd_private;
@@ -68,9 +77,15 @@ int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int coalesce_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data);
+int eee_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 
 /* dump helpers */
 
+int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
+		    bool mask, unsigned int class, const char *before,
+		    const char *between, const char *after,
+		    const char *if_none);
+
 static inline void show_u32(const struct nlattr *attr, const char *label)
 {
 	if (attr)
diff --git a/netlink/settings.c b/netlink/settings.c
index 8be5a22ddd2e..aa627cd300ed 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -17,15 +17,6 @@
 
 /* GET_SETTINGS */
 
-enum link_mode_class {
-	LM_CLASS_UNKNOWN,
-	LM_CLASS_REAL,
-	LM_CLASS_AUTONEG,
-	LM_CLASS_PORT,
-	LM_CLASS_PAUSE,
-	LM_CLASS_FEC,
-};
-
 struct link_mode_info {
 	enum link_mode_class	class;
 	u32			speed;
@@ -263,11 +254,9 @@ static void print_banner(struct nl_context *nlctx)
 	nlctx->no_banner = true;
 }
 
-static int dump_link_modes(struct nl_context *nlctx,
-			   const struct nlattr *bitset, bool mask,
-			   unsigned int class, const char *before,
-			   const char *between, const char *after,
-			   const char *if_none)
+int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
+		    bool mask, unsigned int class, const char *before,
+		    const char *between, const char *after, const char *if_none)
 {
 	const struct nlattr *bitset_tb[ETHTOOL_A_BITSET_MAX + 1] = {};
 	DECLARE_ATTR_TB_INFO(bitset_tb);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 20/21] netlink: add netlink handler for seee (--set-eee)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (18 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 19/21] netlink: add netlink handler for geee (--show-eee) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  2020-05-28 23:22 ` [PATCH ethtool 21/21] netlink: add netlink handler for tsinfo (-T) Michal Kubecek
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool --set-eee <dev> ..." subcommand to set network device
EEE settings using ETHTOOL_MSG_EEE_SET netlink message. These are
traditionally set using ETHTOOL_SEEE ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 ethtool.c        |  1 +
 netlink/eee.c    | 83 +++++++++++++++++++++++++++++++++++++++++++++++-
 netlink/extapi.h |  2 ++
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/ethtool.c b/ethtool.c
index f4aaab58aa5b..3b81345d7120 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5413,6 +5413,7 @@ static const struct option args[] = {
 	{
 		.opts	= "--set-eee",
 		.func	= do_seee,
+		.nlfunc	= nl_seee,
 		.help	= "Set EEE settings",
 		.xhelp	= "		[ eee on|off ]\n"
 			  "		[ advertise %x ]\n"
diff --git a/netlink/eee.c b/netlink/eee.c
index c9a9fcfba1f5..d3135b2094a4 100644
--- a/netlink/eee.c
+++ b/netlink/eee.c
@@ -1,7 +1,8 @@
 /*
  * eee.c - netlink implementation of eee commands
  *
- * Implementation of "ethtool --show-eee <dev>"
+ * Implementation of "ethtool --show-eee <dev>" and
+ * "ethtool --set-eee <dev> ..."
  */
 
 #include <errno.h>
@@ -12,6 +13,7 @@
 #include "../common.h"
 #include "netlink.h"
 #include "bitset.h"
+#include "parser.h"
 
 /* EEE_GET */
 
@@ -106,3 +108,82 @@ int nl_geee(struct cmd_context *ctx)
 		return ret;
 	return nlsock_send_get_request(nlsk, eee_reply_cb);
 }
+
+/* EEE_SET */
+
+static const struct bitset_parser_data advertise_parser_data = {
+	.no_mask	= false,
+	.force_hex	= true,
+};
+
+static const struct param_parser seee_params[] = {
+	{
+		.arg		= "advertise",
+		.type		= ETHTOOL_A_EEE_MODES_OURS,
+		.handler	= nl_parse_bitset,
+		.handler_data	= &advertise_parser_data,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-lpi",
+		.type		= ETHTOOL_A_EEE_TX_LPI_ENABLED,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "tx-timer",
+		.type		= ETHTOOL_A_EEE_TX_LPI_TIMER,
+		.handler	= nl_parse_direct_u32,
+		.min_argc	= 1,
+	},
+	{
+		.arg		= "eee",
+		.type		= ETHTOOL_A_EEE_ENABLED,
+		.handler	= nl_parse_u8bool,
+		.min_argc	= 1,
+	},
+	{}
+};
+
+int nl_seee(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_msg_buff *msgbuff;
+	struct nl_socket *nlsk;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_EEE_SET, false))
+		return -EOPNOTSUPP;
+	if (!ctx->argc) {
+		fprintf(stderr, "ethtool (--set-eee): parameters missing\n");
+		return 1;
+	}
+
+	nlctx->cmd = "--set-eee";
+	nlctx->argp = ctx->argp;
+	nlctx->argc = ctx->argc;
+	nlctx->devname = ctx->devname;
+	nlsk = nlctx->ethnl_socket;
+	msgbuff = &nlsk->msgbuff;
+
+	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_EEE_SET,
+		       NLM_F_REQUEST | NLM_F_ACK);
+	if (ret < 0)
+		return 2;
+	if (ethnla_fill_header(msgbuff, ETHTOOL_A_EEE_HEADER,
+			       ctx->devname, 0))
+		return -EMSGSIZE;
+
+	ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE);
+	if (ret < 0)
+		return 1;
+
+	ret = nlsock_sendmsg(nlsk, NULL);
+	if (ret < 0)
+		return 76;
+	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
+	if (ret == 0)
+		return 0;
+	else
+		return nlctx->exit_code ?: 76;
+}
diff --git a/netlink/extapi.h b/netlink/extapi.h
index f16dd5ed25b4..387787f61015 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -33,6 +33,7 @@ int nl_scoalesce(struct cmd_context *ctx);
 int nl_gpause(struct cmd_context *ctx);
 int nl_spause(struct cmd_context *ctx);
 int nl_geee(struct cmd_context *ctx);
+int nl_seee(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -70,6 +71,7 @@ static inline void nl_monitor_usage(void)
 #define nl_gpause		NULL
 #define nl_spause		NULL
 #define nl_geee			NULL
+#define nl_seee			NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH ethtool 21/21] netlink: add netlink handler for tsinfo (-T)
  2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
                   ` (19 preceding siblings ...)
  2020-05-28 23:22 ` [PATCH ethtool 20/21] netlink: add netlink handler for seee (--set-eee) Michal Kubecek
@ 2020-05-28 23:22 ` Michal Kubecek
  20 siblings, 0 replies; 25+ messages in thread
From: Michal Kubecek @ 2020-05-28 23:22 UTC (permalink / raw)
  To: John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Implement "ethtool -T <dev>" subcommand using ETHTOOL_MSG_TSINFO_GET
netlink message. This retrieves and displays device timestamping
information, traditionally provided by ETHTOOL_GET_TS_INFO ioctl request.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am      |   2 +-
 ethtool.c        |   1 +
 netlink/extapi.h |   2 +
 netlink/tsinfo.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 netlink/tsinfo.c

diff --git a/Makefile.am b/Makefile.am
index 95babcdc8eae..63c3fb3ebf90 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,7 +33,7 @@ ethtool_SOURCES += \
 		  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
 		  netlink/features.c netlink/privflags.c netlink/rings.c \
 		  netlink/channels.c netlink/coalesce.c netlink/pause.c \
-		  netlink/eee.c \
+		  netlink/eee.c netlink/tsinfo.c \
 		  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
 		  netlink/desc-rtnl.c \
 		  uapi/linux/ethtool_netlink.h \
diff --git a/ethtool.c b/ethtool.c
index 3b81345d7120..3646718d5c2a 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5324,6 +5324,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-T|--show-time-stamping",
 		.func	= do_tsinfo,
+		.nlfunc	= nl_tsinfo,
 		.help	= "Show time stamping capabilities"
 	},
 	{
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 387787f61015..1b39ed999f3d 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -34,6 +34,7 @@ int nl_gpause(struct cmd_context *ctx);
 int nl_spause(struct cmd_context *ctx);
 int nl_geee(struct cmd_context *ctx);
 int nl_seee(struct cmd_context *ctx);
+int nl_tsinfo(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -72,6 +73,7 @@ static inline void nl_monitor_usage(void)
 #define nl_spause		NULL
 #define nl_geee			NULL
 #define nl_seee			NULL
+#define nl_tsinfo		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/tsinfo.c b/netlink/tsinfo.c
new file mode 100644
index 000000000000..03ce91cd4314
--- /dev/null
+++ b/netlink/tsinfo.c
@@ -0,0 +1,124 @@
+/*
+ * tsinfo.c - netlink implementation of timestamping commands
+ *
+ * Implementation of "ethtool -T <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "bitset.h"
+
+/* TSINFO_GET */
+
+static void tsinfo_dump_cb(unsigned int idx, const char *name, bool val,
+			   void *data)
+{
+	if (!val)
+		return;
+
+	if (name)
+		printf("\t%s\n", name);
+	else
+		printf("\tbit%u\n", idx);
+}
+
+static int tsinfo_dump_list(struct nl_context *nlctx, const struct nlattr *attr,
+			    const char *label, const char *if_empty,
+			    unsigned int stringset_id)
+{
+	const struct stringset *strings = NULL;
+	int ret;
+
+	printf("%s:", label);
+	ret = 0;
+	if (!attr || bitset_is_empty(attr, false, &ret)) {
+		printf("%s\n", if_empty);
+		return ret;
+	}
+	putchar('\n');
+	if (ret < 0)
+		return ret;
+
+	if (bitset_is_compact(attr)) {
+		ret = netlink_init_ethnl2_socket(nlctx);
+		if (ret < 0)
+			return ret;
+		strings = global_stringset(stringset_id, nlctx->ethnl2_socket);
+	}
+	return walk_bitset(attr, strings, tsinfo_dump_cb, NULL);
+}
+
+int tsinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[ETHTOOL_A_TSINFO_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	bool silent;
+	int err_ret;
+	int ret;
+
+	silent = nlctx->is_dump;
+	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
+	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+	if (ret < 0)
+		return err_ret;
+	nlctx->devname = get_dev_name(tb[ETHTOOL_A_TSINFO_HEADER]);
+	if (!dev_ok(nlctx))
+		return err_ret;
+
+	if (silent)
+		putchar('\n');
+	printf("Time stamping parameters for %s:\n", nlctx->devname);
+
+	ret = tsinfo_dump_list(nlctx, tb[ETHTOOL_A_TSINFO_TIMESTAMPING],
+			       "Capabilities", "", ETH_SS_SOF_TIMESTAMPING);
+	if (ret < 0)
+		return err_ret;
+
+	printf("PTP Hardware Clock: ");
+	if (tb[ETHTOOL_A_TSINFO_PHC_INDEX])
+		printf("%d\n",
+		       mnl_attr_get_u32(tb[ETHTOOL_A_TSINFO_PHC_INDEX]));
+	else
+		printf("none\n");
+
+	ret = tsinfo_dump_list(nlctx, tb[ETHTOOL_A_TSINFO_TX_TYPES],
+			       "Hardware Transmit Timestamp Modes", " none",
+			       ETH_SS_TS_TX_TYPES);
+	if (ret < 0)
+		return err_ret;
+
+	ret = tsinfo_dump_list(nlctx, tb[ETHTOOL_A_TSINFO_RX_FILTERS],
+			       "Hardware Receive Filter Modes", " none",
+			       ETH_SS_TS_RX_FILTERS);
+	if (ret < 0)
+		return err_ret;
+
+	return MNL_CB_OK;
+}
+
+int nl_tsinfo(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	struct nl_socket *nlsk = nlctx->ethnl_socket;
+	int ret;
+
+	if (netlink_cmd_check(ctx, ETHTOOL_MSG_TSINFO_GET, true))
+		return -EOPNOTSUPP;
+	if (ctx->argc > 0) {
+		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
+			*ctx->argp);
+		return 1;
+	}
+
+	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_TSINFO_GET,
+				      ETHTOOL_A_TSINFO_HEADER, 0);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlsk, tsinfo_reply_cb);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH ethtool 02/21] netlink: fix nest type grouping in parser
  2020-05-28 23:21 ` [PATCH ethtool 02/21] netlink: fix nest type grouping in parser Michal Kubecek
@ 2020-05-29 14:28   ` Andrew Lunn
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Lunn @ 2020-05-29 14:28 UTC (permalink / raw)
  To: Michal Kubecek; +Cc: John Linville, netdev, Oleksij Rempel

On Fri, May 29, 2020 at 01:21:17AM +0200, Michal Kubecek wrote:
> Even if we are only interested in one nested attribute when using
> PARSER_GROUP_NEST group type, the temporary buffer must contain proper
> netlink header and have pointer to it and payload set up correctly for
> libmnl composition functions to be able to track current message size.
> 
> Fixes: 9ee9d9517542 ("netlink: add basic command line parsing helpers")
> Reported-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>

Tested-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper
  2020-05-28 23:21 ` [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper Michal Kubecek
@ 2020-05-29 14:29   ` Andrew Lunn
  0 siblings, 0 replies; 25+ messages in thread
From: Andrew Lunn @ 2020-05-29 14:29 UTC (permalink / raw)
  To: Michal Kubecek; +Cc: John Linville, netdev, Oleksij Rempel

On Fri, May 29, 2020 at 01:21:22AM +0200, Michal Kubecek wrote:
> As msgbuff_append() only copies protocol payload, i.e. part of the buffer
> without netlink and genetlink header, and mnl_nlmsg_get_payload_len() only
> subtracts netlink header length, we need to subtract genetlink header
> length manually to get correct length of appended data block.
> 
> Fixes: 5050607946b6 ("netlink: message buffer and composition helpers")
> Reported-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>

Tested-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH ethtool 01/21] netlink: fix build warnings
  2020-05-28 23:21 ` [PATCH ethtool 01/21] netlink: fix build warnings Michal Kubecek
@ 2020-06-06 18:47   ` Heiko Thiery
  0 siblings, 0 replies; 25+ messages in thread
From: Heiko Thiery @ 2020-06-06 18:47 UTC (permalink / raw)
  To: Michal Kubecek, John Linville, netdev; +Cc: Andrew Lunn, Oleksij Rempel

Hi Michal,

On 29.05.20 01:21, Michal Kubecek wrote:
> Depending on compiler version and options, some of these warnings may
> result in build failure.
> 
> - gcc 4.8 wants __KERNEL_DIV_ROUND_UP defined before including ethtool.h
> - avoid pointer arithmetic on void *
> 
> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>

Tested-by: Heiko Thiery <heiko.thiery@gmail.com>


-- 
Heiko

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-06-06 18:47 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-28 23:21 [PATCH ethtool 00/21] netlink interface update for 5.7 release Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 01/21] netlink: fix build warnings Michal Kubecek
2020-06-06 18:47   ` Heiko Thiery
2020-05-28 23:21 ` [PATCH ethtool 02/21] netlink: fix nest type grouping in parser Michal Kubecek
2020-05-29 14:28   ` Andrew Lunn
2020-05-28 23:21 ` [PATCH ethtool 03/21] netlink: fix msgbuff_append() helper Michal Kubecek
2020-05-29 14:29   ` Andrew Lunn
2020-05-28 23:21 ` [PATCH ethtool 04/21] update UAPI header copies Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 05/21] netlink: add more ethtool netlink message format descriptions Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 06/21] selftest: omit test-features if netlink is enabled Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 07/21] netlink: add netlink handler for gfeatures (-k) Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 08/21] netlink: add netlink handler for sfeatures (-K) Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 09/21] netlink: add netlink handler for gprivflags (--show-priv-flags) Michal Kubecek
2020-05-28 23:21 ` [PATCH ethtool 10/21] netlink: add netlink handler for sprivflags (--set-priv-flags) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 11/21] netlink: add netlink handler for gring (-g) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 12/21] netlink: add netlink handler for sring (-G) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 13/21] netlink: add netlink handler for gchannels (-l) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 14/21] netlink: add netlink handler for schannels (-L) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 15/21] netlink: add netlink handler for gcoalesce (-c) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 16/21] netlink: add netlink handler for scoalesce (-C) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 17/21] netlink: add netlink handler for gpause (-a) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 18/21] netlink: add netlink handler for spause (-A) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 19/21] netlink: add netlink handler for geee (--show-eee) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 20/21] netlink: add netlink handler for seee (--set-eee) Michal Kubecek
2020-05-28 23:22 ` [PATCH ethtool 21/21] netlink: add netlink handler for tsinfo (-T) Michal Kubecek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.