yarran@ccicpg.UUCP (Yarran A Lu) (10/22/88)
In implementing connection-oriented protocol module there is a problem when the next downstream module/driver is also a connection-oriented protocol. The listening queue which is connected to the next downstream module/driver is used to receive connect.indication primitives and seems it is better to be always kept in the listening state. When the module gets the connect.ind primitive, it responds back to the lower layer module/driver with a connect. response primitive in order to accept the call. The problem arises on whether the listening module should accept the call on the listening queue or create a new queue to accept the call. In the former case, the listening queue will be changed into data transfer state and no more connect.indication primitives can be put into the queue anymore, until the user process finally receives the call and create a second queue to accept the call (by using ioctl I_FDINSERT). During this period, all the following connect.indications have to be either queued in the lower layer module/driver or be discarded. In the latter case, unfortunately, AT&T did not supply any STREAMS function call for creating a queue between modules. Of course, you can probably avoid this case by implementing it as a mux driver and pre-allocate all the queues. But this approach is undocumented and seems violate the original intent of mux driver. Is there any STREAMS guru or AT&T STREAMS architect knowing the answer?
yarran@ccicpg.UUCP (Yarran A Lu) (10/29/88)
Reading the responses to my question, I feel that it is necessary to explain this question in more detail again. The responses so far all misunderstood what I was asking for. >In implementing connection-oriented protocol module there is a problem when >the next downstream module/driver is also a connection-oriented protocol. >The listening queue which is connected to the next downstream module/driver is >used to receive connect.indication primitives and seems it is better to be >always kept in the listening state. When the module gets the connect.ind >primitive, it responds back to the lower layer module/driver with a connect. >response primitive in order to accept the call. The problem arises on whether >the listening module should accept the call on the listening queue or create >a new queue to accept the call. In the former case, the listening queue will >be changed into data transfer state and no more connect.indication primitives >can be put into the queue anymore, until the user process finally receives the >call and create a second queue to accept the call (by using ioctl I_FDINSERT). >During this period, all the following connect.indications have to be either >queued in the lower layer module/driver or be discarded. In the latter case, >unfortunately, AT&T did not supply any STREAMS function call for creating >a queue between modules. Of course, you can probably avoid this case by >implementing it as a mux driver and pre-allocate all the queues. But this >approach is undocumented and seems violate the original intent of mux driver. Let's see the following figure: ________________ | user process | ---------------- user space | | queues 1 _______________________________________________ | head | kernel space ----------- | | queues 2 ---------------- | module X | layer N ---------------- | | queues 3 ---------------- | module Y or | | driver Y | layer N-1 ---------------- Assumption: user process, module X and module Y all handle connection oriented protocols. The scenario is as follows: 1) User process has done open and bind. The bind primitive also indicated it wants to receive multiple connect.indication in read queue 1. 2) Module Y receives (N-1) peer-to-peer connect.indication PDU and sends the connect.indication primitive to module X. 3) If module X accepts the (N-1)connect.indication primitive, it would have to send downstream a (N-1) connect.response primitive to module Y. If queue 3 is used to accept the call, queue 3 will enter into data transfer state and it will no longer be available for module Y or X to receive further incoming (N-1)connect.indication. Let's assume now that queue 3 enters into data transfer state. 4) The remote layer (N) sends a connect.indication PDU embeded in layer N-1 data PDU. Module Y receives (N-1) data PDU and sends the (N-1)data.indication primitive to module X upstream. 5) Module X receives the (N-1)data.indication which contains (N)connect.ind PDU. Module X in turn sends a (N)connect.indication primitive upstream to user process through read queue 1. 6) User process will open and bind a new stream and accept the call by sending downstream a connect.response primitive to module X. In which, it tells the module X that it really wants to accept the call on the new stream, not queue 1. This way, queue 1 can always be in listening state being able to receive multiple connect.indications. The new queue of course will enter into data transfer state. Now let's see what my question really is: After step 3, if there is another (N-1)connect.indication PDU arrives at module Y, there will be no upstream queue in listening state to take the (N-1)connect.indication primitive. One may suggest that the new stream created after step 6 may be used to replace the old stream. But there is no guaranty that after the (N-1)layer connection is established, when the (N) layer connect.indication will come (sometime a connection is always maintained alive and can be reused again by the upper layer). The ideal solution, I think, is that the module should have the same ability, like the user process has, to create a new queue when it accepts the lower layer connect.indication. However, there is no STREAMS functions provided by AT&T to manipulate the queues. I hope this will clarify the question now. Thanks for all the good will.
bae@unisoft.UUCP (Hwa Jin Bae) (10/31/88)
Yarran A Lu's question was: "...... After step 3, if there is another (N-1)connect.indication PDU arrives at module Y, there will be no upstream queue in listening state to take the (N-1)connect.indication primitive. One may suggest that the new stream created after step 6 may be used to replace the old stream. But there is no guaranty that after the (N-1)layer connection is established, when the (N) layer connect.indication will come (sometime a connection is always maintained alive and can be reused again by the upper layer). The ideal solution, I think, is that the module should have the same ability, like the user process has, to create a new queue when it accepts the lower layer connect.indication. However, there is no STREAMS functions provided by AT&T to manipulate the queues. ....." This is a good point. However, you don't need a STREAMS function to solve this problem. What's needed is some extra data structure and code within module X to take care of the multiple connections. Usually when implementing TCP, a pool of TCB's and sockets are allocated in the beginning. The number of connections that a socket is willing to accept is recorded in socket data structure when the user makes a 'listen()' call. Then module X is sent a T_BIND_REQ message with CONIND_number field equal to that number. With an extra function (call it "listen_one_at_a_time()") that will go through TCB's and make up a new TCB (which has a pointer to the socket queue; we are talking about a socket as implemented as a STREAM head here) and change the state of this TCB to T_WCON_IND. That is, instead of one-to-one correspondence between socket and TCB, you can utilize the same queue (allocated to a socket) for multiple TCB's which may be in various states. /hjb -- ----------- "I am no Jack Kennedy." ------------------------------ Hwa Jin Bae bae@tis.llnl.gov (Internet) UniSoft bae@unisoft.UniSoft (smail uucp) Emeryville, CA ...!uunet!unisoft!bae (plain uucp)