diff -purNa linux-2.6.3-usagi/net/ipv6/ip6_fib.c linux-2.6.3-rtexpiry/net/ipv6/ip6_fib.c --- linux-2.6.3-usagi/net/ipv6/ip6_fib.c 2004-02-19 17:10:55.000000000 +0100 +++ linux-2.6.3-rtexpiry/net/ipv6/ip6_fib.c 2004-02-20 12:41:49.000000000 +0100 @@ -493,6 +493,10 @@ out: static __inline__ void fib6_start_gc(struct rt6_info *rt) { + if ((rt->rt6i_flags & RTF_EXPIRES) && rt->rt6i_expires && + rt->rt6i_expires < ip6_fib_timer.expires) { + mod_timer(&ip6_fib_timer, rt->rt6i_expires); + } else if (ip6_fib_timer.expires == 0 && (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); @@ -504,6 +508,14 @@ void fib6_force_start_gc(void) mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); } +void fib6_update_expiry(struct rt6_info *rt, unsigned int lifetime) +{ + rt->rt6i_expires = jiffies + (HZ * lifetime); + rt->rt6i_flags |= RTF_EXPIRES; + /* Make sure we do a GC when this router expires */ + fib6_start_gc(rt); +} + /* * Add routing information to the routing tree. * / @@ -1128,6 +1140,7 @@ static int fib6_clean_node(struct fib6_w for (rt = w->leaf; rt; rt = rt->u.next) { res = c->func(rt, c->arg); if (res < 0) { + rt->u.dst.error = -ENETUNREACH; w->leaf = rt; res = fib6_del(rt, NULL, NULL); if (res) { @@ -1208,7 +1221,7 @@ static int fib6_age(struct rt6_info *rt, */ if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) { - if (time_after(now, rt->rt6i_expires)) { + if (time_after_eq(now, rt->rt6i_expires)) { RT6_TRACE("expiring %p\n", rt); return -1; } diff -purNa linux-2.6.3-usagi/net/ipv6/ndisc.c linux-2.6.3-rtexpiry/net/ipv6/ndisc.c --- linux-2.6.3-usagi/net/ipv6/ndisc.c 2004-02-19 17:10:55.000000000 +0100 +++ linux-2.6.3-rtexpiry/net/ipv6/ndisc.c 2004-02-20 12:41:06.000000000 +0100 @@ -912,8 +912,11 @@ static void ndisc_recv_na(struct sk_buff */ struct rt6_info *rt; rt = rt6_get_dflt_router(saddr, dev); - if (rt) + if (rt) { + /* Mark as expired (may be in use elsewhere) */ + rt->rt6i_expires = jiffies - 1; ip6_del_rt(rt, NULL, NULL); + } } #else if (neigh->flags & NTF_ROUTER) { @@ -1111,7 +1114,7 @@ static void ndisc_router_discovery(struc } if (rt) - rt->rt6i_expires = jiffies + (HZ * lifetime); + fib6_update_expiry(rt, lifetime); if (ra_msg->icmph.icmp6_hop_limit) in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; diff -purNa linux-2.6.3-usagi/net/ipv6/route.c linux-2.6.3-rtexpiry/net/ipv6/route.c --- linux-2.6.3-usagi/net/ipv6/route.c 2004-02-19 17:10:55.000000000 +0100 +++ linux-2.6.3-rtexpiry/net/ipv6/route.c 2004-02-20 12:41:06.000000000 +0100 @@ -183,6 +183,10 @@ static struct rt6_info *rt6_best_dflt(st struct neighbour *neigh; int m = 0; + /* Skip expired routers */ + if ((sprt->rt6i_flags & RTF_EXPIRES) && time_after(jiffies, sprt->rt6i_expires)) + continue; + if (!oif || (sprt->rt6i_dev && sprt->rt6i_dev->ifindex == oif))