summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2017-11-28 15:40:40 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-30 09:54:26 -0500
commit3a2232e92e87166a8a5113e918b8c7b7bdce4d83 (patch)
treed4bea5d4b31fe38dde724e8eb102038438f17f36
parentb6ca8bd5a9198c70c48297390723e4e56bd6e879 (diff)
ipv6: Move dst->from into struct rt6_info.
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>
-rw-r--r--include/net/dst.h3
-rw-r--r--include/net/ip6_fib.h9
-rw-r--r--net/core/dst.c1
-rw-r--r--net/ipv6/route.c34
4 files changed, 22 insertions, 25 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index cef46207408c..13c839d8235a 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -39,7 +39,6 @@ struct dst_entry {
39 unsigned long _metrics; 39 unsigned long _metrics;
40 unsigned long expires; 40 unsigned long expires;
41 struct dst_entry *path; 41 struct dst_entry *path;
42 struct dst_entry *from;
43#ifdef CONFIG_XFRM 42#ifdef CONFIG_XFRM
44 struct xfrm_state *xfrm; 43 struct xfrm_state *xfrm;
45#else 44#else
@@ -88,7 +87,7 @@ struct dst_entry {
88 * Align __refcnt to a 64 bytes alignment 87 * Align __refcnt to a 64 bytes alignment
89 * (L1_CACHE_SIZE would be too much) 88 * (L1_CACHE_SIZE would be too much)
90 */ 89 */
91 long __pad_to_align_refcnt[3]; 90 long __pad_to_align_refcnt[4];
92#endif 91#endif
93 /* 92 /*
94 * __refcnt wants to be on a different cache line from 93 * __refcnt wants to be on a different cache line from
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 281a922f0c62..44d96a91e745 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -130,6 +130,7 @@ struct rt6_exception {
130struct rt6_info { 130struct rt6_info {
131 struct dst_entry dst; 131 struct dst_entry dst;
132 struct rt6_info __rcu *rt6_next; 132 struct rt6_info __rcu *rt6_next;
133 struct rt6_info *from;
133 134
134 /* 135 /*
135 * Tail elements of dst_entry (__refcnt etc.) 136 * Tail elements of dst_entry (__refcnt etc.)
@@ -204,11 +205,9 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
204{ 205{
205 struct rt6_info *rt; 206 struct rt6_info *rt;
206 207
207 for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); 208 for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES); rt = rt->from);
208 rt = (struct rt6_info *)rt->dst.from);
209 if (rt && rt != rt0) 209 if (rt && rt != rt0)
210 rt0->dst.expires = rt->dst.expires; 210 rt0->dst.expires = rt->dst.expires;
211
212 dst_set_expires(&rt0->dst, timeout); 211 dst_set_expires(&rt0->dst, timeout);
213 rt0->rt6i_flags |= RTF_EXPIRES; 212 rt0->rt6i_flags |= RTF_EXPIRES;
214} 213}
@@ -243,8 +242,8 @@ static inline u32 rt6_get_cookie(const struct rt6_info *rt)
243 u32 cookie = 0; 242 u32 cookie = 0;
244 243
245 if (rt->rt6i_flags & RTF_PCPU || 244 if (rt->rt6i_flags & RTF_PCPU ||
246 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from)) 245 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
247 rt = (struct rt6_info *)(rt->dst.from); 246 rt = rt->from;
248 247
249 rt6_get_cookie_safe(rt, &cookie); 248 rt6_get_cookie_safe(rt, &cookie);
250 249
diff --git a/net/core/dst.c b/net/core/dst.c
index 5cf96179e8e0..cf2076c0eb22 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -70,7 +70,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
70 dst_init_metrics(dst, dst_default_metrics.metrics, true); 70 dst_init_metrics(dst, dst_default_metrics.metrics, true);
71 dst->expires = 0UL; 71 dst->expires = 0UL;
72 dst->path = dst; 72 dst->path = dst;
73 dst->from = NULL;
74#ifdef CONFIG_XFRM 73#ifdef CONFIG_XFRM
75 dst->xfrm = NULL; 74 dst->xfrm = NULL;
76#endif 75#endif
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 22c5e70361d6..1f1ef1e071c2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -186,7 +186,7 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
186 186
187static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt) 187static u32 *rt6_pcpu_cow_metrics(struct rt6_info *rt)
188{ 188{
189 return dst_metrics_write_ptr(rt->dst.from); 189 return dst_metrics_write_ptr(&rt->from->dst);
190} 190}
191 191
192static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) 192static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
@@ -391,7 +391,7 @@ static void ip6_dst_destroy(struct dst_entry *dst)
391{ 391{
392 struct rt6_info *rt = (struct rt6_info *)dst; 392 struct rt6_info *rt = (struct rt6_info *)dst;
393 struct rt6_exception_bucket *bucket; 393 struct rt6_exception_bucket *bucket;
394 struct dst_entry *from = dst->from; 394 struct rt6_info *from = rt->from;
395 struct inet6_dev *idev; 395 struct inet6_dev *idev;
396 396
397 dst_destroy_metrics_generic(dst); 397 dst_destroy_metrics_generic(dst);
@@ -409,8 +409,8 @@ static void ip6_dst_destroy(struct dst_entry *dst)
409 kfree(bucket); 409 kfree(bucket);
410 } 410 }
411 411
412 dst->from = NULL; 412 rt->from = NULL;
413 dst_release(from); 413 dst_release(&from->dst);
414} 414}
415 415
416static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, 416static 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)
443 if (rt->rt6i_flags & RTF_EXPIRES) { 443 if (rt->rt6i_flags & RTF_EXPIRES) {
444 if (time_after(jiffies, rt->dst.expires)) 444 if (time_after(jiffies, rt->dst.expires))
445 return true; 445 return true;
446 } else if (rt->dst.from) { 446 } else if (rt->from) {
447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK || 447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
448 rt6_check_expired((struct rt6_info *)rt->dst.from); 448 rt6_check_expired(rt->from);
449 } 449 }
450 return false; 450 return false;
451} 451}
@@ -1054,7 +1054,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
1054 */ 1054 */
1055 1055
1056 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) 1056 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
1057 ort = (struct rt6_info *)ort->dst.from; 1057 ort = ort->from;
1058 1058
1059 rcu_read_lock(); 1059 rcu_read_lock();
1060 dev = ip6_rt_get_dev_rcu(ort); 1060 dev = ip6_rt_get_dev_rcu(ort);
@@ -1274,7 +1274,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,
1274 1274
1275 /* ort can't be a cache or pcpu route */ 1275 /* ort can't be a cache or pcpu route */
1276 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) 1276 if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
1277 ort = (struct rt6_info *)ort->dst.from; 1277 ort = ort->from;
1278 WARN_ON_ONCE(ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)); 1278 WARN_ON_ONCE(ort->rt6i_flags & (RTF_CACHE | RTF_PCPU));
1279 1279
1280 spin_lock_bh(&rt6_exception_lock); 1280 spin_lock_bh(&rt6_exception_lock);
@@ -1415,8 +1415,8 @@ static struct rt6_info *rt6_find_cached_rt(struct rt6_info *rt,
1415/* Remove the passed in cached rt from the hash table that contains it */ 1415/* Remove the passed in cached rt from the hash table that contains it */
1416int rt6_remove_exception_rt(struct rt6_info *rt) 1416int rt6_remove_exception_rt(struct rt6_info *rt)
1417{ 1417{
1418 struct rt6_info *from = (struct rt6_info *)rt->dst.from;
1419 struct rt6_exception_bucket *bucket; 1418 struct rt6_exception_bucket *bucket;
1419 struct rt6_info *from = rt->from;
1420 struct in6_addr *src_key = NULL; 1420 struct in6_addr *src_key = NULL;
1421 struct rt6_exception *rt6_ex; 1421 struct rt6_exception *rt6_ex;
1422 int err; 1422 int err;
@@ -1460,8 +1460,8 @@ int rt6_remove_exception_rt(struct rt6_info *rt)
1460 */ 1460 */
1461static void rt6_update_exception_stamp_rt(struct rt6_info *rt) 1461static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
1462{ 1462{
1463 struct rt6_info *from = (struct rt6_info *)rt->dst.from;
1464 struct rt6_exception_bucket *bucket; 1463 struct rt6_exception_bucket *bucket;
1464 struct rt6_info *from = rt->from;
1465 struct in6_addr *src_key = NULL; 1465 struct in6_addr *src_key = NULL;
1466 struct rt6_exception *rt6_ex; 1466 struct rt6_exception *rt6_ex;
1467 1467
@@ -1929,9 +1929,9 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
1929 1929
1930static void rt6_dst_from_metrics_check(struct rt6_info *rt) 1930static void rt6_dst_from_metrics_check(struct rt6_info *rt)
1931{ 1931{
1932 if (rt->dst.from && 1932 if (rt->from &&
1933 dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(rt->dst.from)) 1933 dst_metrics_ptr(&rt->dst) != dst_metrics_ptr(&rt->from->dst))
1934 dst_init_metrics(&rt->dst, dst_metrics_ptr(rt->dst.from), true); 1934 dst_init_metrics(&rt->dst, dst_metrics_ptr(&rt->from->dst), true);
1935} 1935}
1936 1936
1937static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie) 1937static 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)
1951{ 1951{
1952 if (!__rt6_check_expired(rt) && 1952 if (!__rt6_check_expired(rt) &&
1953 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && 1953 rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
1954 rt6_check((struct rt6_info *)(rt->dst.from), cookie)) 1954 rt6_check(rt->from, cookie))
1955 return &rt->dst; 1955 return &rt->dst;
1956 else 1956 else
1957 return NULL; 1957 return NULL;
@@ -1971,7 +1971,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1971 rt6_dst_from_metrics_check(rt); 1971 rt6_dst_from_metrics_check(rt);
1972 1972
1973 if (rt->rt6i_flags & RTF_PCPU || 1973 if (rt->rt6i_flags & RTF_PCPU ||
1974 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->dst.from)) 1974 (unlikely(!list_empty(&rt->rt6i_uncached)) && rt->from))
1975 return rt6_dst_from_check(rt, cookie); 1975 return rt6_dst_from_check(rt, cookie);
1976 else 1976 else
1977 return rt6_check(rt, cookie); 1977 return rt6_check(rt, cookie);
@@ -3055,11 +3055,11 @@ out:
3055 3055
3056static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) 3056static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
3057{ 3057{
3058 BUG_ON(from->dst.from); 3058 BUG_ON(from->from);
3059 3059
3060 rt->rt6i_flags &= ~RTF_EXPIRES; 3060 rt->rt6i_flags &= ~RTF_EXPIRES;
3061 dst_hold(&from->dst); 3061 dst_hold(&from->dst);
3062 rt->dst.from = &from->dst; 3062 rt->from = from;
3063 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true); 3063 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
3064} 3064}
3065 3065