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

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
Loading
Loading
Loading
Loading
+33 −23
Original line number Diff line number Diff line
@@ -2407,6 +2407,35 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
		      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 */
struct ip6rd_flowi {
	struct flowi6 fl6;
@@ -2420,7 +2449,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
					     int flags)
{
	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_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);
restart:
	for_each_fib6_node_rt_rcu(fn) {
		if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
			continue;
		if (fib6_check_expired(rt))
			continue;
		if (rt->fib6_flags & RTF_REJECT)
			break;
		if (!rt->fib6_nh.fib_nh_gw_family)
			continue;
		if (fl6->flowi6_oif != rt->fib6_nh.fib_nh_dev->ifindex)
			continue;
		/* 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(&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 (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
					  &rdfl->gateway, &ret))
			goto out;
	}

	if (!rt)