Commit 28679ed1 authored by David Ahern's avatar David Ahern Committed by David S. Miller
Browse files

ipv6: Refactor find_match



find_match primarily needs a fib6_nh (and fib6_flags which it passes
through to rt6_score_route). Move fib6_check_expired up to the call
sites so find_match is only called for relevant entries. Remove the
match argument which is mostly a pass through and use the return
boolean to decide if match gets set in the call sites.

The end result is a helper that can be called per fib6_nh struct
which is needed once fib entries reference nexthop objects that
have more than one fib6_nh.

Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 702cea56
Loading
Loading
Loading
Loading
+32 −18
Original line number Diff line number Diff line
@@ -632,25 +632,22 @@ static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
	return m;
}

static struct fib6_info *find_match(struct fib6_info *rt, int oif, int strict,
				   int *mpri, struct fib6_info *match,
				   bool *do_rr)
static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
		       int oif, int strict, int *mpri, bool *do_rr)
{
	int m;
	bool match_do_rr = false;
	bool rc = false;
	int m;

	if (rt->fib6_nh.fib_nh_flags & RTNH_F_DEAD)
	if (nh->fib_nh_flags & RTNH_F_DEAD)
		goto out;

	if (ip6_ignore_linkdown(rt->fib6_nh.fib_nh_dev) &&
	    rt->fib6_nh.fib_nh_flags & RTNH_F_LINKDOWN &&
	if (ip6_ignore_linkdown(nh->fib_nh_dev) &&
	    nh->fib_nh_flags & RTNH_F_LINKDOWN &&
	    !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
		goto out;

	if (fib6_check_expired(rt))
		goto out;

	m = rt6_score_route(&rt->fib6_nh, rt->fib6_flags, oif, strict);
	m = rt6_score_route(nh, fib6_flags, oif, strict);
	if (m == RT6_NUD_FAIL_DO_RR) {
		match_do_rr = true;
		m = 0; /* lowest valid score */
@@ -659,16 +656,16 @@ static struct fib6_info *find_match(struct fib6_info *rt, int oif, int strict,
	}

	if (strict & RT6_LOOKUP_F_REACHABLE)
		rt6_probe(&rt->fib6_nh);
		rt6_probe(nh);

	/* note that m can be RT6_NUD_FAIL_PROBE at this point */
	if (m > *mpri) {
		*do_rr = match_do_rr;
		*mpri = m;
		match = rt;
		rc = true;
	}
out:
	return match;
	return rc;
}

static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
@@ -678,6 +675,7 @@ static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
				     bool *do_rr)
{
	struct fib6_info *rt, *match, *cont;
	struct fib6_nh *nh;
	int mpri = -1;

	match = NULL;
@@ -688,7 +686,12 @@ static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
			break;
		}

		match = find_match(rt, oif, strict, &mpri, match, do_rr);
		if (fib6_check_expired(rt))
			continue;

		nh = &rt->fib6_nh;
		if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
			match = rt;
	}

	for (rt = leaf; rt && rt != rr_head;
@@ -698,14 +701,25 @@ static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
			break;
		}

		match = find_match(rt, oif, strict, &mpri, match, do_rr);
		if (fib6_check_expired(rt))
			continue;

		nh = &rt->fib6_nh;
		if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
			match = rt;
	}

	if (match || !cont)
		return match;

	for (rt = cont; rt; rt = rcu_dereference(rt->fib6_next))
		match = find_match(rt, oif, strict, &mpri, match, do_rr);
	for (rt = cont; rt; rt = rcu_dereference(rt->fib6_next)) {
		if (fib6_check_expired(rt))
			continue;

		nh = &rt->fib6_nh;
		if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
			match = rt;
	}

	return match;
}