summaryrefslogtreecommitdiffstats
path: root/net/mpls
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-03-23 15:11:56 -0700
committerDavid S. Miller <davem@davemloft.net>2017-03-23 16:41:27 -0700
commit16ae1f223601c44e5cb65c99257ffae003504704 (patch)
tree1f5284c0e82e4d94ca07eb022fa7911d99bb0cb6 /net/mpls
parent6f359f99b8c2ff3b09329611da00fe39a7c10e7e (diff)
parentd038e3dcfff6e3de132726a9c7174d8170032aa4 (diff)
downloadlinux-16ae1f223601c44e5cb65c99257ffae003504704.tar.gz
linux-16ae1f223601c44e5cb65c99257ffae003504704.tar.bz2
linux-16ae1f223601c44e5cb65c99257ffae003504704.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/ethernet/broadcom/genet/bcmmii.c drivers/net/hyperv/netvsc.c kernel/bpf/hashtab.c Almost entirely overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mpls')
-rw-r--r--net/mpls/af_mpls.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index f7a08e5f9763..82589b2abf3c 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1298,6 +1298,8 @@ static void mpls_ifdown(struct net_device *dev, int event)
{
struct mpls_route __rcu **platform_label;
struct net *net = dev_net(dev);
+ unsigned int nh_flags = RTNH_F_DEAD | RTNH_F_LINKDOWN;
+ unsigned int alive;
unsigned index;
platform_label = rtnl_dereference(net->mpls.platform_label);
@@ -1307,9 +1309,11 @@ static void mpls_ifdown(struct net_device *dev, int event)
if (!rt)
continue;
+ alive = 0;
change_nexthops(rt) {
if (rtnl_dereference(nh->nh_dev) != dev)
- continue;
+ goto next;
+
switch (event) {
case NETDEV_DOWN:
case NETDEV_UNREGISTER:
@@ -1317,13 +1321,16 @@ static void mpls_ifdown(struct net_device *dev, int event)
/* fall through */
case NETDEV_CHANGE:
nh->nh_flags |= RTNH_F_LINKDOWN;
- if (event != NETDEV_UNREGISTER)
- ACCESS_ONCE(rt->rt_nhn_alive) = rt->rt_nhn_alive - 1;
break;
}
if (event == NETDEV_UNREGISTER)
RCU_INIT_POINTER(nh->nh_dev, NULL);
+next:
+ if (!(nh->nh_flags & nh_flags))
+ alive++;
} endfor_nexthops(rt);
+
+ WRITE_ONCE(rt->rt_nhn_alive, alive);
}
}