All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Kubecek <mkubecek@suse.cz>
To: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Jiri Pirko <jiri@resnulli.us>,
	David Miller <davem@davemloft.net>,
	Florian Fainelli <f.fainelli@gmail.com>,
	Roopa Prabhu <roopa@cumulusnetworks.com>,
	Jakub Kicinski <kubakici@wp.pl>,
	"John W. Linville" <linville@tuxdriver.com>
Subject: [RFC PATCH net-next v2 14/17] ethtool: implement SET_SETTINGS request for features
Date: Mon, 30 Jul 2018 14:53:52 +0200 (CEST)	[thread overview]
Message-ID: <1127951c1ac8d2fb6fcb3d6caba6f45bcd74a37d.1532953989.git.mkubecek@suse.cz> (raw)
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>

Using ETHNL_SETTINGS_FEATURES attribute, userspace can modify device
features. Actual change is subject to netdev_change_features() sanity
checks so that it can differ from what was requested. Unlike with most
other requests, kernel can reply (if ETHA_FEATURES_WANT_DIFF flag is used)
with a message in the same format but with different semantics: information
about difference between user request and actual result and difference
between old and new state of dev->features.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Documentation/networking/ethtool-netlink.txt |  30 +++--
 include/uapi/linux/ethtool_netlink.h         |   1 +
 net/ethtool/settings.c                       | 127 +++++++++++++++++++
 3 files changed, 150 insertions(+), 8 deletions(-)

diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index c7fe4f518972..307d8c6c6c85 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -285,6 +285,9 @@ to be passed with SET_SETTINGS request:
     ETHA_SETTINGS_SOPASS        (binary)        SecureOn(tm) password
     ETHA_SETTINGS_MSGLVL        (bitfield32)    debug level
     ETHA_SETTINGS_LINK_MODES    (bitset)        device link modes
+    ETHA_SETTINGS_FEATURES	(nested)	device features
+        ETHA_FEATURES_WANTED		(bitset)	wanted features
+        ETHA_FEATURES_WANT_DIFF		(flag)		actual diff
 
 For both bitfield32 types, value and selector work the usual way, i.e. bits
 set in selector are set to corresponding bits from value and the rest is
@@ -299,6 +302,17 @@ autoselection is done on ethtool side with ioctl interface, netlink interface
 is supposed to allow requesting changes without knowing what exactly kernel
 supports.
 
+When changing device features, only ETHA_FEATURES_WANTED is passed. As usual,
+mask defines which bits are to be set and value their values. If the request
+has ETHA_FEATURES_WANT_DIFF flag set, reply will contain a message in the same
+format as response to GET request, except only two bitsets are provided.
+ETHA_FEATURES_WANTED shows difference between requested features and actual
+result (dev->features after the operation); mask shows bits which differ and
+value their values from the original request (new values are negated). Value
+shows changes between old dev->features (before the operation) and new (after
+the operation); mask shows bits which have been changed and value their new
+values.
+
 
 Request translation
 -------------------
@@ -328,30 +342,30 @@ ETHTOOL_SRINGPARAM		n/a
 ETHTOOL_GPAUSEPARAM		n/a
 ETHTOOL_SPAUSEPARAM		n/a
 ETHTOOL_GRXCSUM			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SRXCSUM			n/a
+ETHTOOL_SRXCSUM			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GTXCSUM			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_STXCSUM			n/a
+ETHTOOL_STXCSUM			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GSG			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SSG			n/a
+ETHTOOL_SSG			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_TEST			n/a
 ETHTOOL_GSTRINGS		ETHNL_CMD_GET_STRSET
 ETHTOOL_PHYS_ID			n/a
 ETHTOOL_GSTATS			n/a
 ETHTOOL_GTSO			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_STSO			n/a
+ETHTOOL_STSO			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GPERMADDR		n/a
 ETHTOOL_GUFO			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SUFO			n/a
+ETHTOOL_SUFO			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GGSO			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SGSO			n/a
+ETHTOOL_SGSO			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GFLAGS			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SFLAGS			n/a
+ETHTOOL_SFLAGS			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GPFLAGS			n/a
 ETHTOOL_SPFLAGS			n/a
 ETHTOOL_GRXFH			n/a
 ETHTOOL_SRXFH			n/a
 ETHTOOL_GGRO			ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SGRO			n/a
+ETHTOOL_SGRO			ETHNL_CMD_SET_SETTINGS
 ETHTOOL_GRXRINGS		n/a
 ETHTOOL_GRXCLSRLCNT		n/a
 ETHTOOL_GRXCLSRULE		n/a
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 06c78b281275..8dfcb9ef4009 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -191,6 +191,7 @@ enum {
 	ETHA_FEATURES_WANTED,			/* bitset */
 	ETHA_FEATURES_ACTIVE,			/* bitset */
 	ETHA_FEATURES_NOCHANGE,			/* bitset */
+	ETHA_FEATURES_WANT_DIFF,		/* flag */
 
 	__ETHA_FEATURES_MAX,
 	ETHA_FEATURES_MAX = (__ETHA_FEATURES_MAX - 1)
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
index 678199e621a2..475582b7950c 100644
--- a/net/ethtool/settings.c
+++ b/net/ethtool/settings.c
@@ -1016,6 +1016,122 @@ static int ethnl_update_lsettings(struct genl_info *info, struct nlattr **tb,
 	return 0;
 }
 
+static const struct nla_policy features_policy[ETHA_FEATURES_MAX + 1] = {
+	[ETHA_FEATURES_UNSPEC]		= { .type = NLA_UNSPEC },
+	[ETHA_FEATURES_HW]		= { .type = NLA_NESTED },
+	[ETHA_FEATURES_WANTED]		= { .type = NLA_NESTED },
+	[ETHA_FEATURES_ACTIVE]		= { .type = NLA_NESTED },
+	[ETHA_FEATURES_NOCHANGE]	= { .type = NLA_NESTED },
+	[ETHA_FEATURES_WANT_DIFF]	= { .type = NLA_FLAG },
+};
+
+static void bitmap_from_features(unsigned long *bitmap, netdev_features_t val)
+{
+	const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT);
+	unsigned int i;
+
+	bitmap_zero(bitmap, NETDEV_FEATURE_COUNT);
+	for (i = 0; i < words; i++)
+		bitmap[i] = (unsigned long)(val >> (i * BITS_PER_LONG));
+}
+
+static netdev_features_t features_from_bitmap(unsigned long *bitmap)
+{
+	const unsigned int words = BITS_TO_LONGS(NETDEV_FEATURE_COUNT);
+	netdev_features_t ret = 0;
+	unsigned int i;
+
+	for (i = 0; i < words; i++)
+		ret |= (netdev_features_t)(bitmap[i]) << (i * BITS_PER_LONG);
+	return ret;
+}
+
+int update_features(struct genl_info *info, struct net_device *dev,
+		    const struct nlattr *nest, bool compact)
+{
+	struct nlattr *tb[ETHA_FEATURES_MAX + 1];
+	DECLARE_BITMAP(old_active, NETDEV_FEATURE_COUNT);
+	DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT);
+	DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT);
+	DECLARE_BITMAP(new_active, NETDEV_FEATURE_COUNT);
+	DECLARE_BITMAP(wanted_diff_mask, NETDEV_FEATURE_COUNT);
+	DECLARE_BITMAP(active_diff_mask, NETDEV_FEATURE_COUNT);
+	struct nlattr *feat_attr;
+	unsigned int reply_len;
+	struct sk_buff *rskb;
+	bool mod = false;
+	void *ehdr;
+	int ret;
+
+	ret = nla_parse_nested(tb, ETHA_FEATURES_MAX, nest, features_policy,
+			       info->extack);
+	if (ret < 0)
+		return ret;
+	if (tb[ETHA_FEATURES_HW] || !tb[ETHA_FEATURES_WANTED] ||
+	    tb[ETHA_FEATURES_ACTIVE] || tb[ETHA_FEATURES_NOCHANGE])
+		return -EINVAL;
+
+	bitmap_from_features(old_active, dev->features);
+	bitmap_copy(req_wanted, old_active, NETDEV_FEATURE_COUNT);
+	bitmap_zero(req_mask, NETDEV_FEATURE_COUNT);
+	mod = ethnl_update_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT,
+				  tb[ETHA_FEATURES_WANTED], &ret, feature_names,
+				  info);
+	if (ret < 0 || !mod)
+		return ret;
+
+	dev->wanted_features = features_from_bitmap(req_wanted);
+	netdev_update_features(dev);
+	if (!tb[ETHA_FEATURES_WANT_DIFF])
+		return 0;
+	bitmap_from_features(new_active, dev->features);
+	bitmap_xor(wanted_diff_mask, req_wanted, new_active,
+		   NETDEV_FEATURE_COUNT);
+	bitmap_xor(active_diff_mask, old_active, new_active,
+		   NETDEV_FEATURE_COUNT);
+	bitmap_and(wanted_diff_mask, wanted_diff_mask, req_mask,
+		   NETDEV_FEATURE_COUNT);
+	bitmap_and(req_wanted, req_wanted, wanted_diff_mask,
+		   NETDEV_FEATURE_COUNT);
+	bitmap_and(new_active, new_active, active_diff_mask,
+		   NETDEV_FEATURE_COUNT);
+
+	reply_len = ethnl_bitset_size(compact, NETDEV_FEATURE_COUNT, req_wanted,
+				      wanted_diff_mask, feature_names) +
+		    ethnl_bitset_size(compact, NETDEV_FEATURE_COUNT, new_active,
+				      active_diff_mask, feature_names);
+	reply_len = nla_total_size(reply_len);
+	rskb = ethnl_reply_init(reply_len, dev, ETHNL_CMD_SET_SETTINGS,
+				ETHA_SETTINGS_DEV, info, &ehdr);
+	if (!rskb)
+		goto err;
+	ret = -EMSGSIZE;
+
+	feat_attr = ethnl_nest_start(rskb, ETHA_SETTINGS_FEATURES);
+	if (!feat_attr)
+		goto err;
+	ret = ethnl_put_bitset(rskb, ETHA_FEATURES_WANTED, compact,
+			       NETDEV_FEATURE_COUNT, req_wanted,
+			       wanted_diff_mask, feature_names);
+	if (ret < 0)
+		goto err;
+	ret = ethnl_put_bitset(rskb, ETHA_FEATURES_ACTIVE, compact,
+			       NETDEV_FEATURE_COUNT, new_active,
+			       active_diff_mask, feature_names);
+	if (ret < 0)
+		goto err;
+	nla_nest_end(rskb, feat_attr);
+
+	genlmsg_end(rskb, ehdr);
+	return genlmsg_reply(rskb, info);
+err:
+	WARN_ONCE(ret == -EMSGSIZE,
+		  "calculated message payload length (%d) not sufficient\n",
+		  reply_len);
+	nlmsg_free(rskb);
+	return ret;
+}
+
 int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info)
 {
 	struct nlattr *tb[ETHA_SETTINGS_MAX + 1];
@@ -1092,6 +1208,17 @@ int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info)
 			req_mask |= ETH_SETTINGS_IM_MSGLEVEL;
 		}
 	}
+	if (tb[ETHA_SETTINGS_FEATURES]) {
+		bool compact = tb[ETHA_SETTINGS_COMPACT];
+
+		ret = update_features(info, dev, tb[ETHA_SETTINGS_FEATURES],
+				      compact);
+		if (ret > 0) {
+			req_mask |= ETH_SETTINGS_IM_FEATURES;
+			ret = 0;
+		}
+
+	}
 	ret = 0;
 
 out_unlock:
-- 
2.18.0


  parent reply	other threads:[~2018-07-30 12:54 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-30 12:52 [RFC PATCH net-next v2 00/17] ethtool netlink interface (WiP) Michal Kubecek
2018-07-30 12:52 ` [RFC PATCH net-next v2 01/17] netlink: introduce nla_put_bitfield32() Michal Kubecek
2018-07-30 12:52 ` [RFC PATCH net-next v2 02/17] ethtool: move to its own directory Michal Kubecek
2018-07-30 12:52 ` [RFC PATCH net-next v2 03/17] ethtool: introduce ethtool netlink interface Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 04/17] ethtool: helper functions for " Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 05/17] ethtool: netlink bitset handling Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 06/17] ethtool: support for netlink notifications Michal Kubecek
2018-07-30 13:16   ` Jiri Pirko
2018-07-30 17:01     ` Michal Kubecek
2018-07-31  6:46       ` Jiri Pirko
2018-07-30 12:53 ` [RFC PATCH net-next v2 07/17] ethtool: implement EVENT notifications Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 08/17] ethtool: implement GET_STRSET message Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 09/17] ethtool: implement GET_DRVINFO message Michal Kubecek
2018-07-30 13:21   ` Jiri Pirko
2018-07-30 14:37     ` Michal Kubecek
2018-07-30 14:28   ` Andrew Lunn
2018-07-30 14:46     ` Michal Kubecek
2018-07-30 15:48       ` Andrew Lunn
2018-07-30 16:47         ` Michal Kubecek
2018-07-31  0:56   ` Jakub Kicinski
2018-07-30 12:53 ` [RFC PATCH net-next v2 10/17] ethtool: implement GET_SETTINGS message Michal Kubecek
2018-07-30 18:54   ` Andrew Lunn
2018-08-21  9:32     ` Michal Kubecek
2018-08-21 14:10       ` Andrew Lunn
2018-08-21 14:52         ` Michal Kubecek
2018-07-30 19:06   ` Andrew Lunn
2018-07-30 19:09   ` Andrew Lunn
2018-07-30 19:42     ` Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 11/17] ethtool: implement GET_SETTINGS request for features Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 12/17] ethtool: implement SET_SETTINGS notification Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 13/17] ethtool: implement SET_SETTINGS message Michal Kubecek
2018-07-30 12:53 ` Michal Kubecek [this message]
2018-07-30 12:53 ` [RFC PATCH net-next v2 15/17] ethtool: implement GET_PARAMS message Michal Kubecek
2018-07-30 12:54 ` [RFC PATCH net-next v2 16/17] ethtool: implement SET_PARAMS notification Michal Kubecek
2018-07-30 12:54 ` [RFC PATCH net-next v2 17/17] ethtool: implement SET_PARAMS message Michal Kubecek
2018-07-30 13:07 ` [RFC PATCH net-next v2 00/17] ethtool netlink interface (WiP) Jiri Pirko
2018-07-31  0:38   ` Jakub Kicinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1127951c1ac8d2fb6fcb3d6caba6f45bcd74a37d.1532953989.git.mkubecek@suse.cz \
    --to=mkubecek@suse.cz \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=jiri@resnulli.us \
    --cc=kubakici@wp.pl \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    --cc=roopa@cumulusnetworks.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.