Subject: Re: kern/3508 bug: cached ip route and interface up/down.
To: der Mouse <mouse@rodents.montreal.qc.ca>
From: Nick Amato <naamato@nexthop.com>
List: tech-kern
Date: 11/12/2002 19:15:52
On Tue, Nov 12, 2002 at 11:42:54PM +0100, der Mouse wrote:
> >>  The ip stack, when forwarding a packet, in ip_forward(), makes use
> >>  of a cached route from a global variable called "ipforward_rt".
> 
> > It's been pointed out on current-users that the kernel is
> > "simple-minded" about routing.  In your case, if the interface a
> > route was using goes down, it's still up to a userland program to
> > reroute the traffic by changing the table.
> 
> It's worse than that: even if userland _does_ change the routing table,
> it doesn't affect routing until the kernel wants to forward a packet to
> some other address.  Check out PR 3508.
> 
> You write that
> 
> > At this point ip_output() notices that the cached route is dead and
> > fetches the new route.
> 
> I just had a look at -current's ip_output and I think what it does
> isn't enough:
> 
>         /*
>          * If there is a cached route,
>          * check that it is to the same destination
>          * and is still up.  If not, free it and try again.
>          * The address family should also be checked in case of sharing the
>          * cache with IPv6.
>          */
> 
> The last two lines appear to be out of date, but the rest looks right:
> 
>         if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
>             dst->sin_family != AF_INET ||
>             !in_hosteq(dst->sin_addr, ip->ip_dst))) {
> 
> This won't fix anything in the scenario outlined in PR 3508.

Yes, it is true.  A routing daemon cannot fix the problems in PR 3508.

However, as long as there is an absence of an alternate route (i.e. default)
while a destination is unreachable, it still works.  When a route is deleted
and added the old route has RTF_UP reset and the new route will be rtalloc'd
in ip_output().

Not very useful.  It seems to me that what needs to happen is to clear the
cache whenever a more specific route than the cached route is added to
the table.  I don't know how practical this is.

Nick