ipv6: Refactor find_rr_leaf

find_rr_leaf has 3 loops over fib_entries calling find_match. The loops
are very similar with differences in start point and whether the metric
is evaluated:
    1. start at rr_head, no extra loop compare, check fib metric
    2. start at leaf, compare rt against rr_head, check metric
    3. start at cont (potential saved point from earlier loops), no
       extra loop compare, no metric check

Create 1 loop that is called 3 different times. This will make a
later change with multipath nexthop objects much simpler.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David Ahern 2019-04-09 14:41:15 -07:00 committed by David S. Miller
parent 28679ed104
commit 30c15f0338

View File

@ -668,58 +668,52 @@ static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
return rc; return rc;
} }
static struct fib6_info *find_rr_leaf(struct fib6_node *fn, static void __find_rr_leaf(struct fib6_info *rt_start,
struct fib6_info *leaf, struct fib6_info *nomatch, u32 metric,
struct fib6_info *rr_head, struct fib6_info **match, struct fib6_info **cont,
u32 metric, int oif, int strict, int oif, int strict, bool *do_rr, int *mpri)
bool *do_rr)
{ {
struct fib6_info *rt, *match, *cont; struct fib6_info *rt;
struct fib6_nh *nh;
for (rt = rt_start;
rt && rt != nomatch;
rt = rcu_dereference(rt->fib6_next)) {
struct fib6_nh *nh;
if (cont && rt->fib6_metric != metric) {
*cont = rt;
return;
}
if (fib6_check_expired(rt))
continue;
nh = &rt->fib6_nh;
if (find_match(nh, rt->fib6_flags, oif, strict, mpri, do_rr))
*match = rt;
}
}
static struct fib6_info *find_rr_leaf(struct fib6_node *fn,
struct fib6_info *leaf,
struct fib6_info *rr_head,
u32 metric, int oif, int strict,
bool *do_rr)
{
struct fib6_info *match = NULL, *cont = NULL;
int mpri = -1; int mpri = -1;
match = NULL; __find_rr_leaf(rr_head, NULL, metric, &match, &cont,
cont = NULL; oif, strict, do_rr, &mpri);
for (rt = rr_head; rt; rt = rcu_dereference(rt->fib6_next)) {
if (rt->fib6_metric != metric) {
cont = rt;
break;
}
if (fib6_check_expired(rt)) __find_rr_leaf(leaf, rr_head, metric, &match, &cont,
continue; oif, strict, do_rr, &mpri);
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;
rt = rcu_dereference(rt->fib6_next)) {
if (rt->fib6_metric != metric) {
cont = rt;
break;
}
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) if (match || !cont)
return match; return match;
for (rt = cont; rt; rt = rcu_dereference(rt->fib6_next)) { __find_rr_leaf(cont, NULL, metric, &match, NULL,
if (fib6_check_expired(rt)) oif, strict, do_rr, &mpri);
continue;
nh = &rt->fib6_nh;
if (find_match(nh, rt->fib6_flags, oif, strict, &mpri, do_rr))
match = rt;
}
return match; return match;
} }