diff options
-rw-r--r-- | include/net/dst.h | 8 | ||||
-rw-r--r-- | include/net/ip6_fib.h | 39 | ||||
-rw-r--r-- | net/core/dst.c | 1 | ||||
-rw-r--r-- | net/ipv6/route.c | 8 |
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 | ||
165 | static inline void rt6_clean_expires(struct rt6_info *rt) | 165 | static 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 | ||
174 | static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) | 170 | static 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 | ||
183 | static inline void rt6_update_expires(struct rt6_info *rt, int timeout) | 176 | static 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 | ||
198 | static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) | 189 | static 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 | ||
213 | static inline void ip6_rt_put(struct rt6_info *rt) | 198 | static 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 |