Bug 74 - Redundant routing table lookup for setting src addr of outoging IP packets
: Redundant routing table lookup for setting src addr of outoging IP packets
Status: RESOLVED FIXED
: ns-3
internet-stack
: pre-release
: PC Linux
: P2 minor
Assigned To:
:
:
:
: 115
  Show dependency treegraph
 
Reported: 2007-09-13 06:05 EDT by
Modified: 2009-05-29 17:27 EDT (History)


Attachments


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2007-09-13 06:05:21 EDT
The problem and possible solution is described in the first point in
http://mailman.isi.edu/pipermail/ns-developers/2007-September/003348.html

I proposed to make the Ipv4RoutingProtocol responsible for setting the source
address in Ipv4Header when it is 0.0.0.0.

Tom proposed:
"""
I agree that we now have redundant searches in the routing tables, once 
in UDP and once in IP.  I think the crux of the problem is already 
described in this comment in Ipv4L3Protocol::Send()

       // XXX Note here that in most ipv4 stacks in the world,
       // the route calculation for an outgoing packet is not
       // done in the ip layer. It is done within the application
       // socket when the first packet is sent to avoid this
       // costly lookup on a per-packet basis.
       // That would require us to get the route from the packet,
       // most likely with a packet tag. The higher layers do not
       // do this yet for us.

I would suggest to perhaps fix along the lines suggested in this 
comment, because otherwise, if I understand correctly, the source 
address is incorrectly set down to the IP layer which can cause checksum 
issues when checksums are enabled.
"""

To which my reply would be, this technique won't work very well for very
dynamic adhoc routing protocols, because this way you store the route in the
socket based on the route discovered for the first packet sent, but then you
never change it ever again, even if the underlying routing protocol discovers a
new better route or the old one simply becomes invalid.  IMHO it's better to
keep it as it is, always go through the routing protocol.

If we really want to speed up things along those lines it should be possible,
for example let the Ipv4RoutingProtocol::RequestRoute receive an extra optional
parameter containing the last route found, which would be stored in the socket
as the source comment suggests.  But in this case the routing protocol is given
full control, and can ignore the route suggestion if it can find a better
route.  

But that optimization goes another level.  I am proposing something far simpler
for now.
------- Comment #1 From 2007-09-14 01:03:04 EDT -------
Gustavo, I agree with your point that a route cached from first packet can
become stale.  What about, though, just doing a per-packet lookup but doing it
in UDP when the transport header needs to be created?

I think source address selection needs to be done in the transport layer,
particularly when things like IPsec can be inserted before the packet hits IP. 
Source address selection typically requires the destination to be determined.  

As a first step, one could have the transport layer do the pre-route step per
packet and store the route in a packet tag.  This would ensure per-packet
lookups like you want.

For optimizations, one could consider registering a callback with the routing
layer that flushed cached routes at the transport layer when any routing
protocol routes changed.
------- Comment #2 From 2007-09-14 06:13:51 EDT -------
(In reply to comment #1)
> Gustavo, I agree with your point that a route cached from first packet can
> become stale.  What about, though, just doing a per-packet lookup but doing it
> in UDP when the transport header needs to be created?
> 
> I think source address selection needs to be done in the transport layer,
> particularly when things like IPsec can be inserted before the packet hits IP. 
> Source address selection typically requires the destination to be determined. 

Sounds like a good idea to me.

> 
> As a first step, one could have the transport layer do the pre-route step per
> packet and store the route in a packet tag.  This would ensure per-packet
> lookups like you want.

Sure.

> 
> For optimizations, one could consider registering a callback with the routing
> layer that flushed cached routes at the transport layer when any routing
> protocol routes changed.

That's one possibilty.

Another possibility is to add the previously found route to the RequestRoute
API call, and also add a "creation timestamp" to Ipv4Route.  Then the routing
protocol can simply look at the timestamp and possibly return the previous
route and not do any new lookup.
------- Comment #3 From 2007-09-14 06:56:11 EDT -------
OK, some more comments.  I was looking to quickly implement the
RouteExpireCallback approach, but then I realized that a routing protocol will
have a hard time implementing this interface.  In order for a routing protocol
to call RouteExpireCallback when route expires, it needs to keep a list of
RouteExpireCallbacks associated with every Ipv4Route, and call them all.  This
adds a lot of complexity to the routing protocol, already complex enough.  And
also the caller needs to the define two separate callbacks...

The other alternative appears simpler.  The caller just stores the previous
route along with a timestamp, then for each packet requests a new route but
passing along the previous route and a timestamp.  The routing protocol can
simply do:

  if (Simulator::Now () - timestamp < Seconds(2))
    {
      return previousRoute; // returns the cached result, very fast
    }
  // else the route has become stale and a new one needs to be looked up

This second alternative seems much simpler to implement.  What do you think?
------- Comment #4 From 2007-09-14 07:01:48 EDT -------
As usual, the question is: how do they do this in real network stacks ? 

I suspect that a simple solution would be to just notify every layer of the
network stack whenever there is a change in the routing table which might
require some layers to re-lookup a cached route.
------- Comment #5 From 2007-09-14 08:35:05 EDT -------
(In reply to comment #4)
> As usual, the question is: how do they do this in real network stacks ? 

We cannot base our design purely on existing implementations of real network
stacks, because real implementations take into consideration the userspace /
kernelspace division between routing and forwarding, and associated context
switching penalty.  Here we have no context switching, thus we can achieve a
simpler architecture because we don't have to work around the context switching
bottleneck.

> 
> I suspect that a simple solution would be to just notify every layer of the
> network stack whenever there is a change in the routing table which might
> require some layers to re-lookup a cached route.
> 

That's a rather "course" solution.  Besides, it doesn't work well for reactive
routing protocols, which do not proactively modify the routing table at all,
which means that notification will never happen for example in AODV.
------- Comment #6 From 2007-09-14 09:16:03 EDT -------
> We cannot base our design purely on existing implementations of real network
> stacks, because real implementations take into consideration the userspace /
> kernelspace division between routing and forwarding, and associated context
> switching penalty.  Here we have no context switching, thus we can achieve a
> simpler architecture because we don't have to work around the context switching
> bottleneck.

Sure, but if you knew how others solve the same problem, I am fairly certain
that it would give you food for thought: it does not mean that you should do
the same thing. It just means that trying to redesign something without
a-priori knowledge of what others do does not sound like a great idea.
------- Comment #7 From 2007-09-17 12:34:39 EDT -------
I never meant to mark this as blocker; blocker is just the default severity in
this bugzilla instance...
------- Comment #8 From 2008-06-05 10:52:09 EDT -------
change to P3 (not a blocker)
------- Comment #9 From 2009-02-16 01:00:55 EDT -------
sliding to ns-3.5
------- Comment #10 From 2009-05-29 17:27:56 EDT -------
fixed in changeset e20a31541404

The basic behavior now is that routes are queried with RouteOutput() in the
transport layer, and the retrieved route is passed down the stack with the
packet to the IP layer.