summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2015-10-16 14:01:22 +0200
committerDavid S. Miller <davem@davemloft.net>2015-10-16 07:15:05 -0700
commit573c7ba006edbecff0714db651dd3602b9d0a6a0 (patch)
tree95f4e65ae8d2940047c1211fca064bccd41b25eb
parent125ecf4b5994f17cb581af399933d0bd0b153080 (diff)
downloadlinux-573c7ba006edbecff0714db651dd3602b9d0a6a0.tar.bz2
net: introduce pre-change upper device notifier
This newly introduced netdevice notifier is called before actual change upper happens. That provides a possibility for notifier handlers to know upper change will happen and react to it, including possibility to forbid the change. That is valuable for drivers which can check if the upper device linkage is supported and forbid that in case it is not. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/dev.c9
2 files changed, 10 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b3374402c1ea..69fdd427c8cb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2106,6 +2106,7 @@ struct pcpu_sw_netstats {
#define NETDEV_PRECHANGEMTU 0x0017 /* notify before mtu change happened */
#define NETDEV_CHANGEINFODATA 0x0018
#define NETDEV_BONDING_INFO 0x0019
+#define NETDEV_PRECHANGEUPPER 0x001A
int register_netdevice_notifier(struct notifier_block *nb);
int unregister_netdevice_notifier(struct notifier_block *nb);
diff --git a/net/core/dev.c b/net/core/dev.c
index a229bf0d649d..1225b4be8ed6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5346,6 +5346,12 @@ static int __netdev_upper_dev_link(struct net_device *dev,
changeupper_info.master = master;
changeupper_info.linking = true;
+ ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+ &changeupper_info.info);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ return ret;
+
ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
master);
if (ret)
@@ -5488,6 +5494,9 @@ void netdev_upper_dev_unlink(struct net_device *dev,
changeupper_info.master = netdev_master_upper_dev_get(dev) == upper_dev;
changeupper_info.linking = false;
+ call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+ &changeupper_info.info);
+
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
/* Here is the tricky part. We must remove all dev's lower