ipv6: Handle all fib6_nh in a nexthop in __find_rr_leaf

Add a hook in __find_rr_leaf to handle nexthop struct in a fib6_info.
nexthop_for_each_fib6_nh is used to walk each fib6_nh in a nexthop and
call find_match. On a match, use the fib6_nh saved in the callback arg
to setup fib6_result.

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-06-08 14:53:25 -07:00 committed by David S. Miller
parent 962b680383
commit 17a5984eee
1 changed files with 47 additions and 2 deletions

View File

@ -765,6 +765,24 @@ out:
return rc;
}
struct fib6_nh_frl_arg {
u32 flags;
int oif;
int strict;
int *mpri;
bool *do_rr;
struct fib6_nh *nh;
};
static int rt6_nh_find_match(struct fib6_nh *nh, void *_arg)
{
struct fib6_nh_frl_arg *arg = _arg;
arg->nh = nh;
return find_match(nh, arg->flags, arg->oif, arg->strict,
arg->mpri, arg->do_rr);
}
static void __find_rr_leaf(struct fib6_info *f6i_start,
struct fib6_info *nomatch, u32 metric,
struct fib6_result *res, struct fib6_info **cont,
@ -775,6 +793,7 @@ static void __find_rr_leaf(struct fib6_info *f6i_start,
for (f6i = f6i_start;
f6i && f6i != nomatch;
f6i = rcu_dereference(f6i->fib6_next)) {
bool matched = false;
struct fib6_nh *nh;
if (cont && f6i->fib6_metric != metric) {
@ -785,8 +804,34 @@ static void __find_rr_leaf(struct fib6_info *f6i_start,
if (fib6_check_expired(f6i))
continue;
if (unlikely(f6i->nh)) {
struct fib6_nh_frl_arg arg = {
.flags = f6i->fib6_flags,
.oif = oif,
.strict = strict,
.mpri = mpri,
.do_rr = do_rr
};
if (nexthop_is_blackhole(f6i->nh)) {
res->fib6_flags = RTF_REJECT;
res->fib6_type = RTN_BLACKHOLE;
res->f6i = f6i;
res->nh = nexthop_fib6_nh(f6i->nh);
return;
}
if (nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_find_match,
&arg)) {
matched = true;
nh = arg.nh;
}
} else {
nh = f6i->fib6_nh;
if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
if (find_match(nh, f6i->fib6_flags, oif, strict,
mpri, do_rr))
matched = true;
}
if (matched) {
res->f6i = f6i;
res->nh = nh;
res->fib6_flags = f6i->fib6_flags;