[Ns-developers] [ns3] socket API
Mathieu Lacage
mathieu.lacage at sophia.inria.fr
Thu May 15 09:09:06 PDT 2008
(sorry for the late reply)
On Tue, 2008-05-13 at 22:45 -0700, Tom Henderson wrote:
> > Do you have a better suggestion ? Otherwise, let's just use ENOMEM.
>
> EMSGSIZE? I think of ENOMEM as typically referring to failed malloc().
good for me.
> >> I would support whatever consensus would emerge on whether to keep or
> >> remove these variants, but my sense is that opinions still differ.
> >
> > So, what do you suggest we do to make progress on this issue ? Not
> > making a decision before merging and leaving your current tree as-is is
> > making an implicit decision so, please, let's make this explicit before
> > merging.
> >
> > The main argument for not implementing a SocketHelper as was discussed a
> > week ago is potential user confusion about slightly-different and
> > duplicated API: the _exact same_ argument applies equally to all the
> > one-liner overloads of Send in socket.h and is the main reason why I
> > originally proposed to remove them.
>
> This is revisiting an old contentious issue (November developers
> meeting) and also seemed to not have universal agreement when raised on
> the list in April. So I think the default should probably be to keep
> what we have unless discussion results in different consensus now.
Since then, a number of issues have been raised, most notably the fact
that we were wrongly trying to make our users believe that we were
providing a posix socket API while we are not. It is based on these new
discussions that I proposed that removal so, arguing that you would like
to keep the current state based on discussions which predate these new
arguments would be misleading.
A better way to deal with this issue would be to revisit the previous
decision and rationale based on the new discussions we have had recently
about actual user confusion. Since I don't remember anything (I honestly
don't) about the november discussion you allude to, it might be helpful
to dig these and post them here: it might be that there is a showstopper
which I forgot about.
Another alternative is for you to state an explicit decision about this
and ignore the pointless bickering we are into. I would be fine with
this but I want to make progress and I don't want to see decisions being
made implicitely.
> >> 3) How should socket options and ioctls be supported ?
> >>
> >> I implemented this along the lines of Mathieu's suggestion (define
> >> SocketOptions class and aggregate the object to a socket) although
> I
> >
> > I looked at the code and did not find that class: it seems that you
> have
> > implemented the options in the socket subclasses directly.
>
> see the top of sockets.h file
I see.
> >> The question arose as to where to put the defaults for these
> options,
> >> since class SocketFactory is abstract base class. I implemented a
> >> class SocketDefaults and made these attribute-based, and aggregated
> a
> >> SocketDefaults object to the Node (in
> >> InternetStack::AddInternetStack()).
> >>
> >> Maybe there is a better implementation strategy that avoids this
> >> class, but the above seems workable at least.
> >
> > The problem with a single SocketDefaults class per node is that it
> will
> > have to contain all the defaults of all protocols, including the
> > protocols developed by users which will kill one of the "features"
> we
> > have been working on for a long time, that is, the ability to add a
> new
> > type of socket/protocol to the system without having to patch
> anything
> > src/node/. So, that solution is really not an option.
>
> I was thinking that the SocketDefaults class just held "sockets"
> level
> defaults such as SO_SNDBUF. The per-protocol defaults could be
> hosted
> by the respective socket factory objects. I do not think such an
> approach requires to edit src/node.
The issue here is that I can imagine sockets for which the "TxBufSize"
option makes zero sense (for example, a netlink socket) so, I don't
think you will be able to come up with a useful set of generic options
which apply to everyone to stick in there.
> For instance, if one implements SctpSocket with SctpSocketOptions, then
> SctpSocketOptions could be aggregated to SctpSocket by the SctpImpl
> factory. A user holding Ptr<Socket> sock could call
> sock->GetObject<SctpSocketOptions> (); and then could use this class to
> set options on the SctpSocket. There wouldn't be a need to edit class
> Socket either because the user could get the SctpSocket public API via
> GetObject(). Am I missing something?
You are right.
> > Given all the constraints we have here, I would like to suggest that,
> > instead, we do something potentially simpler: for each subclass of
> > Socket, define an attribute for each socket option relevant to that
> > specific subclass and define its initial value there. This will allow
> > you to:
> >
> > - define any number of options for each socket subclass independentely
> > from the other socket subclasses, hence allowing a user to create new
> > socket subclasses without having to patch src/node/*
>
> Again, I don't think my suggestion was requiring such a patch.
I see this now.
>
> >
> > - override on a simulation-wide basis the initial value of each of
> > these socket options with the Config::SetDefault function
> >
> > - if you want to allow the user of a socket to write code which sets
> > or gets a socket option in the same way across multiple implementations
> > of the same kind of socket, all you have to do is use the same attribute
> > name and type to allow the following to work consistently:
> > socket->SetAttribute ("RcvBufSize", UintegerValue (10));
>
> Yes, but the Config::SetDefault is no longer generic, right?
Not really. If you really think that RcvBufSize is a generic attribute,
you could conceivably move it to the Socket base class and make it
indirect through a pair of private virtual methods:
class Socket
{
public:
static TypeId GetTypeId (void) {
static TypeTid tid = TypeId ("ns3::Socket")
...
.AddAttribute ("RcvBufSize", "help text",
UintegerValue (10),
MakeUintegerAccessor (&Socket::GetRcvBufSize,
&Socket::SetRcvBufSize)
...)
;
return tid;
}
private:
virtual void SetRcvBufSize (uint32_t size) = 0;
virtual uint32_t GetRcvBufSize (void) = 0;
}
> > The above proposal is not optimal since it will not allow you to specify
> > a default value on a per-node basis but, I view this as a much lesser
> > evil than the alternatives.
> >
>
> If what I said above was correct (about how it could work) do you still
> view it as evil?
Given your comments above, no, I do not see this as evil anymore
(although I _really_ feel uncomfortable about these "generic" socket
options stored in the class SocketOptions).
I know that we discussed this at length last friday in my office but the
more I look at this, the less I am convinced that we need the extra
complexity (both from an implementation and from a user point of view)
provided by these aggregated socket option classes. It seems just
simpler to go with an attribute-based approach and I have a hard time
convincing myself that the extra features provided by the aggregate
classes are worth the extra pain.
To summarize, I tend to favor giving up a single feature (namely, the
ability to specify per-node defaults) for a net decrease in terms of
implementation and user-visible complexity. i.e., users don't have to
call GetObject before calling SetAttribute or GetAttribute to set or get
an option.
regards,
Mathieu
More information about the Ns-developers
mailing list