alp@hpindwa.cup.hp.com (Arnold Patton) (12/08/90)
I have two questions concerning the implementation of TCP and the
interpretation of RFC-793, specifically concerning connection
shutdown.
Question #1:
In step 8, on page 75, RFC-793 states that:
"If the FIN bit is set, signal the user 'connection closing' and
return any pending RECEIVEs with same message, advance RCV.NXT
over the FIN, and send an acknowledgment for the FIN. Note that
FIN implies PUSH for any segment text not yet delivered to the
user."
Notice that the RFC does not mention checking the current RCV.NXT
value against the FIN sequence number. If one were to interpret this
literally, then it would seem that one would accept the FIN and change
states even if there were still holes in the TCP reassembly queue due
to lost or dropped packets (assuming that we are doing the right thing
and not accepting only in-order packets). If that is the intent of
the RFC, then the statement about PUSHing any text not yet delivered
is ambiguous or at least not detailed enough, since it is possible to
have data both before and after a hole in the reassembly queue. Do we
push only the data before the hole? Or do we push all the data and
ignore the hole?
It seems to me that this was not the intent of the RFC, and that the
assumption was being made that there would not be any holes in the
reassembly queue (which is normally the case) when the FIN is
received. In my understanding, the FIN handshake was intended to
insure that all data has been received by both sides. The "literal
interpretation" above would defeat this attribute of the FIN handshake.
I thought that perhaps HOSTS RFC (RFC 1122) had clarified RFC-793's
statement, but it does not. In fact, when I checked a copy of the BSD
4.3 TCP code, it appears that they indeed accept the FIN no matter
what! (However, I haven't tested the actual behavior of the code, and
I may have overlooked something. It would be difficult to believe
that the BSD code would behave this way.)
Also, if you do not accept the FIN right away, what do you do with it?
Options seem to be either set some state vector or to drop the FIN
packet and to pick it up in a retransmission after your reassembly
queue has been filled. The second option would cause a delay in
waiting for the retranmitted FIN, and has a potential danger in that
if the retransmitted FIN is dropped in between (say at a gateway), the
remote connection half may time out. However, the first option also
has the preformance penalty of always needing to check against this
new state vector to see if we should accept the FIN now.
Does the standard really intend some sort of bizarre behavior here?
Or does someone know of a reference in the standards which clarifies
things? What behavior do BSD SOCKETS and other ULPs based on TCP
expect? Or have I missed the boat entirely and overlooked something
in RFC-793?
Question #2:
This question also regards TCP connection shutdown implementations.
I thought that I read somewhere (I thought it was HOSTS RFC) that if
you get a FIN without an ACK of FIN while you are in the FINWAIT1
state that you should reply with a FIN, ACK of FIN packet (not just
ACK of FIN as RFC-793 states), but I can no longer find the reference.
I can see why you might want to do this, but I think it would work either
way.
Was I just imagining things? Or does someone know of such a reference?
If you could pass it on to me, it'd be much appreciated.
-------------------------------------------------------------------------------
Arnold Lee Patton | MPE/XL Networking Engineer | I wonder how much time is
Hewlett-Packard Co. | alp@hpindwa.cup.hp.com | spent figuring out clever
| | notes for this space.
-------------------------------------------------------------------------------
dls@mentor.cc.purdue.edu (David L Stevens) (12/08/90)
If you check in the beginning of the "SEGMENT ARRIVES" section of RFC 793, it says that they assume packets have already been sequenced in proper order for the rest of it. Re: shutdown(2) in BSD implementations. It corresponds roughly to the TCP ABORT function, but not quite. In particular, as the manual page says, any buffered data pending will be dropped. It isn't really the "half close" that RFC 793 wants, and it should only be used in programs that are aborting or, because of mechanisms in the application protocol, already know that the data has been delivered. It should *not* be used for applications that have done writes and just want to mark the end of data for the peer, since any data still pending in the local send buffers is discarded and never delivered. -- +-DLS (dls@mentor.cc.purdue.edu)
thomson@hub.toronto.edu (Brian Thomson) (12/11/90)
In article <2452@mentor.cc.purdue.edu> dls@mentor.cc.purdue.edu (David L Stevens) writes: > Re: shutdown(2) in BSD implementations. It corresponds roughly to >the TCP ABORT function, but not quite. In particular, as the manual page >says, any buffered data pending will be dropped. It isn't really the >"half close" that RFC 793 wants, and it should only be used in programs >that are aborting or, because of mechanisms in the application protocol, >already know that the data has been delivered. It should *not* be used for >applications that have done writes and just want to mark the end of data for >the peer, since any data still pending in the local send buffers is discarded >and never delivered. I think the original question was about the TCP shutdown procedure, not the BSD shutdown() system call, but this answer caught my attention because it seems to contradict everything I thought I knew about the BSD routine. My understanding is as follows: shutdown(s, 0) - flushes data queued for receive, and shrinks my receive window to zero. Succeeding reads will fail. shutdown(s, 1) - data already queued will be delivered, followed by a FIN. Succeeding writes will fail. shutdown(s, 2) - equivalent to { shutdown(s, 0); shutdown(s, 1); } The second of these is precisely the orderly half close. None of them performs the TCP ABORT function. And, to top it off, my manual pages (Sun) say nothing about loss of buffered data pending. -- Brian Thomson, CSRI Univ. of Toronto utcsri!uthub!thomson, thomson@hub.toronto.edu
dls@mentor.cc.purdue.edu (David L Stevens) (12/11/90)
In article <1990Dec10.131116.19393@jarvis.csri.toronto.edu>, thomson@hub.toronto.edu (Brian Thomson) writes: > > I think the original question was about the TCP shutdown procedure, not the > BSD shutdown() system call, but this answer caught my attention because it > seems to contradict everything I thought I knew about the BSD routine. > My understanding is as follows: > shutdown(s, 0) - flushes data queued for receive, and shrinks > my receive window to zero. Succeeding reads will > fail. > shutdown(s, 1) - data already queued will be delivered, followed > by a FIN. Succeeding writes will fail. > shutdown(s, 2) - equivalent to { shutdown(s, 0); shutdown(s, 1); } > ... > > And, to top it off, my manual pages (Sun) say nothing about loss of > buffered data pending. Sorry, I had forgotten where I saw it. It isn't in the man page, and I originally came across it in the code, but I knew there was a documentation reference as well. The "IPC Primer" (section 2.6) says: "....Applying shutdown to a socket causes any data queued to be immediately discarded." Also, from the "Advanced 4.3BSD IPC Tutorial" (PS1:8-8): "Once a socket is no longer of interest, it may be discarded by applying close to the descriptor, close(s); If data is associated with a socket which promises reliable delivery (e.g., a stream socket) when a close takes place, the system will continue to attempt to transfer the data. However, after a fairly long period of time, if the data is still undelivered, it will be discarded. Should a user have no use for a any pending data, it may perform a shutdown on the socket prior to closing it." -- +-DLS (dls@mentor.cc.purdue.edu)
dls@mentor.cc.purdue.edu (David L Stevens) (12/11/90)
More information: I looked briefly through our (4.3 Tahoe) code and it does in fact appear to do shutdown(2) as the "half-close" that you (and I) want it to do. That is, it doesn't deallocate the send buffer until the final close and it does appear to go into TIME_WAIT, instead of just deallocating the TCB. So, if you trust my cursory reading of the current code and you don't take the documentation I quoted too literally, then shutdown(2) appears to be safe after a write, even if it's buffered, in at least 4.3 Tahoe. :-) I unfortunately don't have time to look at it in detail enough to turn the "appears to be safe" to just "is safe" right now, but if anyone else does, I'd like to see what you find. -- +-DLS (dls@mentor.cc.purdue.edu)
george@na.excelan.com (George Powers) (12/29/90)
> In article <1990Dec10.131116.19393@jarvis.csri.toronto.edu>, thomson@hub.toronto.edu (Brian Thomson) writes: > > > > I think the original question was about the TCP shutdown procedure, not the > > BSD shutdown() system call, but this answer caught my attention because it > > seems to contradict everything I thought I knew about the BSD routine. > > My understanding is as follows: > > shutdown(s, 0) - flushes data queued for receive, and shrinks > > my receive window to zero. Succeeding reads will > > fail. > > shutdown(s, 1) - data already queued will be delivered, followed > > by a FIN. Succeeding writes will fail. > > shutdown(s, 2) - equivalent to { shutdown(s, 0); shutdown(s, 1); } > > ... > > > > And, to top it off, my manual pages (Sun) say nothing about loss of > > buffered data pending. Having read the 4.3BSD source and tested SUNOS 4.0, I agree with Brian. Shutdown is typically useful when applied to the send direction. The application program can then keep reading until it gets an EOF, meaning that the peer application has seen the EOF which shutdown caused, and has closed in response. Therefore the application which initiated the shutdown can be sure that all data has been delivered in both directions. If an application has no other way of confirming delivery and closes without the shutdown method, it cannot tell whether enqueued send data is lost after close detaches the socket from its file descriptor. -- UUCP: {ames,sun,apple,mtxinu,cae780,sco}!novell!george George Powers Internet: george@novell.com --