summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-03-27 14:09:50 -0700
committerDavid S. Miller <davem@davemloft.net>2017-03-27 14:09:50 -0700
commit5dac9eaa39b3207f977adb3cd78b06dcbd97f69d (patch)
tree74d242126811f7d73bc09832cd46865c253de9cb
parent88275ed0cb3ac89ed869a925337b951801b154d7 (diff)
parent4ea8efadf5690c1ab22f981a5fcff819bd09ff31 (diff)
downloadlwn-5dac9eaa39b3207f977adb3cd78b06dcbd97f69d.tar.gz
lwn-5dac9eaa39b3207f977adb3cd78b06dcbd97f69d.zip
Merge branch 'mpls-multipath-route-cleanups'
David Ahern says: ==================== net: mpls: multipath route cleanups When a device associated with a nexthop is deleted, the nexthop in the route is effectively removed, so remove it from the route dump. Further, when all nexhops have been deleted the route is effectively done, so remove the route. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/mpls/af_mpls.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index cd8be8d5e4ad..74755920c689 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1299,7 +1299,7 @@ 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 int alive, deleted;
unsigned index;
platform_label = rtnl_dereference(net->mpls.platform_label);
@@ -1310,6 +1310,7 @@ static void mpls_ifdown(struct net_device *dev, int event)
continue;
alive = 0;
+ deleted = 0;
change_nexthops(rt) {
if (rtnl_dereference(nh->nh_dev) != dev)
goto next;
@@ -1328,9 +1329,15 @@ static void mpls_ifdown(struct net_device *dev, int event)
next:
if (!(nh->nh_flags & nh_flags))
alive++;
+ if (!rtnl_dereference(nh->nh_dev))
+ deleted++;
} endfor_nexthops(rt);
WRITE_ONCE(rt->rt_nhn_alive, alive);
+
+ /* if there are no more nexthops, delete the route */
+ if (event == NETDEV_UNREGISTER && deleted == rt->rt_nhn)
+ mpls_route_update(net, index, NULL, NULL);
}
}
@@ -1769,13 +1776,15 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
goto nla_put_failure;
for_nexthops(rt) {
+ dev = rtnl_dereference(nh->nh_dev);
+ if (!dev)
+ continue;
+
rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
if (!rtnh)
goto nla_put_failure;
- dev = rtnl_dereference(nh->nh_dev);
- if (dev)
- rtnh->rtnh_ifindex = dev->ifindex;
+ rtnh->rtnh_ifindex = dev->ifindex;
if (nh->nh_flags & RTNH_F_LINKDOWN) {
rtnh->rtnh_flags |= RTNH_F_LINKDOWN;
linkdown++;