aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-03-18 19:20:20 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 19:02:07 -0400
commit0a8c3637ba3ae76b6454e4199f6e0a46282a5e8d (patch)
tree1cf468742e891583ac8c4c09394ac7a444530d23 /net
parent9f24b75bf551b5f343159da229ce734da380431b (diff)
ipv4: check rt_genid in dst_check
[ Upstream commit d11a4dc18bf41719c9f0d7ed494d295dd2973b92 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to '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 555d27873e03..98656bca1e47 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1415,7 +1415,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1415 dev_hold(rt->u.dst.dev); 1415 dev_hold(rt->u.dst.dev);
1416 if (rt->idev) 1416 if (rt->idev)
1417 in_dev_hold(rt->idev); 1417 in_dev_hold(rt->idev);
1418 rt->u.dst.obsolete = 0; 1418 rt->u.dst.obsolete = -1;
1419 rt->u.dst.lastuse = jiffies; 1419 rt->u.dst.lastuse = jiffies;
1420 rt->u.dst.path = &rt->u.dst; 1420 rt->u.dst.path = &rt->u.dst;
1421 rt->u.dst.neighbour = NULL; 1421 rt->u.dst.neighbour = NULL;
@@ -1480,7 +1480,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1480 struct dst_entry *ret = dst; 1480 struct dst_entry *ret = dst;
1481 1481
1482 if (rt) { 1482 if (rt) {
1483 if (dst->obsolete) { 1483 if (dst->obsolete > 0) {
1484 ip_rt_put(rt); 1484 ip_rt_put(rt);
1485 ret = NULL; 1485 ret = NULL;
1486 } else if ((rt->rt_flags & RTCF_REDIRECTED) || 1486 } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
@@ -1700,7 +1700,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1700 1700
1701static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1701static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1702{ 1702{
1703 return NULL; 1703 if (rt_is_expired((struct rtable *)dst))
1704 return NULL;
1705 return dst;
1704} 1706}
1705 1707
1706static void ipv4_dst_destroy(struct dst_entry *dst) 1708static 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,
1862 if (!rth) 1864 if (!rth)
1863 goto e_nobufs; 1865 goto e_nobufs;
1864 1866
1865 rth->u.dst.output= ip_rt_bug; 1867 rth->u.dst.output = ip_rt_bug;
1868 rth->u.dst.obsolete = -1;
1866 1869
1867 atomic_set(&rth->u.dst.__refcnt, 1); 1870 atomic_set(&rth->u.dst.__refcnt, 1);
1868 rth->u.dst.flags= DST_HOST; 1871 rth->u.dst.flags= DST_HOST;
@@ -2023,6 +2026,7 @@ static int __mkroute_input(struct sk_buff *skb,
2023 rth->fl.oif = 0; 2026 rth->fl.oif = 0;
2024 rth->rt_spec_dst= spec_dst; 2027 rth->rt_spec_dst= spec_dst;
2025 2028
2029 rth->u.dst.obsolete = -1;
2026 rth->u.dst.input = ip_forward; 2030 rth->u.dst.input = ip_forward;
2027 rth->u.dst.output = ip_output; 2031 rth->u.dst.output = ip_output;
2028 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); 2032 rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2187,6 +2191,7 @@ local_input:
2187 goto e_nobufs; 2191 goto e_nobufs;
2188 2192
2189 rth->u.dst.output= ip_rt_bug; 2193 rth->u.dst.output= ip_rt_bug;
2194 rth->u.dst.obsolete = -1;
2190 rth->rt_genid = rt_genid(net); 2195 rth->rt_genid = rt_genid(net);
2191 2196
2192 atomic_set(&rth->u.dst.__refcnt, 1); 2197 atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2413,6 +2418,7 @@ static int __mkroute_output(struct rtable **result,
2413 rth->rt_spec_dst= fl->fl4_src; 2418 rth->rt_spec_dst= fl->fl4_src;
2414 2419
2415 rth->u.dst.output=ip_output; 2420 rth->u.dst.output=ip_output;
2421 rth->u.dst.obsolete = -1;
2416 rth->rt_genid = rt_genid(dev_net(dev_out)); 2422 rth->rt_genid = rt_genid(dev_net(dev_out));
2417 2423
2418 RT_CACHE_STAT_INC(out_slow_tot); 2424 RT_CACHE_STAT_INC(out_slow_tot);