diff options
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 24 | 
1 files changed, 20 insertions, 4 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c8bc9b4ac328..826e6aa44f8d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -404,6 +404,14 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,  	}  } +static bool __rt6_check_expired(const struct rt6_info *rt) +{ +	if (rt->rt6i_flags & RTF_EXPIRES) +		return time_after(jiffies, rt->dst.expires); +	else +		return false; +} +  static bool rt6_check_expired(const struct rt6_info *rt)  {  	if (rt->rt6i_flags & RTF_EXPIRES) { @@ -515,7 +523,7 @@ static void rt6_probe_deferred(struct work_struct *w)  		container_of(w, struct __rt6_probe_work, work);  	addrconf_addr_solict_mult(&work->target, &mcaddr); -	ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, NULL); +	ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL);  	dev_put(work->dev);  	kfree(work);  } @@ -1252,7 +1260,8 @@ static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)  static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)  { -	if (rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK && +	if (!__rt6_check_expired(rt) && +	    rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&  	    rt6_check((struct rt6_info *)(rt->dst.from), cookie))  		return &rt->dst;  	else @@ -1272,7 +1281,8 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)  	rt6_dst_from_metrics_check(rt); -	if ((rt->rt6i_flags & RTF_PCPU) || unlikely(dst->flags & DST_NOCACHE)) +	if (rt->rt6i_flags & RTF_PCPU || +	    (unlikely(dst->flags & DST_NOCACHE) && rt->dst.from))  		return rt6_dst_from_check(rt, cookie);  	else  		return rt6_check(rt, cookie); @@ -1322,6 +1332,12 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)  	rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);  } +static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) +{ +	return !(rt->rt6i_flags & RTF_CACHE) && +		(rt->rt6i_flags & RTF_PCPU || rt->rt6i_node); +} +  static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,  				 const struct ipv6hdr *iph, u32 mtu)  { @@ -1335,7 +1351,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,  	if (mtu >= dst_mtu(dst))  		return; -	if (rt6->rt6i_flags & RTF_CACHE) { +	if (!rt6_cache_allowed_for_pmtu(rt6)) {  		rt6_do_update_pmtu(rt6, mtu);  	} else {  		const struct in6_addr *daddr, *saddr;  | 
