aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-03-18 19:20:20 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-20 00:00:41 -0400
commitd11a4dc18bf41719c9f0d7ed494d295dd2973b92 (patch)
tree654f7abdf27e1aeca25505896ead0e07664ee9fa
parent11bc3088373e913f165a8652601c6f8b8dc4aea2 (diff)
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@iki.fi> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/route.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a770df2493d2..32d396196df8 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1441,7 +1441,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1441 dev_hold(rt->u.dst.dev); 1441 dev_hold(rt->u.dst.dev);
1442 if (rt->idev) 1442 if (rt->idev)
1443 in_dev_hold(rt->idev); 1443 in_dev_hold(rt->idev);
1444 rt->u.dst.obsolete = 0; 1444 rt->u.dst.obsolete = -1;
1445 rt->u.dst.lastuse = jiffies; 1445 rt->u.dst.lastuse = jiffies;
1446 rt->u.dst.path = &rt->u.dst; 1446 rt->u.dst.path = &rt->u.dst;
1447 rt->u.dst.neighbour = NULL; 1447 rt->u.dst.neighbour = NULL;
@@ -1506,7 +1506,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1506 struct dst_entry *ret = dst; 1506 struct dst_entry *ret = dst;
1507 1507
1508 if (rt) { 1508 if (rt) {
1509 if (dst->obsolete) { 1509 if (dst->obsolete > 0) {
1510 ip_rt_put(rt); 1510 ip_rt_put(rt);
1511 ret = NULL; 1511 ret = NULL;
1512 } else if ((rt->rt_flags & RTCF_REDIRECTED) || 1512 } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
@@ -1726,7 +1726,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1726 1726
1727static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1727static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1728{ 1728{
1729 return NULL; 1729 if (rt_is_expired((struct rtable *)dst))
1730 return NULL;
1731 return dst;
1730} 1732}
1731 1733
1732static void ipv4_dst_destroy(struct dst_entry *dst) 1734static void ipv4_dst_destroy(struct dst_entry *dst)
@@ -1888,7 +1890,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1888 if (!rth) 1890 if (!rth)
1889 goto e_nobufs; 1891 goto e_nobufs;
1890 1892
1891 rth->u.dst.output= ip_rt_bug; 1893 rth->u.dst.output = ip_rt_bug;
1894 rth->u.dst.obsolete = -1;
1892 1895
1893 atomic_set(&rth->u.dst.__refcnt, 1); 1896 atomic_set(&rth->u.dst.__refcnt, 1);
1894 rth->u.dst.flags= DST_HOST; 1897 rth->u.dst.flags= DST_HOST;
@@ -2054,6 +2057,7 @@ static int __mkroute_input(struct sk_buff *skb,
2054 rth->fl.oif = 0; 2057 rth->fl.oif = 0;
2055 rth->rt_spec_dst= spec_dst; 2058 rth->rt_spec_dst= spec_dst;
2056 2059
2060 rth->u.dst.obsolete = -1;
2057 rth->u.dst.input = ip_forward; 2061 rth->u.dst.input = ip_forward;
2058 rth->u.dst.output = ip_output; 2062 rth->u.dst.output = ip_output;
2059 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); 2063 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2218,6 +2222,7 @@ local_input:
2218 goto e_nobufs; 2222 goto e_nobufs;
2219 2223
2220 rth->u.dst.output= ip_rt_bug; 2224 rth->u.dst.output= ip_rt_bug;
2225 rth->u.dst.obsolete = -1;
2221 rth->rt_genid = rt_genid(net); 2226 rth->rt_genid = rt_genid(net);
2222 2227
2223 atomic_set(&rth->u.dst.__refcnt, 1); 2228 atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2444,6 +2449,7 @@ static int __mkroute_output(struct rtable **result,
2444 rth->rt_spec_dst= fl->fl4_src; 2449 rth->rt_spec_dst= fl->fl4_src;
2445 2450
2446 rth->u.dst.output=ip_output; 2451 rth->u.dst.output=ip_output;
2452 rth->u.dst.obsolete = -1;
2447 rth->rt_genid = rt_genid(dev_net(dev_out)); 2453 rth->rt_genid = rt_genid(dev_net(dev_out));
2448 2454
2449 RT_CACHE_STAT_INC(out_slow_tot); 2455 RT_CACHE_STAT_INC(out_slow_tot);