[comp.protocols.tcp-ip] Call queueing

jgh@root.co.uk (Jeremy G Harris) (08/25/88)

The BSD listen(2) syscall (on a socket) provides for the specification
of a queue of pending connection requests.  So does the TLI T_LISTEN function.

What are the pros and cons of this functionality?  Is it merely a matter
of the cost of copying a protocol control block versus the cost of opening
and initialising one?  Or is there also a functional benefit?

    Jeremy.

-- 
Jeremy Harris			jgh@root.co.uk

romkey@asylum.UUCP (John Romkey) (08/28/88)

jgh@root.co.uk asked about why listen(2) allows a queue of pending
connection requests.

Under the BSD networking model, when you want to listen() for a
connection, you first get a socket and then listen() on it. When a
connection is opened, you do an accept() (which gets you a new socket)
to actually get ahold of the connection. A server which wants to be
able to handle more than one connection at a time normally fork()s,
and the child process does the actual work while the parent goes back
to listen()ing.

If you don't allow a queue of pending requests, then from the time
when the listen() completes to the time when the server issues a new
listen(), there is no one listening. Any incoming requests will then
get a reset. The window of time is probably pretty small, on the order
of milliseconds, but you want it to be 0. So you need listen() to be
able to handle more than one incoming request. And you have to tell
listen() how many to handle so that the kernel can allocate
appropriate resources.
				- john romkey

CLYNN@G.BBN.COM (08/29/88)

Jeremy,
	As John pointed out, the call queueing is used to reduce the
probability that a SYN arrives during a window where there is no listening
connection to bind it to, thus causing a RESET to be returned.  Queueing
can only reduce it, since it is always possible for there to be more
arriving SYNs than there are remaining free queue slots.  However, I reguard
specifying the size to the kernel to be more for the purpose of "limiting"
resources (such as processes [from the forks] and cpu cycles) than for
"allocating" them.
	As with all implementations, tradeoffs have been made.  I feel that
one of the "minuses" with the BSD implementation is that not only does the
listen cause the arriving SYN to be accepted and bound to a new TCP connection
block, but that the protocol machine is also started.  Thus a connection may
proceed to the ESTABLISHED state and accept/ACKnowledge (usually 4K bytes of)
data before the application-level peer (process) is even created.  This
prevents the process from:
    1) examining the IP-address identity of the caller before deciding
       ACKnowledge the SYN vs. send a RESET,
          What if X were to place a "collect" call to such an implementation
          and send 4K data; then the receiver process start up and decides
          it doesn't want to accept the call.  Who pays for the 4K bytes?
          (The receiver COULD make the 4K available to the appliaction.)
    2) checking its routing tables and applying administratively specified
       per IP-address source routing, etc.,
    3) selecting initialization parters based on IP-level parameters such as
       TOS and options, or
           Maybe local system has a method for setting the TCP MSS (which
           the spec says has to be in the SYN packet).           
    4) specifying initial TCP-level options, etc.

Charlie

dougm@violet.ICO.ISC.COM ("Doug McCallum") (08/29/88)

In reply to your message of 25 Aug 88 16:10:01 GMT
-------
> The BSD listen(2) syscall (on a socket) provides for the specification
> of a queue of pending connection requests.  So does the TLI T_LISTEN function.

> What are the pros and cons of this functionality?  Is it merely a matter
> of the cost of copying a protocol control block versus the cost of opening
> and initialising one?  Or is there also a functional benefit?

The reason you want to allow for queueing of incoming connection requests is
that you want to buffer them while an application is processing a previous
one.  The alternative is to reject the connections until the application is
ready again.  Even with minimal overhead tin getting the appliation started
there will be cases where multiple connection requests arrive back-to-back
from the network.  You don't want to reject these so you queue them until
there is time to properly respond.

In the BSD systems, the queued connection requests get accepted
automatically.  In the TLI mechanism, it is possible that the connection
request has not been responded to giving the application final say on
whether to accept or reject the request.

One minor clarification, the TLI indication to queue connection requests is
in the t_bind call and not the t_listen.  T_listen is not the same as the
socket listen.  t_listen waits for an incoming connection request and
returns that to the application.  The information in the connection request
is then given to the t_accept call if the connection is to be accepted or
the t_snddis call if the connection is to be rejected.

mouse@mcgill-vision.UUCP (der Mouse) (09/02/88)

> [A disadvantage of the BSD networking model is that] a connection may
> proceed to the ESTABLISHED state and accept/ACKnowledge (usually 4K
> bytes of) data before the application-level peer (process) is even
> created.  [...] What if X were to place a "collect" call to such an
> implementation and send data; then the receiver process start up and
> decides it doesn't want to accept the call.  Who pays for the bytes?

Presumably in an environment where the notion of a "collect" call makes
sense, one doesn't use this model.  It would be fairly easy to add such
capability to BSD.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

jgh@root.co.uk (Jeremy G Harris) (09/02/88)

I asked:
> The BSD listen(2) syscall (on a socket) provides for the specification
> of a queue of pending connection requests.  So does the TLI T_LISTEN function.

> What are the pros and cons of this functionality?  Is it merely a matter
> of the cost of copying a protocol control block versus the cost of opening
> and initialising one?  Or is there also a functional benefit?

My thanks to everybody who replied, both here and by mail.  Several people
pointed out that I said t_listen when I should have said t_bind - sorry,
my fingers were running faster than my brain....

However, nobody has answered the question that I was trying to ask.  I can't
have made a good job of the question :-)

Why does this connection queue have to be handled by the kernel?  Why couldn't
the application just open and initialise for listening (not in the BSD syscall
sense)  as many transport endpoints as it's queue needs to be long?

Opinions, anybody?

Jeremy
-- 
Jeremy Harris			jgh@root.co.uk

dannyb@kulcs.uucp (Danny Backx) (09/08/88)

In article <628@root44.co.uk> jgh@root44.UUCP (Jeremy G Harris) writes:
>I asked:
>> The BSD listen(2) syscall (on a socket) provides for the specification
>> of a queue of pending connection requests.  So does the TLI T_LISTEN function.
>
>> What are the pros and cons of this functionality?  Is it merely a matter
>> of the cost of copying a protocol control block versus the cost of opening
>> and initialising one?  Or is there also a functional benefit?
>
>Why does this connection queue have to be handled by the kernel?  Why couldn't
>the application just open and initialise for listening (not in the BSD syscall
>sense)  as many transport endpoints as it's queue needs to be long?

How about this:

A server process S is doing accept. It implements a highly available server.
For speeding things up, it forks of a process for every client.
A client A connects to the socket, and while S is forking, closing the second
socket, and doing the next accept, two client processes B and C have attempted
to connect.

Without a queue, what would happen ? One of the connects could be remembered,
while the second one certainly is forgotten by the kernel that the server runs
on.

Since we're talking about TCP, which is supposed to be reliable, the client
which was forgotten will retry the attempt to connect (after a LONG timeout),
and then probably the connection will be made.

The time interval between the two accept in S is probably small. Therefore,
this situation will not happen very frequently. Still, adding a small
queuing function in the kernel on the accepting side would remove the problem
alltogether.

How about letting the server do a new system call? (Let's call it `listen')
This should eliminate the problem completely.

Disclaimer : I can't claim that this is really the way the listen system call
was invented. I only think this is its only use.

	Danny Backx

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 Danny Backx                            |  mail: Danny Backx
 Tel: +32 16 200656 x 3544              |        Katholieke Universiteit Leuven 
 Fax: +32 16 205308                     |        Dept. Computer Science
 E-mail: dannyb@kulcs.UUCP              |        Celestijnenlaan 200 A
         ... mcvax!prlb2!kulcs!dannyb   |        B-3030 Leuven
         dannyb@blekul60.BITNET         |        Belgium     

art@ACC.ARPA (09/09/88)

>Why does this connection queue have to be handled by the kernel?  Why couldn't
>the application just open and initialise for listening (not in the BSD syscall
>sense)  as many transport endpoints as it's queue needs to be long?
>
>Opinions, anybody?

At least for BSD, the kernel will not allow more than one listening socket
to be bound to a particular local endpoint address, but the server wants to
be able to open multiple connections which refer to the same local endpoint
address.  To deal with this, the kernel accepts multiple connections and
queues them at the listening socket.  When an accept system call is issued,
an open connection is associated with a new socket which is then returned
to the user.  One can think of the new socket a "clone" of the listening
socket.

To allow multiple listening sockets to be bound to the same endpoint address
opens up a bunch of ambiguity problems.
(TCP doesn't know if identical services are available on all those sockets)

						Art Berggreen
						art@acc.arpa

------