ipv6: Move dst->from into struct rt6_info.
authorDavid Miller <davem@davemloft.net>
Tue, 28 Nov 2017 20:40:40 +0000 (15:40 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Nov 2017 14:54:26 +0000 (09:54 -0500)
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>
include/net/dst.h
include/net/ip6_fib.h
net/core/dst.c
net/ipv6/route.c

index cef46207408c9ac290db3590034a9c0cde46df3e..13c839d8235ad75ecca1b0b2d7bda595cd3a03d4 100644 (file)
@@ -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
@@ -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
index 281a922f0c62999a39d2af84e12f1046be1f7da0..44d96a91e74516c4e8b487603a15489245d0da58 100644 (file)
@@ -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.)
@@ -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;
 }
@@ -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);
 
index 5cf96179e8e0bc863a9d9befb59e1844d9920975..cf2076c0eb220de98090534ee551333a792a08e8 100644 (file)
@@ -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
index 22c5e70361d696cd46be7818d0a7ea275f3ef349..1f1ef1e071c2f5a1e3b0e7104280da9c2838ff80 100644 (file)
@@ -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)
@@ -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);
@@ -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,
@@ -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;
 }
@@ -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);
@@ -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);
@@ -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;
@@ -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;
 
@@ -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)
@@ -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;
@@ -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);
@@ -3055,11 +3055,11 @@ out:
 
 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);
 }