[Ns-developers] [ns3] socket API

Mathieu Lacage mathieu.lacage at sophia.inria.fr
Tue Apr 15 12:18:09 PDT 2008


On Tue, 2008-04-15 at 18:19 +0000, Tom Henderson wrote:

> I was assuming that you just pass a null pointer, but set the size
> parameter to the size of fake data, and the socket converts it to the
> null packet for you.  This is already supported:
> 
> int Socket::SendTo (const Address &address, const uint8_t* buf,
> uint32_t size)
> {
>   NS_LOG_FUNCTION;
>   Ptr<Packet> p;
>   if(buf)
>     {
>       p = Create<Packet> (buf, size);
>     }
>   else
>     {
>       p = Create<Packet> (size);
>     }
>   return SendTo (address,p);
> }

I see. I missed that piece of code. I have to confess that I find that
an absolutely horrifying API. I guess I agreed to that at some point,
but looking at it now makes me want to cry.

> >> In the receive direction, if you want to support recv/recvfrom
> >> semantics, the choices are Recv (..., Ptr<Packet>, ...) or Recv
> (...,
> >> uint8_t* buf, ...).
> >> 
> >> In the case of fake data, there is no efficiency difference because
> >> zero bytes are copied.  In the case of real data, the use of the
> buf
> >
> >There is a difference, even in the case of fake data: If you have
> fake
> >data, Recv (uint8_t *buf) will require that you actually convert that
> >fake data to a real buffer and copy it. The Ptr<Packet> version, on
> the
> >other hand, will not require that last conversion and will track of
> the
> >fake data without allocating it.
> 
> Similarly, I was assuming that you could implement a variant of
> recv(uint8_t* buf) that worked with fake data.  for instance,
> Socket::Recv (0, len); and you implement a check in the socket to
> avoid copying in any data to a null pointer.

You are right, it should be possible, but, again, that is a truly
horrifying API.

> >> There are also cases in which the Recv does not align with the
> Packet
> >> boundaries as Packets were delivered to the receive socket.  For
> >> instance, in TCP, you may have a read that spans multiple packet
> (and
> >> packet Buffers).  The application may also read less than what is
> >> available.  In these cases, do you end up losing the _really_
> >> efficient operation of the Ptr<Packet> version, when your read
> spans
> >> underlying Buffers?  
> >
> >No: In the case of fake data stored in a Ptr<Packet>, Ptr<Packet> is
> >still smart enough to keep track of slices of the fake data if it is
> >sliced.
> 
> but in the case of real data?

Of course, if there is real data, it cannot do anything. But if you have
real data, you have already lost the performance race, so, I don't
really see your point.

> >> In the case of a large read, wouldn't you have to create a new
> Packet
> >> that concatenated the underlying Buffers (and hence required a copy
> >> into this new Buffer)?  If not, how would that work?
> >
> >If you kept track of the received data with a list of pointers to
> >packets, you can aggregate them with Packet::AddAtEnd and that will
> also
> >be smart enough to avoid buffer allocations in case of fake data.
> 
> but in the case of real data?

yes, it cannot make magic happen in that case.

> >> In the case of the small read, you may have multiple Packet objects
> >> pointing at the same Buffer, with differing offsets (m_start,
> m_end),
> >> so unless the read spans Buffers, then it seems like you can also
> >> avoid copies here. 
> >
> >I am sorry but I do not understand what you mean by this.
> 
> (for real data)  You received two packets of size 1000, but your
> application does two reads of size 700 followed by a read of 600.
> What happens to the Packet buffer on this second read, which spans
> multiple received Buffers?

Well, there is no magic happening: it will get a new buffer allocated
and data copied in it.

> 
> The basic question is, when you have real data, if you implement the
> receive buffer in the socket using the received Packets (to avoid
> copies of the underlying Buffers), what happens when your reads do not
> align with these Buffer boundaries-- do copies happen?

yes.

> It still seems to me that, for fake data, whether you use the byte
> buffer version or Packet version of these socket calls does not matter
> (or does not have to matter), since in either case you can avoid
> allocating buffers for fake payload.

You are right, but, I mentioned in my reply to george that there are two
reasons for exporting a Ptr<Packet> version of this API:

  1) performance (you focused on that in your emails and demonstrated
successfully that it was not the _strictly_ necessary)

  2) allow applications to be written using Ptr<Packet>. hint: gusvato's
olsr code does that pretty successfully.

There is another one I alluded to also: the need to support fancy
features of the socket API such as ancillary buffers: it is trivial to
add this support to a Ptr<Packet> API through tags attached to packets
but adding this to a raw buffer-based API will require that you clone
the C-style ancillary data API (man cmsg) which... Well, will represent
much more careful painful work.

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.

It seems that the proposal to remove the duplicate raw-buffer API is
controversial (why that is the case is something I don't really
understand but, if you know, please, feel free to enlighten me) so, can
we ignore that, assume that the raw buffer API will stay untouched, will
not get any extra work to support any extra features for now and focus
instead on the rest of my proposal ?

regards,
Mathieu



More information about the Ns-developers mailing list