diff options
author | David Ahern <dsa@cumulusnetworks.com> | 2017-03-24 15:21:57 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-03-27 14:09:50 -0700 |
commit | 4ea8efadf5690c1ab22f981a5fcff819bd09ff31 (patch) | |
tree | 74d242126811f7d73bc09832cd46865c253de9cb | |
parent | c00e51ddbfda73d2be6d61fea2e58aeb57527475 (diff) |
net: mpls: Delete route when all nexthops have been deleted
When all devices for all nexthops in a route have been deleted, the
route is effectively dead, so remove it.
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/mpls/af_mpls.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 3861f8dfa9c1..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); } } |