Skip to content

Commit d11a4dc

Browse files
fableddavem330
authored andcommitted
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 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>
1 parent 11bc308 commit d11a4dc

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

net/ipv4/route.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
14411441
dev_hold(rt->u.dst.dev);
14421442
if (rt->idev)
14431443
in_dev_hold(rt->idev);
1444-
rt->u.dst.obsolete = 0;
1444+
rt->u.dst.obsolete = -1;
14451445
rt->u.dst.lastuse = jiffies;
14461446
rt->u.dst.path = &rt->u.dst;
14471447
rt->u.dst.neighbour = NULL;
@@ -1506,7 +1506,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
15061506
struct dst_entry *ret = dst;
15071507

15081508
if (rt) {
1509-
if (dst->obsolete) {
1509+
if (dst->obsolete > 0) {
15101510
ip_rt_put(rt);
15111511
ret = NULL;
15121512
} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
@@ -1726,7 +1726,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
17261726

17271727
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
17281728
{
1729-
return NULL;
1729+
if (rt_is_expired((struct rtable *)dst))
1730+
return NULL;
1731+
return dst;
17301732
}
17311733

17321734
static 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,
18881890
if (!rth)
18891891
goto e_nobufs;
18901892

1891-
rth->u.dst.output= ip_rt_bug;
1893+
rth->u.dst.output = ip_rt_bug;
1894+
rth->u.dst.obsolete = -1;
18921895

18931896
atomic_set(&rth->u.dst.__refcnt, 1);
18941897
rth->u.dst.flags= DST_HOST;
@@ -2054,6 +2057,7 @@ static int __mkroute_input(struct sk_buff *skb,
20542057
rth->fl.oif = 0;
20552058
rth->rt_spec_dst= spec_dst;
20562059

2060+
rth->u.dst.obsolete = -1;
20572061
rth->u.dst.input = ip_forward;
20582062
rth->u.dst.output = ip_output;
20592063
rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2218,6 +2222,7 @@ out: return err;
22182222
goto e_nobufs;
22192223

22202224
rth->u.dst.output= ip_rt_bug;
2225+
rth->u.dst.obsolete = -1;
22212226
rth->rt_genid = rt_genid(net);
22222227

22232228
atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2444,6 +2449,7 @@ static int __mkroute_output(struct rtable **result,
24442449
rth->rt_spec_dst= fl->fl4_src;
24452450

24462451
rth->u.dst.output=ip_output;
2452+
rth->u.dst.obsolete = -1;
24472453
rth->rt_genid = rt_genid(dev_net(dev_out));
24482454

24492455
RT_CACHE_STAT_INC(out_slow_tot);

0 commit comments

Comments
 (0)