Subject: Re: kern/3508 bug: cached ip route and interface up/down.
To: Tad Hunt <tad@entrisphere.com>
From: Nick Amato <naamato@nexthop.com>
List: tech-net
Date: 11/12/2002 17:32:18
On Tue, Nov 12, 2002 at 01:27:23PM -0800, Tad Hunt wrote:
> (...)
> Problem:
>  The ip stack, when forwarding a packet, in ip_forward(), makes use
>  of a cached route from a global variable called "ipforward_rt".
>  When the interface that route directs outbound packets toward goes
>  down the cached route is not cleared, so the packets don't get
>  re-routed.  When the interface comes back up, the packets still
>  don't get delivered to it.

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.

A program such as gated(8) watches for interface changes like this, and
will update e.g. static routes as necessary.  So in this case, without
alternate paths available, when ifc1 goes down, the route is deleted.
When it comes back up, the route is re-added.  At this point ip_output()
notices that the cached route is dead and fetches the new route.

Nick


>  Hmm. I just looked in the PR database.  This appears to be
>  a longstanding problem.  der Mouse reported PR3508, which is
>  the same problem, way back in 1997.  As he said then, I believe
>  this is still a problem in NetBSD-current.
> 
> To Fix:
>  I put in a call in if_down() and if_up() to free the cached route.
>  The next time a packet is received, the route will be reallocated
>  and everything will be happy.  This is just a hack to see if I'm
>  on the right track.  However, PR3508 points out more ways that
>  the cached route can be wrong.  I'm inclined to follow der Mouse's
>  lead and get rid of the cached route entirely.
>
> To Reproduce:
> 
> 	Client1 <----> NetBSD Router <----> Client2
>                     ifc0           ifc1
> 
>  1) Setup a NetBSD router with at least two interfaces (ifc0, ifc1)
>     as above.
> 
>  2) Configure a default route on ifc0, and a route to Client2
>     on ifc1.
> 
>  3) In the absence of any other traffic to be forwarded, ping
>     Client2 from Client1. (The cached route is cleared whenever a
>     packet for a different destination arrives)
> 
>  4) ifconfig ifc1 down
> 
>  5) notice the ping stops receiving the echo reply.
> 
>  6) ifconfig ifc1 up
> 
>  7) notice the ping still doesn't receive the echo reply.
> 
>  8) without stopping the first ping, ping another address which
>     the router will also forward (doesn't have to respond)
> 
>  9) notice the first ping starts working again