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: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0c59d00675
commit
0b34eb0043
|
@ -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,
|
||||||
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,
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue