linux-kernel.vger.kernel.org archive mirror
 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 12/17] ethtool: implement SET_SETTINGS notification
Date: Mon, 30 Jul 2018 14:53:42 +0200 (CEST)	[thread overview]
Message-ID: <0f59c43203698da554069328f1a96026bf9bf037.1532953989.git.mkubecek@suse.cz> (raw)
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>

SET_SETTINGS notification message has the same format as response to
GET_SETTINGS request and is broadcasted on change of relevant fields. Info
mask can be used to limit the information passed to userspace.

Also trigger the notification on analogous changes performed via the legacy
ioctl interface.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Documentation/networking/ethtool-netlink.txt |  3 +-
 net/core/dev.c                               |  3 ++
 net/ethtool/ioctl.c                          | 36 +++++++++++++++--
 net/ethtool/netlink.c                        |  2 +
 net/ethtool/settings.c                       | 41 ++++++++++++++++++++
 5 files changed, 80 insertions(+), 5 deletions(-)

diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 82b839c03707..3993652f81a9 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -263,7 +263,8 @@ requests.
 
 GET_SETTINGS requests allow dumps and messages in the same format as response
 to them are broadcasted as notifications on change of these settings using
-netlink or ioctl ethtool interface.
+netlink or ioctl ethtool interface; feature notifications are also sent
+whenever netdev_update_features() or netdev_change_features() is called.
 
 
 Request translation
diff --git a/net/core/dev.c b/net/core/dev.c
index 8a0773a52dd7..66932a9f133e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -93,6 +93,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/ethtool_netlink.h>
 #include <linux/notifier.h>
 #include <linux/skbuff.h>
 #include <linux/bpf.h>
@@ -1318,6 +1319,8 @@ int dev_get_alias(const struct net_device *dev, char *name, size_t len)
 void netdev_features_change(struct net_device *dev)
 {
 	call_netdevice_notifiers(NETDEV_FEAT_CHANGE, dev);
+	netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+				   ETH_SETTINGS_IM_FEATURES);
 }
 EXPORT_SYMBOL(netdev_features_change);
 
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 39e9aea60516..2754d3f6fd75 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -27,6 +27,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/sched/signal.h>
 #include <linux/net.h>
+#include <linux/ethtool_netlink.h>
 #include "common.h"
 
 /*
@@ -125,6 +126,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	dev->wanted_features &= ~valid;
 	dev->wanted_features |= wanted & valid;
 	__netdev_update_features(dev);
+	netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+				   ETH_SETTINGS_IM_FEATURES);
 
 	if ((dev->wanted_features ^ dev->features) & valid)
 		ret |= ETHTOOL_F_WISH;
@@ -243,6 +246,8 @@ static int ethtool_set_one_feature(struct net_device *dev,
 		dev->wanted_features &= ~mask;
 
 	__netdev_update_features(dev);
+	netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+				   ETH_SETTINGS_IM_FEATURES);
 
 	return 0;
 }
@@ -298,6 +303,8 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
 		(dev->wanted_features & ~changed) | (features & changed);
 
 	__netdev_update_features(dev);
+	netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+				   ETH_SETTINGS_IM_FEATURES);
 
 	return 0;
 }
@@ -638,6 +645,7 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
 static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_cmd cmd;
+	int ret;
 
 	ASSERT_RTNL();
 
@@ -655,8 +663,14 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
 		link_ksettings.base.cmd = ETHTOOL_SLINKSETTINGS;
 		link_ksettings.base.link_mode_masks_nwords
 			= __ETHTOOL_LINK_MODE_MASK_NU32;
-		return dev->ethtool_ops->set_link_ksettings(dev,
-							    &link_ksettings);
+		ret = dev->ethtool_ops->set_link_ksettings(dev,
+							   &link_ksettings);
+		if (ret >= 0)
+			netdev_ethtool_info_change(dev, NULL,
+						   ETHNL_CMD_SET_SETTINGS,
+						   ETH_SETTINGS_IM_LINKINFO |
+						   ETH_SETTINGS_IM_LINKMODES);
+		return ret;
 	}
 
 	/* legacy %ethtool_cmd API */
@@ -668,7 +682,12 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
 	if (!dev->ethtool_ops->set_settings)
 		return -EOPNOTSUPP;
 
-	return dev->ethtool_ops->set_settings(dev, &cmd);
+	ret = dev->ethtool_ops->set_settings(dev, &cmd);
+	if (ret >= 0)
+		netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+					   ETH_SETTINGS_IM_LINKINFO |
+					   ETH_SETTINGS_IM_LINKMODES);
+	return ret;
 }
 
 static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
@@ -1279,6 +1298,7 @@ static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
 static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_wolinfo wol;
+	int ret;
 
 	if (!dev->ethtool_ops->set_wol)
 		return -EOPNOTSUPP;
@@ -1286,7 +1306,11 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
 	if (copy_from_user(&wol, useraddr, sizeof(wol)))
 		return -EFAULT;
 
-	return dev->ethtool_ops->set_wol(dev, &wol);
+	ret = dev->ethtool_ops->set_wol(dev, &wol);
+	if (ret >= 0)
+		netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+					   ETH_SETTINGS_IM_WOLINFO);
+	return ret;
 }
 
 static int ethtool_get_eee(struct net_device *dev, char __user *useraddr)
@@ -2478,6 +2502,10 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_SMSGLVL:
 		rc = ethtool_set_value_void(dev, useraddr,
 				       dev->ethtool_ops->set_msglevel);
+		if (rc >= 0)
+			netdev_ethtool_info_change(dev, NULL,
+						   ETHNL_CMD_SET_SETTINGS,
+						   ETH_SETTINGS_IM_MSGLEVEL);
 		break;
 	case ETHTOOL_GEEE:
 		rc = ethtool_get_eee(dev, useraddr);
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 6c14185a6466..0e2158092a44 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -629,7 +629,9 @@ int ethnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 
 typedef void (*ethnl_notify_handler_t)(struct netdev_notifier_ethtool_info *);
 
+void ethnl_settings_notify(struct netdev_notifier_ethtool_info *);
 ethnl_notify_handler_t ethnl_notify_handlers[] = {
+	[ETHNL_CMD_SET_SETTINGS]	= ethnl_settings_notify,
 };
 
 static void __ethnl_notify(struct netdev_notifier_ethtool_info *info)
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
index fdca418a6d8e..739bd006c924 100644
--- a/net/ethtool/settings.c
+++ b/net/ethtool/settings.c
@@ -565,3 +565,44 @@ int ethnl_settings_done(struct netlink_callback *cb)
 
 	return 0;
 }
+
+void ethnl_settings_notify(struct netdev_notifier_ethtool_info *info)
+{
+	struct settings_reqinfo req_info = {
+		.dev		= info->info.dev,
+		.req_mask	= info->ethtool_info.req_mask,
+		.compact	= true,
+		.is_privileged	= false,
+		.have_rtnl	= true,
+	};
+	struct settings_data data;
+	struct sk_buff *skb;
+	int reply_len;
+	void *ehdr;
+	int ret;
+
+	ret = prepare_settings(&data, &req_info, NULL, req_info.dev);
+	if (ret < 0)
+		return;
+	reply_len = settings_size(&data, &req_info);
+	if (ret < 0)
+		return;
+	skb = genlmsg_new(reply_len, GFP_KERNEL);
+	if (!skb)
+		return;
+	ehdr = genlmsg_put(skb, 0, ++ethnl_bcast_seq, &ethtool_genl_family, 0,
+			   ETHNL_CMD_SET_SETTINGS);
+	ret = ethnl_fill_dev(skb, req_info.dev, ETHA_SETTINGS_DEV);
+	if (ret < 0)
+		goto err_skb;
+	ret = fill_settings(skb, &data, &req_info);
+	if (ret < 0)
+		goto err_skb;
+	genlmsg_end(skb, ehdr);
+
+	genlmsg_multicast(&ethtool_genl_family, skb, 0, ETHNL_MCGRP_MONITOR,
+			  GFP_KERNEL);
+	return;
+err_skb:
+	nlmsg_free(skb);
+}
-- 
2.18.0


  parent reply	other threads:[~2018-07-30 12:53 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 ` Michal Kubecek [this message]
2018-07-30 12:53 ` [RFC PATCH net-next v2 13/17] ethtool: implement SET_SETTINGS message Michal Kubecek
2018-07-30 12:53 ` [RFC PATCH net-next v2 14/17] ethtool: implement SET_SETTINGS request for features Michal Kubecek
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=0f59c43203698da554069328f1a96026bf9bf037.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).