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:
committed by
David S. Miller
parent
962b680383
commit
17a5984eee
@@ -765,6 +765,24 @@ out:
|
|||||||
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,
|
|||||||
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,
|
|||||||
if (fib6_check_expired(f6i))
|
if (fib6_check_expired(f6i))
|
||||||
continue;
|
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;
|
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->f6i = f6i;
|
||||||
res->nh = nh;
|
res->nh = nh;
|
||||||
res->fib6_flags = f6i->fib6_flags;
|
res->fib6_flags = f6i->fib6_flags;
|
||||||
|
|||||||
Reference in New Issue
Block a user