Skip to content

Commit

Permalink
ipv6: Move dst->from into struct rt6_info.
Browse files Browse the repository at this point in the history
The dst->from value is only used by ipv6 routes to track where
a route "came from".

Any time we clone or copy a core ipv6 route in the ipv6 routing
tables, we have the copy/clone's ->from point to the base route.

This is used to handle route expiration properly.

Only ipv6 uses this mechanism, and only ipv6 code references
it.  So it is safe to move it into rt6_info.

Signed-off-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Eric Dumazet <edumazet@google.com>
  • Loading branch information
David Miller committed Nov 30, 2017
1 parent b6ca8bd commit 3a2232e
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 25 deletions.
3 changes: 1 addition & 2 deletions include/net/dst.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct dst_entry {
unsigned long _metrics;
unsigned long expires;
struct dst_entry *path;
struct dst_entry *from;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
Expand Down Expand Up @@ -88,7 +87,7 @@ struct dst_entry {
* Align __refcnt to a 64 bytes alignment
* (L1_CACHE_SIZE would be too much)
*/
long __pad_to_align_refcnt[3];
long __pad_to_align_refcnt[4];
#endif
/*
* __refcnt wants to be on a different cache line from
Expand Down
9 changes: 4 additions & 5 deletions include/net/ip6_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct rt6_exception {
struct rt6_info {
struct dst_entry dst;
struct rt6_info __rcu *rt6_next;
struct rt6_info *from;

/*
* Tail elements of dst_entry (__refcnt etc.)
Expand Down Expand Up @@ -204,11 +205,9 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
{
struct rt6_info *rt;

for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
rt = (struct rt6_info *)rt->dst.from);
for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); rt = rt->from);
if (rt && rt != rt0)
rt0->dst.expires = rt->dst.expires;

dst_set_expires(&rt0->dst, timeout);
rt0->rt6i_flags |= RTF_EXPIRES;
}
Expand Down Expand Up @@ -243,8 +242,8 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt)
u32 cookie = 0;

if (rt->rt6i_flags & RTF_PCPU ||
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from))
rt = (struct rt6_info *)(rt->dst.from);
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
rt = rt->from;

rt6_get_cookie_safe(rt, &cookie);

Expand Down
1 change: 0 additions & 1 deletion net/core/dst.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
dst_init_metrics(dst, dst_default_metrics.metrics, true);
dst->expires = 0UL;
dst->path = dst;
dst->from = NULL;
#ifdef CONFIG_XFRM
dst->xfrm = NULL;
#endif
Expand Down
34 changes: 17 additions & 17 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)

static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt)
{
return dst_metrics_write_ptr(rt->dst.from);
return dst_metrics_write_ptr(&rt->from->dst);
}

static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
Expand Down Expand Up @@ -391,7 +391,7 @@ static void ip6_dst_destroy(struct dst_entry *dst)
{
struct rt6_info *rt = (struct rt6_info *)dst;
struct rt6_exception_bucket *bucket;
struct dst_entry *from = dst->from;
struct rt6_info *from = rt->from;
struct inet6_dev *idev;

dst_destroy_metrics_generic(dst);
Expand All @@ -409,8 +409,8 @@ static void ip6_dst_destroy(struct dst_entry *dst)
kfree(bucket);
}

dst->from = NULL;
dst_release(from);
rt->from = NULL;
dst_release(&from->dst);
}

static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
Expand Down Expand Up @@ -443,9 +443,9 @@ static bool rt6_check_expired(const struct rt6_info *rt)
if (rt->rt6i_flags & RTF_EXPIRES) {
if (time_after(jiffies, rt->dst.expires))
return true;
} else if (rt->dst.from) {
} else if (rt->from) {
return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
rt6_check_expired((struct rt6_info *)rt->dst.from);
rt6_check_expired(rt->from);
}
return false;
}
Expand Down Expand Up @@ -1054,7 +1054,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
*/

if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
ort = (struct rt6_info *)ort->dst.from;
ort = ort->from;

rcu_read_lock();
dev = ip6_rt_get_dev_rcu(ort);
Expand Down Expand Up @@ -1274,7 +1274,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,

/* ort can't be a cache or pcpu route */
if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
ort = (struct rt6_info *)ort->dst.from;
ort = ort->from;
WARN_ON_ONCE(ort->rt6i_flags & (RTF_CACHE | RTF_PCPU));

spin_lock_bh(&rt6_exception_lock);
Expand Down Expand Up @@ -1415,8 +1415,8 @@ static struct rt6_info *rt6_find_cached_rt(struct rt6_info *rt,
/* Remove the passed in cached rt from the hash table that contains it */
int rt6_remove_exception_rt(struct rt6_info *rt)
{
struct rt6_info *from = (struct rt6_info *)rt->dst.from;
struct rt6_exception_bucket *bucket;
struct rt6_info *from = rt->from;
struct in6_addr *src_key = NULL;
struct rt6_exception *rt6_ex;
int err;
Expand Down Expand Up @@ -1460,8 +1460,8 @@ int rt6_remove_exception_rt(struct rt6_info *rt)
*/
static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
{
struct rt6_info *from = (struct rt6_info *)rt->dst.from;
struct rt6_exception_bucket *bucket;
struct rt6_info *from = rt->from;
struct in6_addr *src_key = NULL;
struct rt6_exception *rt6_ex;

Expand Down Expand Up @@ -1929,9 +1929,9 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori

static void rt6_dst_from_metrics_check(struct rt6_info *rt)
{
if (rt->dst.from &&
dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from))
dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true);
if (rt->from &&
dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(&rt->from->dst))
dst_init_metrics(&rt->dst, dst_metrics_ptr(&rt->from->dst), true);
}

static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
Expand All @@ -1951,7 +1951,7 @@ static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)
{
if (!__rt6_check_expired(rt) &&
rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
rt6_check((struct rt6_info *)(rt->dst.from), cookie))
rt6_check(rt->from, cookie))
return &rt->dst;
else
return NULL;
Expand All @@ -1971,7 +1971,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
rt6_dst_from_metrics_check(rt);

if (rt->rt6i_flags & RTF_PCPU ||
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from))
(unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
return rt6_dst_from_check(rt, cookie);
else
return rt6_check(rt, cookie);
Expand Down Expand Up @@ -3055,11 +3055,11 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu

static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
{
BUG_ON(from->dst.from);
BUG_ON(from->from);

rt->rt6i_flags &= ~RTF_EXPIRES;
dst_hold(&from->dst);
rt->dst.from = &from->dst;
rt->from = from;
dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
}

Expand Down

0 comments on commit 3a2232e

Please sign in to comment.