aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/dst.h8
-rw-r--r--include/net/ip6_fib.h39
-rw-r--r--net/core/dst.c1
-rw-r--r--net/ipv6/route.c8
4 files changed, 18 insertions, 38 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 3da47e0a4a1f..853cda11e518 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -36,13 +36,9 @@ struct dst_entry {
36 struct net_device *dev; 36 struct net_device *dev;
37 struct dst_ops *ops; 37 struct dst_ops *ops;
38 unsigned long _metrics; 38 unsigned long _metrics;
39 union { 39 unsigned long expires;
40 unsigned long expires;
41 /* point to where the dst_entry copied from */
42 struct dst_entry *from;
43 };
44 struct dst_entry *path; 40 struct dst_entry *path;
45 void *__pad0; 41 struct dst_entry *from;
46#ifdef CONFIG_XFRM 42#ifdef CONFIG_XFRM
47 struct xfrm_state *xfrm; 43 struct xfrm_state *xfrm;
48#else 44#else
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 6919a501f99e..2a601e7da1bf 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -164,50 +164,35 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
164 164
165static inline void rt6_clean_expires(struct rt6_info *rt) 165static inline void rt6_clean_expires(struct rt6_info *rt)
166{ 166{
167 if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
168 dst_release(rt->dst.from);
169
170 rt->rt6i_flags &= ~RTF_EXPIRES; 167 rt->rt6i_flags &= ~RTF_EXPIRES;
171 rt->dst.from = NULL;
172} 168}
173 169
174static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) 170static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
175{ 171{
176 if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
177 dst_release(rt->dst.from);
178
179 rt->rt6i_flags |= RTF_EXPIRES;
180 rt->dst.expires = expires; 172 rt->dst.expires = expires;
173 rt->rt6i_flags |= RTF_EXPIRES;
181} 174}
182 175
183static inline void rt6_update_expires(struct rt6_info *rt, int timeout) 176static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
184{ 177{
185 if (!(rt->rt6i_flags & RTF_EXPIRES)) { 178 struct rt6_info *rt;
186 if (rt->dst.from) 179
187 dst_release(rt->dst.from); 180 for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
188 /* dst_set_expires relies on expires == 0 181 rt = (struct rt6_info *)rt->dst.from);
189 * if it has not been set previously. 182 if (rt && rt != rt0)
190 */ 183 rt0->dst.expires = rt->dst.expires;
191 rt->dst.expires = 0; 184
192 } 185 dst_set_expires(&rt0->dst, timeout);
193 186 rt0->rt6i_flags |= RTF_EXPIRES;
194 dst_set_expires(&rt->dst, timeout);
195 rt->rt6i_flags |= RTF_EXPIRES;
196} 187}
197 188
198static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) 189static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
199{ 190{
200 struct dst_entry *new = (struct dst_entry *) from; 191 struct dst_entry *new = (struct dst_entry *) from;
201 192
202 if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
203 if (new == rt->dst.from)
204 return;
205 dst_release(rt->dst.from);
206 }
207
208 rt->rt6i_flags &= ~RTF_EXPIRES; 193 rt->rt6i_flags &= ~RTF_EXPIRES;
209 rt->dst.from = new;
210 dst_hold(new); 194 dst_hold(new);
195 rt->dst.from = new;
211} 196}
212 197
213static inline void ip6_rt_put(struct rt6_info *rt) 198static inline void ip6_rt_put(struct rt6_info *rt)
diff --git a/net/core/dst.c b/net/core/dst.c
index ee6153e2cf43..35fd12f1a69c 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -179,6 +179,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
179 dst_init_metrics(dst, dst_default_metrics, true); 179 dst_init_metrics(dst, dst_default_metrics, true);
180 dst->expires = 0UL; 180 dst->expires = 0UL;
181 dst->path = dst; 181 dst->path = dst;
182 dst->from = NULL;
182#ifdef CONFIG_XFRM 183#ifdef CONFIG_XFRM
183 dst->xfrm = NULL; 184 dst->xfrm = NULL;
184#endif 185#endif
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 515bb51e05a8..928266569689 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -287,6 +287,7 @@ static void ip6_dst_destroy(struct dst_entry *dst)
287{ 287{
288 struct rt6_info *rt = (struct rt6_info *)dst; 288 struct rt6_info *rt = (struct rt6_info *)dst;
289 struct inet6_dev *idev = rt->rt6i_idev; 289 struct inet6_dev *idev = rt->rt6i_idev;
290 struct dst_entry *from = dst->from;
290 291
291 if (!(rt->dst.flags & DST_HOST)) 292 if (!(rt->dst.flags & DST_HOST))
292 dst_destroy_metrics_generic(dst); 293 dst_destroy_metrics_generic(dst);
@@ -296,8 +297,8 @@ static void ip6_dst_destroy(struct dst_entry *dst)
296 in6_dev_put(idev); 297 in6_dev_put(idev);
297 } 298 }
298 299
299 if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) 300 dst->from = NULL;
300 dst_release(dst->from); 301 dst_release(from);
301 302
302 if (rt6_has_peer(rt)) { 303 if (rt6_has_peer(rt)) {
303 struct inet_peer *peer = rt6_peer_ptr(rt); 304 struct inet_peer *peer = rt6_peer_ptr(rt);
@@ -1010,7 +1011,6 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
1010 1011
1011 rt->rt6i_gateway = ort->rt6i_gateway; 1012 rt->rt6i_gateway = ort->rt6i_gateway;
1012 rt->rt6i_flags = ort->rt6i_flags; 1013 rt->rt6i_flags = ort->rt6i_flags;
1013 rt6_clean_expires(rt);
1014 rt->rt6i_metric = 0; 1014 rt->rt6i_metric = 0;
1015 1015
1016 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); 1016 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -1784,8 +1784,6 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
1784 if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == 1784 if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
1785 (RTF_DEFAULT | RTF_ADDRCONF)) 1785 (RTF_DEFAULT | RTF_ADDRCONF))
1786 rt6_set_from(rt, ort); 1786 rt6_set_from(rt, ort);
1787 else
1788 rt6_clean_expires(rt);
1789 rt->rt6i_metric = 0; 1787 rt->rt6i_metric = 0;
1790 1788
1791#ifdef CONFIG_IPV6_SUBTREES 1789#ifdef CONFIG_IPV6_SUBTREES