summaryrefslogtreecommitdiff
path: root/include/net/ip6_fib.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/ip6_fib.h')
-rw-r--r--include/net/ip6_fib.h39
1 files changed, 27 insertions, 12 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 28d27a6..fdc48a9 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -166,35 +166,50 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
static inline void rt6_clean_expires(struct rt6_info *rt)
{
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
rt->rt6i_flags &= ~RTF_EXPIRES;
+ rt->dst.from = NULL;
}
static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
{
- rt->dst.expires = expires;
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
rt->rt6i_flags |= RTF_EXPIRES;
+ rt->dst.expires = expires;
}
-static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
+static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
{
- struct rt6_info *rt;
-
- for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
- rt = (struct rt6_info *)rt->dst.from);
- if (rt && rt != rt0)
- rt0->dst.expires = rt->dst.expires;
-
- dst_set_expires(&rt0->dst, timeout);
- rt0->rt6i_flags |= RTF_EXPIRES;
+ if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+ if (rt->dst.from)
+ dst_release(rt->dst.from);
+ /* dst_set_expires relies on expires == 0
+ * if it has not been set previously.
+ */
+ rt->dst.expires = 0;
+ }
+
+ dst_set_expires(&rt->dst, timeout);
+ rt->rt6i_flags |= RTF_EXPIRES;
}
static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
{
struct dst_entry *new = (struct dst_entry *) from;
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
+ if (new == rt->dst.from)
+ return;
+ dst_release(rt->dst.from);
+ }
+
rt->rt6i_flags &= ~RTF_EXPIRES;
- dst_hold(new);
rt->dst.from = new;
+ dst_hold(new);
}
static inline void ip6_rt_put(struct rt6_info *rt)