forked from Minki/linux
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:
parent
962b680383
commit
17a5984eee
@ -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;
|
||||
|
||||
nh = f6i->fib6_nh;
|
||||
if (find_match(nh, f6i->fib6_flags, oif, strict, mpri, do_rr)) {
|
||||
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))
|
||||
matched = true;
|
||||
}
|
||||
if (matched) {
|
||||
res->f6i = f6i;
|
||||
res->nh = nh;
|
||||
res->fib6_flags = f6i->fib6_flags;
|
||||
|
Loading…
Reference in New Issue
Block a user