Commit 8067bb8c authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

ipv6: Ignore dead routes during lookup

Currently, dead routes are only present in the routing tables in case
the 'ignore_routes_with_linkdown' sysctl is set. Otherwise, they are
flushed.

Subsequent patches are going to remove the reliance on this sysctl and
make IPv6 more consistent with IPv4.

Before this is done, we need to make sure dead routes are skipped during
route lookup, so as to not cause packet loss.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44c9f2f2
...@@ -474,6 +474,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, ...@@ -474,6 +474,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
if (route_choosen == 0) { if (route_choosen == 0) {
struct inet6_dev *idev = sibling->rt6i_idev; struct inet6_dev *idev = sibling->rt6i_idev;
if (sibling->rt6i_nh_flags & RTNH_F_DEAD)
break;
if (sibling->rt6i_nh_flags & RTNH_F_LINKDOWN && if (sibling->rt6i_nh_flags & RTNH_F_LINKDOWN &&
idev->cnf.ignore_routes_with_linkdown) idev->cnf.ignore_routes_with_linkdown)
break; break;
...@@ -499,12 +501,15 @@ static inline struct rt6_info *rt6_device_match(struct net *net, ...@@ -499,12 +501,15 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
struct rt6_info *local = NULL; struct rt6_info *local = NULL;
struct rt6_info *sprt; struct rt6_info *sprt;
if (!oif && ipv6_addr_any(saddr)) if (!oif && ipv6_addr_any(saddr) && !(rt->rt6i_nh_flags & RTNH_F_DEAD))
goto out; return rt;
for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) { for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) {
struct net_device *dev = sprt->dst.dev; struct net_device *dev = sprt->dst.dev;
if (sprt->rt6i_nh_flags & RTNH_F_DEAD)
continue;
if (oif) { if (oif) {
if (dev->ifindex == oif) if (dev->ifindex == oif)
return sprt; return sprt;
...@@ -533,8 +538,8 @@ static inline struct rt6_info *rt6_device_match(struct net *net, ...@@ -533,8 +538,8 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
if (flags & RT6_LOOKUP_F_IFACE) if (flags & RT6_LOOKUP_F_IFACE)
return net->ipv6.ip6_null_entry; return net->ipv6.ip6_null_entry;
} }
out:
return rt; return rt->rt6i_nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt;
} }
#ifdef CONFIG_IPV6_ROUTER_PREF #ifdef CONFIG_IPV6_ROUTER_PREF
...@@ -680,6 +685,9 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, ...@@ -680,6 +685,9 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
bool match_do_rr = false; bool match_do_rr = false;
struct inet6_dev *idev = rt->rt6i_idev; struct inet6_dev *idev = rt->rt6i_idev;
if (rt->rt6i_nh_flags & RTNH_F_DEAD)
goto out;
if (idev->cnf.ignore_routes_with_linkdown && if (idev->cnf.ignore_routes_with_linkdown &&
rt->rt6i_nh_flags & RTNH_F_LINKDOWN && rt->rt6i_nh_flags & RTNH_F_LINKDOWN &&
!(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE)) !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
...@@ -2153,6 +2161,8 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, ...@@ -2153,6 +2161,8 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart: restart:
for_each_fib6_node_rt_rcu(fn) { for_each_fib6_node_rt_rcu(fn) {
if (rt->rt6i_nh_flags & RTNH_F_DEAD)
continue;
if (rt6_check_expired(rt)) if (rt6_check_expired(rt))
continue; continue;
if (rt->dst.error) if (rt->dst.error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment