Commit 9c6451ef authored by Michal Kubecek's avatar Michal Kubecek Committed by David S. Miller
Browse files

ethtool: add FEATURES_NTF notification



Send ETHTOOL_MSG_FEATURES_NTF notification whenever network device features
are modified using ETHTOOL_MSG_FEATURES_SET netlink message, ethtool ioctl
request or any other way resulting in call to netdev_update_features() or
netdev_change_features()

Signed-off-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0980bfcd
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@ Kernel to userspace:
  ``ETHTOOL_MSG_WOL_NTF``               wake-on-lan settings notification
  ``ETHTOOL_MSG_FEATURES_GET_REPLY``    device features
  ``ETHTOOL_MSG_FEATURES_SET_REPLY``    optional reply to FEATURES_SET
  ``ETHTOOL_MSG_FEATURES_NTF``          netdev features notification
  ===================================== =================================

``GET`` requests are sent by userspace applications to retrieve device
@@ -591,6 +592,11 @@ reports the difference between old and new dev->features: mask consists of
bits which have changed, values are their values in new dev->features (after
the operation).

``ETHTOOL_MSG_FEATURES_NTF`` notification is sent not only if device features
are modified using ``ETHTOOL_MSG_FEATURES_SET`` request or on of ethtool ioctl
request but also each time features are modified with netdev_update_features()
or netdev_change_features().


Request translation
===================
+1 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ enum {
	ETHTOOL_MSG_WOL_NTF,
	ETHTOOL_MSG_FEATURES_GET_REPLY,
	ETHTOOL_MSG_FEATURES_SET_REPLY,
	ETHTOOL_MSG_FEATURES_NTF,

	/* add new constants above here */
	__ETHTOOL_MSG_KERNEL_CNT,
+4 −0
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
	struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1];
	struct ethnl_req_info req_info = {};
	struct net_device *dev;
	bool mod;
	int ret;

	ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb,
@@ -272,6 +273,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
	dev->wanted_features = ethnl_bitmap_to_features(req_wanted);
	__netdev_update_features(dev);
	ethnl_features_to_bitmap(new_active, dev->features);
	mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);

	ret = 0;
	if (!(req_info.flags & ETHTOOL_FLAG_OMIT_REPLY)) {
@@ -292,6 +294,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
					  wanted_diff_mask, new_active,
					  active_diff_mask, compact);
	}
	if (mod)
		ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL);

out_rtnl:
	rtnl_unlock();
+28 −1
Original line number Diff line number Diff line
@@ -528,6 +528,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = {
	[ETHTOOL_MSG_LINKMODES_NTF]	= &ethnl_linkmodes_request_ops,
	[ETHTOOL_MSG_DEBUG_NTF]		= &ethnl_debug_request_ops,
	[ETHTOOL_MSG_WOL_NTF]		= &ethnl_wol_request_ops,
	[ETHTOOL_MSG_FEATURES_NTF]	= &ethnl_features_request_ops,
};

/* default notification handler */
@@ -613,6 +614,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = {
	[ETHTOOL_MSG_LINKMODES_NTF]	= ethnl_default_notify,
	[ETHTOOL_MSG_DEBUG_NTF]		= ethnl_default_notify,
	[ETHTOOL_MSG_WOL_NTF]		= ethnl_default_notify,
	[ETHTOOL_MSG_FEATURES_NTF]	= ethnl_default_notify,
};

void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data)
@@ -630,6 +632,29 @@ void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data)
}
EXPORT_SYMBOL(ethtool_notify);

static void ethnl_notify_features(struct netdev_notifier_info *info)
{
	struct net_device *dev = netdev_notifier_info_to_dev(info);

	ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL);
}

static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
			      void *ptr)
{
	switch (event) {
	case NETDEV_FEAT_CHANGE:
		ethnl_notify_features(ptr);
		break;
	}

	return NOTIFY_DONE;
}

static struct notifier_block ethnl_netdev_notifier = {
	.notifier_call = ethnl_netdev_event,
};

/* genetlink setup */

static const struct genl_ops ethtool_genl_ops[] = {
@@ -736,7 +761,9 @@ static int __init ethnl_init(void)
		return ret;
	ethnl_ok = true;

	return 0;
	ret = register_netdevice_notifier(&ethnl_netdev_notifier);
	WARN(ret < 0, "ethtool: net device notifier registration failed");
	return ret;
}

subsys_initcall(ethnl_init);