Commit 17a5984e authored by David Ahern's avatar David Ahern Committed by David S. Miller

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: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 962b6803
...@@ -765,6 +765,24 @@ static bool find_match(struct fib6_nh *nh, u32 fib6_flags, ...@@ -765,6 +765,24 @@ static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
return rc; 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, static void __find_rr_leaf(struct fib6_info *f6i_start,
struct fib6_info *nomatch, u32 metric, struct fib6_info *nomatch, u32 metric,
struct fib6_result *res, struct fib6_info **cont, struct fib6_result *res, struct fib6_info **cont,
...@@ -775,6 +793,7 @@ static void __find_rr_leaf(struct fib6_info *f6i_start, ...@@ -775,6 +793,7 @@ static void __find_rr_leaf(struct fib6_info *f6i_start,
for (f6i = f6i_start; for (f6i = f6i_start;
f6i && f6i != nomatch; f6i && f6i != nomatch;
f6i = rcu_dereference(f6i->fib6_next)) { f6i = rcu_dereference(f6i->fib6_next)) {
bool matched = false;
struct fib6_nh *nh; struct fib6_nh *nh;
if (cont && f6i->fib6_metric != metric) { if (cont && f6i->fib6_metric != metric) {
...@@ -785,8 +804,34 @@ static void __find_rr_leaf(struct fib6_info *f6i_start, ...@@ -785,8 +804,34 @@ static void __find_rr_leaf(struct fib6_info *f6i_start,
if (fib6_check_expired(f6i)) if (fib6_check_expired(f6i))
continue; continue;
nh = f6i->fib6_nh; if (unlikely(f6i->nh)) {
if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) { 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))
matched = true;
}
if (matched) {
res->f6i = f6i; res->f6i = f6i;
res->nh = nh; res->nh = nh;
res->fib6_flags = f6i->fib6_flags; res->fib6_flags = f6i->fib6_flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment