[Ns-developers] [ns3] socket API

Gustavo Carneiro gjcarneiro at gmail.com
Wed Apr 16 03:51:58 PDT 2008


On 16/04/2008, Sam Jansen <sam.jansen at gmail.com> wrote:
>
> Some comments inline...
>
>
>
> >
> >  >
> >  >> >Anyhow, 2) described above really makes it mandatory to have a
> >  >> >Ptr<Packet> version of the API so, the question is: why should you
> >  >> keep
> >  >> >around the raw buffer-based version of the API since:
> >  >> >
> >  >> >  - it is trivial to emulate its behavior: wrap your raw buffers
> with
> >  >> >Packet::Packet (uint8_t *buf, uint32_t size)
> >  >> >
> >  >> >  - it either won't support features such as ancillary data or will
> >  >> >require a _lot_ of work to support them
> >  >> >
> >  >> >  - it duplicates the other API
> >  >> >
> >  >> >I am certain that craig would be able to come up with a nice
> summary
> >  >> of
> >  >> >all the reasons why providing two ways to do the same thing in an
> API
> >  >> is
> >  >> >really bad and why it should be avoided so, I won't try to beat him
> >  >> to
> >  >> >it.
> >  >>
> >  >> The only reason that I see to support this is the legacy API issue,
> >  >> which is where I believe George is coming from.  Recall that Joe had
> a
> >  >> question last year about how to copy data into a packet at the
> >  >> application level (you need to use AddHeader, which is not
> intuitively
> >  >> obvious).
> >  >
> >  >Why can't you write this:
> >  >
> >
> > >uint8_t *buffer =...;
> >
> > >uint32_t size = ...;
> >  >
> >  >Ptr<Packet> end = Create<Packet> (buffer, size); ?
> >  >
> >  >Ptr<Packet> begin = ...;
> >  >
> >  >begin->AddAtEnd (end);
> >
> >
> > Yes, you can do that too.  I think the point was, that these techniques
> are not as immediately obvious to the new users who knows sockets or who are
> porting over existing code.
> >
>
>
> I'd like to add my 2 cents here and say that this is a big important
> point we shouldn't lose sight of here.
>
> Some ideas off the top of my head:
>
> 1. I don't like the idea of designing an API around performance and
> forgetting what this is actually modeling (which appears to be
> happening here).
>
> 2. How incredibly confusing, for either a student new to
> networks/sockets, or an old hand used to streaming sockets, to see an
> API where you have to pass a packet in. Without the context of this
> email thread, I think this would leave even experienced network
> programmers with a confused look on their face.


I think that, because of the way ns-3 headers work, we are forced to pass in
packets when we want to use the ns-3 headers framework on top of UDP
sockets, like I did in OLSR.

3. For better or for worse, the sockets API is here, has been here for
> a long time, and is here to stay. People are familiar with it. It's in
> books. Do we really need to deviate so much from it? Forgetting the
> simu/process work for a second, if I want to model my application in
> ns-3, why can't I have a familiar API to send/receive data (or send
> receive a number of bytes).
>
> Let's look at this another way. When dealing with TCP, an application
> *never* has to deal with anything called a "packet". The idea of a
> "packet" should never enter the mind of an application developer. This
> is the reality, so it is what we are trying to model.
>
> I see that performance is required here when application data is not
> used, but why do we have to use the Packet here? It is obviously
> convenient and solves the problem, but it doesn't sound like the right
> way to do this to me.
>
> It seems to be that a different abstraction than a packet is required
> here.
>
>
> >  >
> >  >> That is, make Ptr<Packet> the primary API in terms of features
> (cmsg),
> >  >> but also agree to support the Send/Recv buf versions as overloaded
> >  >> functions, where they are immediately converted to/from Packet below
> >  >> the API, as is presently done in Socket::SendTo ().
> >  >
> >  >I would like to avoid being on the receiving side of user emails such
> >  >as: "which version should I use ?".
>
>
> Howabout emails like, "why can I only send packets with TCP, why can't
> I just send a bunch of bytes?"
>
> Doesn't sound like a net win to me.
>

I think perhaps sockets could accept an _additional_ API accepting bytes for
sockets.  But we cannot remove the packet based API for the reason I
explained.

But another consideration to be made is whether sockets should accept a pair
of uint8_t* and uint32_t, (base pointer and length).  Such an interface is
very low level and very C-like.  It is also hard to wrap for language
bindings, as it requires manually written wrappers all the time, since for
example a single python string argument maps to a pair of C/C++ parameters.

Perhaps a good approach (in _addition to_ the existing API, I can't stress
enough) would be a Buffer based API.

Socket::Send (const Buffer &buffer);

Like:

Ptr<Socket> sock = ...;
sock->Send (Buffer ("hello", 5));

I think it "reads" better, even for TCP sockets, and is high level enough to
not make language bindings too difficult.

For greater performance (avoid copy) we could have:

sock->Send (Buffer::NewFromForeignData ("hello", 5));

But then we need very clear semantics of when the data is actually copied
into a packet, and this is very tricky.  Copy too soon and you lose any
performance advantage you thought you had.  Copy too late and you risk the
data disappearing underneath you and a memory error when you do need it.

So I really do not think we are so desperate for performance that we want to
risk using something like my proposed Buffer::NewFromForeignData.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert


More information about the Ns-developers mailing list