]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv4/fib_semantics.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / net / ipv4 / fib_semantics.c
index f30df0ee4f4d8b93814d6f24aa6e020ce381c40c..3e87447e65c777ff969d366136d2015e3cf9a8e2 100644 (file)
@@ -1343,7 +1343,13 @@ int fib_sync_down_addr(struct net *net, __be32 local)
        return ret;
 }
 
-int fib_sync_down_dev(struct net_device *dev, unsigned long event)
+/* Event              force Flags           Description
+ * NETDEV_CHANGE      0     LINKDOWN        Carrier OFF, not for scope host
+ * NETDEV_DOWN        0     LINKDOWN|DEAD   Link down, not for scope host
+ * NETDEV_DOWN        1     LINKDOWN|DEAD   Last address removed
+ * NETDEV_UNREGISTER  1     LINKDOWN|DEAD   Device removed
+ */
+int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force)
 {
        int ret = 0;
        int scope = RT_SCOPE_NOWHERE;
@@ -1352,8 +1358,7 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event)
        struct hlist_head *head = &fib_info_devhash[hash];
        struct fib_nh *nh;
 
-       if (event == NETDEV_UNREGISTER ||
-           event == NETDEV_DOWN)
+       if (force)
                scope = -1;
 
        hlist_for_each_entry(nh, head, nh_hash) {
@@ -1498,6 +1503,13 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags)
        if (!(dev->flags & IFF_UP))
                return 0;
 
+       if (nh_flags & RTNH_F_DEAD) {
+               unsigned int flags = dev_get_flags(dev);
+
+               if (flags & (IFF_RUNNING | IFF_LOWER_UP))
+                       nh_flags |= RTNH_F_LINKDOWN;
+       }
+
        prev_fi = NULL;
        hash = fib_devindex_hashfn(dev->ifindex);
        head = &fib_info_devhash[hash];