if the ipv6 dst cache copy from the dst witch generated by ICMPV6 RA packet.
this dst cache will not be checked expire because it has no RTF_EXPIRES flag
So this dst cache always be used until the dst gc run.
add a pointer in struct rt6_info,point to where the dst cache copy from.
in func rt6_check_expired check if rt6->info->rt6i_copy is expired.
Signed-off-by: Gao feng <redacted>
---
include/net/ip6_fib.h | 1 +
net/ipv6/route.c | 16 ++++++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index b26bb81..3da4d58c 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -106,6 +106,7 @@ struct rt6_info {
u32 rt6i_metric;
u32 rt6i_peer_genid;
+ struct rt6_info *rt6i_copy;
struct inet6_dev *rt6i_idev;
struct inet_peer *rt6i_peer;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8c2e3ab..939d06a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -316,8 +316,15 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
static __inline__ int rt6_check_expired(const struct rt6_info *rt)
{
- return (rt->rt6i_flags & RTF_EXPIRES) &&
- time_after(jiffies, rt->dst.expires);
+ if ((rt->rt6i_flags & RTF_EXPIRES) &&
+ time_after(jiffies, rt->dst.expires))
+ return 1;
+
+ if (rt->rt6i_copy && (rt->rt6i_copy->rt6i_flags & RTF_EXPIRES) &&
+ time_after(jiffies, rt->rt6i_copy->dst.expires))
+ return 1;
+
+ return 0;
}
static inline int rt6_need_strict(const struct in6_addr *daddr)@@ -1804,6 +1811,11 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
rt->rt6i_gateway = ort->rt6i_gateway;
rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
rt->rt6i_metric = 0;
+
+ if (ort->rt6i_copy)
+ rt->rt6i_copy = ort->rt6i_copy;
+ else
+ rt->rt6i_copy = ort;
#ifdef CONFIG_IPV6_SUBTREES
memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
--
1.7.5.4