aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2019-04-16 14:36:02 -0700
committerDavid S. Miller <davem@davemloft.net>2019-04-17 23:10:46 -0700
commit9b6b35abfbde376665c76029c75e4ab03186d378 (patch)
treed1a3f5b3e719fe6406a30e5b949edb9d5faf8a9d /net/ipv6/route.c
parentipv6: Pass fib6_result to ip6_rt_cache_alloc (diff)
downloadlinux-dev-9b6b35abfbde376665c76029c75e4ab03186d378.tar.xz
linux-dev-9b6b35abfbde376665c76029c75e4ab03186d378.zip
ipv6: Pass fib6_result to ip6_create_rt_rcu
Change ip6_create_rt_rcu to take fib6_result over a fib6_info. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5dd6113c8f8f..87a59883edd2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1038,22 +1038,24 @@ static bool ip6_hold_safe(struct net *net, struct rt6_info **prt)
}
/* called with rcu_lock held */
-static struct rt6_info *ip6_create_rt_rcu(struct fib6_info *rt)
+static struct rt6_info *ip6_create_rt_rcu(const struct fib6_result *res)
{
- unsigned short flags = fib6_info_dst_flags(rt);
- struct net_device *dev = rt->fib6_nh.fib_nh_dev;
+ struct net_device *dev = res->nh->fib_nh_dev;
+ struct fib6_info *f6i = res->f6i;
+ unsigned short flags;
struct rt6_info *nrt;
- if (!fib6_info_hold_safe(rt))
+ if (!fib6_info_hold_safe(f6i))
goto fallback;
+ flags = fib6_info_dst_flags(f6i);
nrt = ip6_dst_alloc(dev_net(dev), dev, flags);
if (!nrt) {
- fib6_info_release(rt);
+ fib6_info_release(f6i);
goto fallback;
}
- ip6_rt_copy_init(nrt, rt);
+ ip6_rt_copy_init(nrt, f6i);
return nrt;
fallback:
@@ -1104,7 +1106,7 @@ restart:
if (ip6_hold_safe(net, &rt))
dst_use_noref(&rt->dst, jiffies);
} else {
- rt = ip6_create_rt_rcu(res.f6i);
+ rt = ip6_create_rt_rcu(&res);
}
out:
@@ -2417,12 +2419,13 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
NULL);
}
-static bool ip6_redirect_nh_match(struct fib6_info *f6i,
- struct fib6_nh *nh,
+static bool ip6_redirect_nh_match(const struct fib6_result *res,
struct flowi6 *fl6,
const struct in6_addr *gw,
struct rt6_info **ret)
{
+ const struct fib6_nh *nh = res->nh;
+
if (nh->fib_nh_flags & RTNH_F_DEAD || !nh->fib_nh_gw_family ||
fl6->flowi6_oif != nh->fib_nh_dev->ifindex)
return false;
@@ -2433,12 +2436,9 @@ static bool ip6_redirect_nh_match(struct fib6_info *f6i,
* is different.
*/
if (!ipv6_addr_equal(gw, &nh->fib_nh_gw6)) {
- struct fib6_result res = {
- .f6i = f6i,
- };
struct rt6_info *rt_cache;
- rt_cache = rt6_find_cached_rt(&res, &fl6->daddr, &fl6->saddr);
+ rt_cache = rt6_find_cached_rt(res, &fl6->daddr, &fl6->saddr);
if (rt_cache &&
ipv6_addr_equal(gw, &rt_cache->rt6i_gateway)) {
*ret = rt_cache;
@@ -2463,6 +2463,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
{
struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
struct rt6_info *ret = NULL;
+ struct fib6_result res = {};
struct fib6_info *rt;
struct fib6_node *fn;
@@ -2480,12 +2481,14 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
for_each_fib6_node_rt_rcu(fn) {
+ res.f6i = rt;
+ res.nh = &rt->fib6_nh;
+
if (fib6_check_expired(rt))
continue;
if (rt->fib6_flags & RTF_REJECT)
break;
- if (ip6_redirect_nh_match(rt, &rt->fib6_nh, fl6,
- &rdfl->gateway, &ret))
+ if (ip6_redirect_nh_match(&res, fl6, &rdfl->gateway, &ret))
goto out;
}
@@ -2502,11 +2505,13 @@ restart:
goto restart;
}
+ res.f6i = rt;
+ res.nh = &rt->fib6_nh;
out:
if (ret)
ip6_hold_safe(net, &ret);
else
- ret = ip6_create_rt_rcu(rt);
+ ret = ip6_create_rt_rcu(&res);
rcu_read_unlock();