diff mbox series

[RFC,ethtool,2/2] netlink: Set 'ETHTOOL_FLAG_LEGACY' for compatibility with legacy ioctl interface

Message ID 20201027145147.227053-3-idosch@idosch.org (mailing list archive)
State RFC
Delegated to: Michal Kubecek
Headers show
Series Improve compatibility between netlink and ioctl interfaces | expand

Commit Message

Ido Schimmel Oct. 27, 2020, 2:51 p.m. UTC
From: Ido Schimmel <idosch@nvidia.com>

Set the above mentioned flag in the ethtool netlink request header of
the various commands mapped to 'ethtool set' (e.g.,
'ETHTOOL_MSG_LINKMODES_SET').

The purpose of the flag is to indicate to the kernel to be compatible
with legacy ioctl interface. The current use case is to ensure that the
kernel will advertise all the supported link modes when autoneg is
enabled, but without specifying other parameters.

To prevent the kernel from complaining about unknown flags, the flag is
only set in the request header in case the kernel supports it. This is
achieved by using the recently introduced per-operation policy dump
infrastructure.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 netlink/netlink.c | 13 +++++++++++++
 netlink/netlink.h |  2 ++
 netlink/parser.c  |  5 ++++-
 3 files changed, 19 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/netlink/netlink.c b/netlink/netlink.c
index f655f6ea25b7..11c5a639f381 100644
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -289,6 +289,19 @@  u32 get_stats_flag(struct nl_context *nlctx, unsigned int nlcmd,
 	return nlctx->ops_info[nlcmd].hdr_flags & ETHTOOL_FLAG_STATS;
 }
 
+u32 get_legacy_flag(struct nl_context *nlctx, unsigned int nlcmd,
+		    unsigned int hdrattr)
+{
+	if (nlcmd > ETHTOOL_MSG_USER_MAX ||
+	    !(nlctx->ops_info[nlcmd].op_flags & GENL_CMD_CAP_HASPOL))
+		return 0;
+
+	if (read_flags_policy(nlctx, nlctx->ethnl_socket, nlcmd, hdrattr) < 0)
+		return 0;
+
+	return nlctx->ops_info[nlcmd].hdr_flags & ETHTOOL_FLAG_LEGACY;
+}
+
 /* initialization */
 
 static int genl_read_ops(struct nl_context *nlctx,
diff --git a/netlink/netlink.h b/netlink/netlink.h
index c02558540218..97a1e72ff930 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -74,6 +74,8 @@  const char *get_dev_name(const struct nlattr *nest);
 int get_dev_info(const struct nlattr *nest, int *ifindex, char *ifname);
 u32 get_stats_flag(struct nl_context *nlctx, unsigned int nlcmd,
 		   unsigned int hdrattr);
+u32 get_legacy_flag(struct nl_context *nlctx, unsigned int nlcmd,
+		    unsigned int hdrattr);
 
 int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data);
 int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data);
diff --git a/netlink/parser.c b/netlink/parser.c
index 3b25f5d5a88e..7d4d51235628 100644
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -996,6 +996,7 @@  int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
 	for (parser = params; parser->arg; parser++) {
 		struct nl_msg_buff *msgbuff;
 		struct nlattr *nest;
+		u32 flags;
 
 		n_params++;
 		if (group_style == PARSER_GROUP_NONE || !parser->group)
@@ -1018,9 +1019,11 @@  int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
 				goto out_free_buffs;
 			break;
 		case PARSER_GROUP_MSG:
+			flags = get_legacy_flag(nlctx, parser->group,
+						ETHTOOL_A_LINKINFO_HEADER);
 			if (ethnla_fill_header(msgbuff,
 					       ETHTOOL_A_LINKINFO_HEADER,
-					       nlctx->devname, 0))
+					       nlctx->devname, flags))
 				goto out_free_buffs;
 			break;
 		default: