ipv6: Handle all fib6_nh in a nexthop in rt6_device_match
Add a hook in rt6_device_match to handle nexthop struct in a fib6_info. The new rt6_nh_dev_match uses nexthop_for_each_fib6_nh to walk each fib6_nh in a nexthop and call __rt6_device_match. On match, rt6_nh_dev_match returns the fib6_nh and rt6_device_match uses it 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
2ab75bfb17
commit
962b680383
|
@ -490,6 +490,45 @@ static bool __rt6_device_match(struct net *net, const struct fib6_nh *nh,
|
|||
return false;
|
||||
}
|
||||
|
||||
struct fib6_nh_dm_arg {
|
||||
struct net *net;
|
||||
const struct in6_addr *saddr;
|
||||
int oif;
|
||||
int flags;
|
||||
struct fib6_nh *nh;
|
||||
};
|
||||
|
||||
static int __rt6_nh_dev_match(struct fib6_nh *nh, void *_arg)
|
||||
{
|
||||
struct fib6_nh_dm_arg *arg = _arg;
|
||||
|
||||
arg->nh = nh;
|
||||
return __rt6_device_match(arg->net, nh, arg->saddr, arg->oif,
|
||||
arg->flags);
|
||||
}
|
||||
|
||||
/* returns fib6_nh from nexthop or NULL */
|
||||
static struct fib6_nh *rt6_nh_dev_match(struct net *net, struct nexthop *nh,
|
||||
struct fib6_result *res,
|
||||
const struct in6_addr *saddr,
|
||||
int oif, int flags)
|
||||
{
|
||||
struct fib6_nh_dm_arg arg = {
|
||||
.net = net,
|
||||
.saddr = saddr,
|
||||
.oif = oif,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
if (nexthop_is_blackhole(nh))
|
||||
return NULL;
|
||||
|
||||
if (nexthop_for_each_fib6_nh(nh, __rt6_nh_dev_match, &arg))
|
||||
return arg.nh;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rt6_device_match(struct net *net, struct fib6_result *res,
|
||||
const struct in6_addr *saddr, int oif, int flags)
|
||||
{
|
||||
|
@ -510,8 +549,19 @@ static void rt6_device_match(struct net *net, struct fib6_result *res,
|
|||
}
|
||||
|
||||
for (spf6i = f6i; spf6i; spf6i = rcu_dereference(spf6i->fib6_next)) {
|
||||
nh = spf6i->fib6_nh;
|
||||
if (__rt6_device_match(net, nh, saddr, oif, flags)) {
|
||||
bool matched = false;
|
||||
|
||||
if (unlikely(spf6i->nh)) {
|
||||
nh = rt6_nh_dev_match(net, spf6i->nh, res, saddr,
|
||||
oif, flags);
|
||||
if (nh)
|
||||
matched = true;
|
||||
} else {
|
||||
nh = spf6i->fib6_nh;
|
||||
if (__rt6_device_match(net, nh, saddr, oif, flags))
|
||||
matched = true;
|
||||
}
|
||||
if (matched) {
|
||||
res->f6i = spf6i;
|
||||
goto out;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue