[comp.protocols.tcp-ip] FIN_WAIT_2, LAST_ACK, and PRU_DISCONNECT

epg@cwi.nl (Ed Gronke) (06/29/87)

I have been having a problem with rsh that I thought that I should refer to the
net. The problem has to do with outstanding send data 
(the socket send queue is non-zero) and in the CLOSE_WAIT state
that receives a PRU_DISCONNECT (through a the final close of stdout of the
child process of the rshd when it exits) when the other side of the socket
(the originator) has already entered the FIN_WAIT_2 state.

In a diagram:

Originator                Reciever      Recieve user

FIN_WAIT_2                CLOSE_WAIT     PRU_DISCONNECT
(no further sends)       /              /
                        /              /
                 (DATA)/              /
                      /   LAST_ACK
                     /    (treated like a close but
                    /      doesn't generate a fin
                           FIN and also marks socket
(send ack of data)         for no further reads or writes)
                   \
                    \

What happens after this seems to be this. There is one more input processed (the
ACK of the previous data which also updates the send window to 800 (it was 0))
process and one more output is processed. The trpt output is as follows:


371 CLOSE_WAIT:output [ecd0603..ecd0a03)@16b69885(win=1000)<ACK> -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0203 snd_nxt ecd0a03 snd_max ecd0a03
	snd_wl1 16b69885 snd_wl2 ecd0203 snd_wnd c00
372 CLOSE_WAIT:output [ecd0a03..ecd0e03)@16b69885(win=1000)<ACK,PUSH> -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0203 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0203 snd_wnd c00
372 CLOSE_WAIT:user SEND -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0203 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0203 snd_wnd c00
377 CLOSE_WAIT:input 16b69885@ecd0e03<ACK> -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 0
377 CLOSE_WAIT:user SEND -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 0
379 CLOSE_WAIT:user SEND -> CLOSE_WAIT
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 0
			/* Here is the disconnect. the child of the rsh has died and
			 * done the close (in exit) */
389 CLOSE_WAIT:user DISCONNECT -> LAST_ACK
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 0
	/* The last ack processed, snd_wnd: 0 -> 800 */
532 LAST_ACK:input 16b69885@ecd0e03(win=800)<ACK> -> LAST_ACK
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd0e03 snd_max ecd0e03
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 800
532 LAST_ACK:output [ecd0e03..ecd1203)@16b69885(win=1000)<ACK> -> LAST_ACK
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd0e03 snd_nxt ecd1203 snd_max ecd1203
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 800

	/* The only difference with this case and above is that the snd_wnd is
	 * not = 0, as far as I can tell */
	 
534 LAST_ACK:drop 16b69885@ecd1203(win=c00)<ACK> -> LAST_ACK
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd1203 snd_nxt ecd1203 snd_max ecd1203
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 400
015 LAST_ACK:user SLOWTIMO<KEEP> -> LAST_ACK
	rcv_nxt 16b69885 rcv_wnd 1000 snd_una ecd1203 snd_nxt ecd1203 snd_max ecd1203
	snd_wl1 16b69885 snd_wl2 ecd0e03 snd_wnd 400


So, my question is this:

What should be the response to a user DISCONNECT request? (Should it be
the same as CLOSE? )

(For those interested, the relevant pieces of code are in tcp_input.c: tcp_input
 in the section related to responding to an ack and in tcp_usrreq.c:tcp_disconnect()
and tcp_usrreq.c:tcp_usrclosed()).

If anyone knows of a fix or can explain to me why 4.3 tcp goes from CLOSE_WAIT
to LAST_ACK without generating a FIN and also why tcp_input is dropping the input
and/or whether this is related to no output being generated. (Should there be
a timeout to flush the mbuf's on a connection in the LAST_ACK state?)

-- Ed Gronke (epg@cwi.nl or mcvax!epg)