Subject: setsockopt()

From: Gaurab Paul <[email-masked]>
Date: Tue, 03 Jun 2003 18:06:22 +0000

Hi,

I shall be thankful if I could know the rationale for the following.

The scenario is:

TCP server steps at runtime:

1. sd=socket(AF_INET, SOCK_STREAM, 0) - create socket
2. bind(sd,...)
3. listen(sd,..)
4. setsockopt(sd, SOL_SOCKET, SO_SNDBUF, .....)
5. newSd=accept(sd,...)
6. getsockopt(newSd, SOL_SOCKET, SO_SNDBUF,....)
.....

It has been quite sometime since it was observed that the SO_SNDBUF size which I set on "sd" is also set automatically
when for the "newSd".
For example,

   * set "2900" for SO_SNDBUF on "sd" with setsockopt()
   * getsockopt() on "newSd"  shall return "2900" for SO_SNDBUF

I have tested this on a Solaris 2.8 box. And, this seems to be true on some other platforms also.

Since "newSd" is a new/fresh socket descriptor, I would have expected the SO_SNDBUF settings which I did on "sd" NOT to
be set on
"newSd".

What was the rationale or why was this behavior chosen for  socket libraries?

Thanks,

Gaurab

---

From: "Randall Stewart (cisco)" <[email-masked]>
Date: Tue, 03 Jun 2003 10:15:46 -0500

Paul:

I am a bit confused by this question... is this an SCTP question?

It seems like you are talking about TCP or do you mean the
TCP-style interface of SCTP... note this nomenclature will be
going away in the next draft...

Thanks

R

Gaurab Paul wrote:

> It has been quite sometime since it was observed that the SO_SNDBUF 
> size which I set on "sd" is also set automatically when for the "newSd".
> For example,
>
> Since "newSd" is a new/fresh socket descriptor, I would have expected 
> the SO_SNDBUF settings which I did on "sd" NOT to be set on
> "newSd".
>  
>

-- 
Randall R. Stewart
ITD
Cisco Systems Inc.
[email-masked] 815-342-5222(cell) or 815-477-2127(office)

---

From: Gaurab Paul <[email-masked]>
Date: Wed, 04 Jun 2003 12:04:15 +0000

Hi Randall,

If this nomenclature goes away in the next draft, then perhaps we should be no longer concerned
with this question so far as SCTP is concerned.

However, I wanted to know WHY was this behavior opted for in TCP.

An "accept()" implementation in UNIX for the example TCP server provided earlier, broadly,

1. Maps listen socket node( vnode type VSOCK, for the listen socket) to a file descriptor.
2. Wait for a connection; ( blocking here, flags from the file descriptor in step 1 are used here).
3. Create a new socket.
4. New socket's local address is SET to be the listen socket's local address.
5. New socket inherits SIOCSPGRP, SS_ASYNC  so that any data arriving on the new socket
     will cause the appropriate signals to be delivered for the new socket.
6. And then, the SOL_SOCKET socket options are inherited from the listener to acceptor.

Now, the number of socket options, as we all know are not few. Just to enumerate:

SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
SO_USELOOPBACK, SO_OOBINLINE, SO_DGRAM_ERRIND, SO_LINGER, SO_SNDBUF,
SO_RCVBUF

My questions arises because:

1. Since on a succesfull "accept()", a new socket descriptor is returned, it seems logical to think that the
new acceptor socket descriptor does NOT have the  socket options of the listener socket descriptor.

2. I do not see why - any TCP protocol rules which directly or indirectly enforces that -  the socket options
needs to be inherited by the acceptor socket descriptor from the listener socket descriptor.

3. And, if we go with "1", then the copy/inherit operations on the acceptor socket descriptor from the
listener socket descriptor can be avoided; in the process reducing the CPU cycles etc every time we do an "accept()" .

The only reason, if it could be called reason at all, which I could think of is, an INCLINATION to treat the acceptor
socket descriptor more like a CHILD descriptor of the listener socket descriptor rather than a NEW socket descriptor.
Hence, inheriting the socket options also from the parent. Please note that some properties like local address etc are
needed to be inherited.

But, as obvious, the above INCLINATION seems rather not so acceptable or reasonable.

To reiterate, I shall be thankful if I could know the rationale WHY the  behavior described above was chosen.

Thanks,

Gaurab

---

From: "Brian F. G. Bidulock" <[email-masked]>
Date: Wed, 4 Jun 2003 02:22:58 -0600

Gaurab,

How else are you to specify socket options for the accepting socket?

In XTI/STREAMS the user would open a new stream set the options how
they liked and then accept the T_CONN_IND with T_CONN_RES on the new
stream.

For sockets, if you do not transfer the socket options from the listening
socket, there is no way to specify them.  The socket is already fully formed
by the time that accept() returns with the file descriptor and the user
has lost the chance to specify anything about the accepted socket.

So, in sockets, the user specifies the socket options they want on the
listening socket, and then calls accept() with the knowledge that the
returned socket will have the specified options.

Do you see some other rational (and backwards compatible) way for the
user to specify socket options for accepted sockets before the accepted
socket is fully formed?

--brian

-- 
Brian F. G. Bidulock    ¦ The reasonable man adapts himself to the ¦
[email-masked]    ¦ world; the unreasonable one persists in  ¦
http://www.openss7.org/ ¦ trying  to adapt the  world  to himself. ¦
                        ¦ Therefore  all  progress  depends on the ¦
                        ¦ unreasonable man. -- George Bernard Shaw ¦

---

From: Gaurab Paul <[email-masked]>
Date: Wed, 04 Jun 2003 15:54:18 +0000

Brian,

For the acceptor socket, to specify options say for SO_SNDBUF, TCP server steps at runtime could be :

1. sd=socket(AF_INET, SOCK_STREAM, 0) - create socket
2. bind(sd,...)
3. listen(sd,..)
4. setsockopt(sd, SOL_SOCKET, SO_SNDBUF, ....., OLD_BUF_SIZ)
5. newSd=accept(sd,...)
6. setsockopt(newSd, SOL_SOCKET, SO_SNDBUF, ....., NEW_BUF_SIZ)
7. getsockopt(newSd, SOL_SOCKET, SO_SNDBUF,....)

This  is working fine in Solaris 2.8 at least.

However, for some specific socket options, there COULD be a restriction.

"fully formed"  as you say. There is NOTHING WRONG which I see as such :-)

However, as I had indicated earlier, we could have at least saved a few hundred CPU
instructions if by default we did not make the acceptor socket inherit all the options of the
listening socket on every successfull "accept()".

The advantage, however, is that in the current framework, setting the options in the
listener socket helps the user in NOT writing the code to modify the socket options
for each acceptor socket.  Modify once in the listener socket, avail it on all acceptor sockets.

On the other hand, if he/she wishes to override the socket options for the listener socket,
he/she could do so. Flexiblility and performance, isn't  it?

I do not understand the question. If you do not mind, could you please explain.

Thanks,

Gaurab

---

From: "Randall Stewart (cisco)" <[email-masked]>
Date: Wed, 04 Jun 2003 08:36:43 -0500

>However, I wanted to know WHY was this behavior opted for in TCP.

Ok, it is always good to know the background of such things.. but the 
problem
here is I think you ask the wrong list...

You need to find the appropriate TCP list to ask this question... since 
it seems
to me you are asking why the designers of sockets for TCP made particular
choices... the folks on this list are focused on SCTP and might be able to
answer such a question about SCTP.. but I  would expect most of what you
would receive here on TCP is not an acurate dipiction of why TCP made
certian choices... since I doubt that most of the folks on the list had
anything to do with those choices...

I am sure there is a better list to ask this qeustion too... even TSVWG 
probably
has some of the folks that were working on TCP back then.. also a hunt of
the comp.xxx.. mailing lists probably has a tcp one in there somewhere :-0

R

---

From: "Brian F. G. Bidulock" <[email-masked]>
Date: Wed, 4 Jun 2003 11:38:56 -0600

Gaurab,

>    4. setsockopt(sd, SOL_SOCKET, SO_SNDBUF, ....., OLD_BUF_SIZ)

Your program gets scheduled here....

>    6. setsockopt(newSd, SOL_SOCKET, SO_SNDBUF, ....., NEW_BUF_SIZ)

Too late.  Your socket has been running for some time with some
"other" options.  Not the listening socket's options according to
your argument.

Consider SO_DEBUG or SO_OOBINLINE.

>    In XTI/STREAMS the user would open a new stream set the options how they
>    liked and then accept the T_CONN_IND with T_CONN_RES on the new stream.
> 
>    For  sockets,  if  you  do  not  transfer  the socket options from the
>    listening socket,  there is no way to specify them.  The socket is
>    already fully formed by  the  time  that  accept() returns with the file
>    descriptor and the user has lost the chance to specify anything about the
>    accepted socket.
> 
>    However,  as  I  had indicated earlier, we could have at least saved a
>    few hundred CPU instructions if by default we did not make the acceptor
>    socket inherit all the options of the listening socket on every
>    successfull "accept()".

You are assuming what the user program will do.  Perchance the user will
immediately close() the socket because the user program doesn't like the
calling address.  Then all the accept() cycles were wasted.  Perchance
the user will set all of the same options on the accepted socket as were
set on the listening socket, one by one, generating a setsockopt call for
each option.  Wasting even more cycles.

> 
>    The  advantage, however, is that in the current framework, setting the
>    options in the listener  socket  helps the user in NOT writing the code
>    to modify the socket options for  each  acceptor socket.  Modify once in
>    the listener socket, avail it on all acceptor sockets.
> 
>    On the other hand, if he/she wishes to override the socket options for
>    the listener socket, he/she could do so. Flexiblility and performance,
>    isn't  it?
> 
>    user  to  specify  socket  options  for  accepted  sockets  before the
>    accepted socket is fully formed?
> 

How else can you change socket options on a socket BEFORE it is FULLY FORMED.

--brian