Commit 0b34eb00 authored by David Ahern's avatar David Ahern Committed by David S. Miller

ipv6: Refactor __ip6_route_redirect

Move the nexthop evaluation of a fib entry to a helper that can be
leveraged for each fib6_nh in a multipath nexthop object.

In the move, 'continue' statements means the helper returns false
(loop should continue) and 'break' means return true (found the entry
of interest).
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0c59d006
...@@ -2407,6 +2407,35 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst, ...@@ -2407,6 +2407,35 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
NULL); NULL);
} }
static bool ip6_redirect_nh_match(struct fib6_info *f6i,
struct fib6_nh *nh,
struct flowi6 *fl6,
const struct in6_addr *gw,
struct rt6_info **ret)
{
if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family ||
fl6->flowi6_oif != nh->fib_nh_dev->ifindex)
return false;
/* rt_cache's gateway might be different from its 'parent'
* in the case of an ip redirect.
* So we keep searching in the exception table if the gateway
* is different.
*/
if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
struct rt6_info *rt_cache;
rt_cache = rt6_find_cached_rt(f6i, &fl6->daddr, &fl6->saddr);
if (rt_cache &&
ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
*ret = rt_cache;
return true;
}
return false;
}
return true;
}
/* Handle redirects */ /* Handle redirects */
struct ip6rd_flowi { struct ip6rd_flowi {
struct flowi6 fl6; struct flowi6 fl6;
...@@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, ...@@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
int flags) int flags)
{ {
struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
struct rt6_info *ret = NULL, *rt_cache; struct rt6_info *ret = NULL;
struct fib6_info *rt; struct fib6_info *rt;
struct fib6_node *fn; struct fib6_node *fn;
...@@ -2438,34 +2467,15 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, ...@@ -2438,34 +2467,15 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); fn = fib6_node_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->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
continue;
if (fib6_check_expired(rt)) if (fib6_check_expired(rt))
continue; continue;
if (rt->fib6_flags & RTF_REJECT) if (rt->fib6_flags & RTF_REJECT)
break; break;
if (!rt->fib6_nh.fib_nh_gw_family)
continue;
if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex) if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex)
continue; continue;
/* rt_cache's gateway might be different from its 'parent' if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
* in the case of an ip redirect. &rdfl->gateway, &ret))
* So we keep searching in the exception table if the gateway goto out;
* is different.
*/
if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh.fib_nh_gw6)) {
rt_cache = rt6_find_cached_rt(rt,
&fl6->daddr,
&fl6->saddr);
if (rt_cache &&
ipv6_addr_equal(&rdfl->gateway,
&rt_cache->rt6i_gateway)) {
ret = rt_cache;
break;
}
continue;
}
break;
} }
if (!rt) if (!rt)
......
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