Skip to content

Commit

Permalink
ipv4: check rt_genid in dst_check
Browse files Browse the repository at this point in the history
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 87c1e12
("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>
  • Loading branch information
Timo Teräs authored and David S. Miller committed Mar 20, 2010
1 parent 11bc308 commit d11a4dc
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,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;
Expand Down Expand Up @@ -1506,7 +1506,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) ||
Expand Down Expand Up @@ -1726,7 +1726,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)
Expand Down Expand Up @@ -1888,7 +1890,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;
Expand Down Expand Up @@ -2054,6 +2057,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));
Expand Down Expand Up @@ -2218,6 +2222,7 @@ out: return err;
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);
Expand Down Expand Up @@ -2444,6 +2449,7 @@ static int __mkroute_output(struct rtable **result,
rth->rt_spec_dst= fl->fl4_src;

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);
Expand Down

0 comments on commit d11a4dc

Please sign in to comment.