net: introduce pre-change upper device notifier
authorJiri Pirko <jiri@mellanox.com>
Fri, 16 Oct 2015 12:01:22 +0000 (14:01 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Oct 2015 14:15:05 +0000 (07:15 -0700)
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>
include/linux/netdevice.h
net/core/dev.c

index b3374402c1ea1d2c0df80d3b5c6a38a1cf1b4156..69fdd427c8cb8ff5f54c01c16481d0d39258c6de 100644 (file)
@@ -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);
index a229bf0d649dc9bf58ece00e95d58f8a133addca..1225b4be8ed6e5b419bc7789e75a75b3339eb7ba 100644 (file)
@@ -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