Re: [ 150/184] ipv4: check rt_genid in dst_check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2013-06-04 at 19:24 +0200, Willy Tarreau wrote:
> 2.6.32-longterm review patch.  If anyone has any objections, please let me know.
> 
> ------------------
> 
> From: Benjamin LaHaise <bcrl@xxxxxxxxx>
> 
> commit d11a4dc18bf41719c9f0d7ed494d295dd2973b92
> Author: Timo Ters <timo.teras@xxxxxx>
> Date:   Thu Mar 18 23:20:20 2010 +0000
> 
>     ipv4: check rt_genid in dst_check
> 
>     Xfrm_dst keeps a reference to ipv4 rtable entries on each
>     cached bundle. The only way to renew xfrm_dst when the underlying
>     route has changed, is to implement dst_check for this. This is
>     what ipv6 side does too.
> 
>     The problems started after 87c1e12b5eeb7b30b4b41291bef8e0b41fc3dde9
>     ("ipsec: Fix bogus bundle flowi") which fixed a bug causing xfrm_dst
>     to not get reused, until that all lookups always generated new
>     xfrm_dst with new route reference and path mtu worked. But after the
>     fix, the old routes started to get reused even after they were expired
>     causing pmtu to break (well it would occationally work if the rtable
>     gc had run recently and marked the route obsolete causing dst_check to
>     get called).
> 
>     Signed-off-by: Timo Teras <timo.teras@xxxxxx>
>     Acked-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
>     Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
> 
> This commit is based on the above, with the addition of verifying blackhole
> routes in the same manner.

That addition doesn't seem to correspond to anything in mainline.  Why
should 2.6.32 differ?

Ben.

> Signed-off-by: Benjamin LaHaise <bcrl@xxxxxxxxx>
> Signed-off-by: Willy Tarreau <w@xxxxxx>
> ---
>  net/ipv4/route.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 58f141b..f16d19b 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -1412,7 +1412,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
>  					dev_hold(rt->u.dst.dev);
>  				if (rt->idev)
>  					in_dev_hold(rt->idev);
> -				rt->u.dst.obsolete	= 0;
> +				rt->u.dst.obsolete	= -1;
>  				rt->u.dst.lastuse	= jiffies;
>  				rt->u.dst.path		= &rt->u.dst;
>  				rt->u.dst.neighbour	= NULL;
> @@ -1477,7 +1477,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
>  	struct dst_entry *ret = dst;
>  
>  	if (rt) {
> -		if (dst->obsolete) {
> +		if (dst->obsolete > 0) {
>  			ip_rt_put(rt);
>  			ret = NULL;
>  		} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
> @@ -1700,7 +1700,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
>  
>  static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
>  {
> -	return NULL;
> +	if (rt_is_expired((struct rtable *)dst))
> +		return NULL;
> +	return dst;
>  }
>  
>  static void ipv4_dst_destroy(struct dst_entry *dst)
> @@ -1862,7 +1864,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
>  	if (!rth)
>  		goto e_nobufs;
>  
> -	rth->u.dst.output= ip_rt_bug;
> +	rth->u.dst.output = ip_rt_bug;
> +	rth->u.dst.obsolete = -1;
>  
>  	atomic_set(&rth->u.dst.__refcnt, 1);
>  	rth->u.dst.flags= DST_HOST;
> @@ -2023,6 +2026,7 @@ static int __mkroute_input(struct sk_buff *skb,
>  	rth->fl.oif 	= 0;
>  	rth->rt_spec_dst= spec_dst;
>  
> +	rth->u.dst.obsolete = -1;
>  	rth->u.dst.input = ip_forward;
>  	rth->u.dst.output = ip_output;
>  	rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
> @@ -2187,6 +2191,7 @@ local_input:
>  		goto e_nobufs;
>  
>  	rth->u.dst.output= ip_rt_bug;
> +	rth->u.dst.obsolete = -1;
>  	rth->rt_genid = rt_genid(net);
>  
>  	atomic_set(&rth->u.dst.__refcnt, 1);
> @@ -2411,7 +2416,8 @@ static int __mkroute_output(struct rtable **result,
>  	rth->rt_gateway = fl->fl4_dst;
>  	rth->rt_spec_dst= fl->fl4_src;
>  
> -	rth->u.dst.output=ip_output;
> +	rth->u.dst.output = ip_output;
> +	rth->u.dst.obsolete = -1;
>  	rth->rt_genid = rt_genid(dev_net(dev_out));
>  
>  	RT_CACHE_STAT_INC(out_slow_tot);
> @@ -2741,6 +2747,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
>  	if (rt) {
>  		struct dst_entry *new = &rt->u.dst;
>  
> +		new->obsolete = -1;
>  		atomic_set(&new->__refcnt, 1);
>  		new->__use = 1;
>  		new->input = dst_discard;

-- 
Ben Hutchings
Theory and practice are closer in theory than in practice.
                                - John Levine, moderator of comp.compilers

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]