Bug 136 - Sockets bound to specific interfaces receive broadcasts arriving on other interfaces
: Sockets bound to specific interfaces receive broadcasts arriving on other int...
Status: RESOLVED FIXED
: ns-3
internet-stack
: pre-release
: All All
: P3 normal
Assigned To:
:
:
:
:
  Show dependency treegraph
 
Reported: 2008-02-12 07:18 EDT by
Modified: 2008-02-26 05:28 EDT (History)


Attachments
patch to exercise the problem in the unit tests (4.84 KB, patch)
2008-02-12 07:20 EDT, Gustavo J. A. M. Carneiro
Details | Diff
patch to fix issue (including unit test) (20.50 KB, patch)
2008-02-12 10:24 EDT, Gustavo J. A. M. Carneiro
Details | Diff


Note

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


Description From 2008-02-12 07:18:12 EDT
here's a simple diagram

              <----- broadcast
   / 10.0.0.1 --------------------- 10.0.0.2
  /                                         \
N1                                           N2
  \
   \ 10.0.1.1


Suppose N1 has two sockets, one bound to one interface, another bound to
another interface (Bind (interface-ipv4-address)).  When N2 sends a broadcast
packet to N1, currently both sockets in N1 are receiving a copy, which is
wrong.  That should only happen when using sockets bound to the "any" address,
not like this.

Yes, this is partly my fault (bug 51) but there is a subtle distinction between
multiple sockets receiving a broadcast packet when they are bound to the "any"
address and the case where all sockets are bound to specific interface
addresses.  Both scenarios have their uses and should be supported.
------- Comment #1 From 2008-02-12 07:20:34 EDT -------
Created an attachment (id=105) [details]
patch to exercise the problem in the unit tests
------- Comment #2 From 2008-02-12 10:24:41 EDT -------
Created an attachment (id=106) [details]
patch to fix issue (including unit test)

Phew!  It has been a challenge to get both cases working together :P
The rationale for this change is (besides the usual "Linux does it") that in
the OLSR agent I am now trying to create several sockets, each bound to its own
interface, because I need to know on which interface OLSR HELLO messages
arrive, in order to properly follow the RFC algorithm, which states that "link
sensing" uses real interface addresses, unlike everything else that uses "main
addresses".  As far as I know, this is the only way using sockets to discover
on which interface a packet arrived.
------- Comment #3 From 2008-02-12 20:03:15 EDT -------
OK, I have finally finished debugging OLSR, and I have a big patch to cleanup
OLSR and fix a ton of bugs.  But it needs this patch to go in first.

So, can someone please review this, or give a suggestion of how to get
information of interface by which UDP packets are received.

I suppose we could make something else up to solve the problem, by using packet
tags for example, but since there is a standard way of doing it with sockets I
think it is best to use it -> less learning for users that know socket
programming -> less difficulty in porting daemons between NS-3 and real world.

Eagerly awaiting a reply; this is kind of blocking my research into OSLR for
large wireless networks... :P
------- Comment #4 From 2008-02-13 00:36:52 EDT -------
I support the patch; just had a couple of nits:

+      ipv4_api->FindInterfaceForAddr (ipv4); // check if address matches a
local interface

I would change the above comment to // asserts if requested address is not
found

I was looking at this function for a while and wondering "why is the return
value ignored?"

Also,
+  Ipv4Address m_localInterface; // local interface (optional)

In what sense is this optional?  I see it as a mandatory parameter everywhere. 
Does "(optional)" mean optional in the sense that the user calling Bind is
optional?
------- Comment #5 From 2008-02-13 12:31:02 EDT -------
(In reply to comment #4)
> I support the patch; just had a couple of nits:
> 
> +      ipv4_api->FindInterfaceForAddr (ipv4); // check if address matches a
> local interface
> 
> I would change the above comment to // asserts if requested address is not
> found

Agree; will change it.

> 
> I was looking at this function for a while and wondering "why is the return
> value ignored?"

I'll change to NS_ASSERT (ipv4_api->FindInterfaceForAddr (ipv4) != 0), to make
the code clearer.  (the outer assert will never be invoked, but it doesn't
hurt).

> 
> Also,
> +  Ipv4Address m_localInterface; // local interface (optional)
> 
> In what sense is this optional?  I see it as a mandatory parameter everywhere. 
> Does "(optional)" mean optional in the sense that the user calling Bind is
> optional?

+  Ipv4Address m_localInterface; // local interface (optional)

It is optional in the sense that localInterface can be Ipv4Address::GetAny (),
which means the end point is not associated with any particular interface.  I
will clarify this comment.
------- Comment #6 From 2008-02-13 12:48:22 EDT -------
committed -> http://code.nsnam.org/ns-3-dev/rev/eec07777d1a2
------- Comment #7 From 2008-02-25 18:07:35 EDT -------
With these changes, several UDP and TCP APIs have an additional localInterface
parameter passed in.  Can we use a default parameter, or have overloaded
versions that assume the parameter is Ipv4Address::GetAny() ?  It will simplify
the user API for simple cases.  I noticed this because these changes broke the
API I was using when I wrote the TCP server forking code, and I'm now
revisiting that.
------- Comment #8 From 2008-02-26 05:28:49 EDT -------
I'm fine in principle with a default parameter version, but I remember I
intentionally made the parameter mandatory precisely to catch code that needed
to adapt to new API requirements.  If the parameter had a default a lot of code
would silently compile but fail in subtle ways in runtime...