BRUCE@UMDD.UMD.EDU (Bruce Crabill) (03/13/89)
I've noticed a quirk with a TCP/IP implementation that I'm working with. It has to do with how it handles the PUSH bit on TCP segments that it receives. What is happening is that when a segment is received with the PUSH bit set, it is placed in the client buffer and the client is notified as he should be. However, if another segment comes in before the client picks up the data, the new segment is also appended to the buffer. When the client picks up the buffer, it is marked as having been PUSHed. The problems are that in some cases the second packet won't completely fit in the buffer and will have to be split (or the second packet didn't have the PUSH bit on it). The client is seeing data that is marked as being PUSHed, but in fact it was data earlier in the buffer. I see three possible solutions, do it as RFC 793 implied and don't allow anymore data to be placed in the buffer. This has the drawbacks of wasting buffer space and causes more overhead in that the client needs to be notified more times. Second, don't set the PUSH flag for the buffer if the buffer ends up with the final byte not being the last byte of a PUSHed segment (but still give the buffer to the client ASAP). Third, only allow data to be appended to the buffer if they are also PUSHed and will fit within the buffer. What I guess I'm really asking is what is the exact purpose of the PUSH bit. You could interpret the PUSH bit as a end of logical record marker. Or you could interpret is as simply a mechanism to make sure all the data that is currently in the pipe is pushed out to the client. Since TCP is a stream oriented protocol, it would appear that the latter is the correct interpretation. In which case, any of the above 3 solutions will work. However, the thing that is throwing me is the fact that PUSH data indications are to be given to the client. Why was this done? Does this imply that for every PUSH done on the sending side, their must be a corresponding PUSH indication on the receiver's side? If not, why bother with PUSH indications at all? Bruce
barns@GATEWAY.MITRE.ORG (Bill Barns) (03/13/89)
OK, I'll bite, since I babbled about this in the Host Requirements WG. The PSH bit is definitely NOT a record marker. It is the sending application's means of demanding that the data not be allowed to linger in buffers somewhere between the sending and receiving application. It is fine to deliver some 'non-PSHed' data in the same buffer as the PUSHed data, if there is some of both kinds available for delivery. It is always permitted to deliver any (in-sequence) data that is on hand, regardless of Push. The ABSENCE of Push gives all the intermediate processes permission to buffer the data until there is a Push (or until some other event implying a Push occurs, such as a FIN arriving). It is not required that PSH be transferred one-to-one. Either the sending or receiving TCP may 'collapse' them. The HR RFC (coming soon...) will clarify that providing notification of a Push to a receiving application is optional rather than required. Kindly note, tiny minority of careless readers, that sending a PSH bit at appropriate times is still mandatory. This is important!! Anyhow, the service definition in RFC 793 is somewhat exemplary and contains a few optional features. It is hoped that the text in the HR RFC will clarify all this. (Draft available from venera.isi.edu by anonymous ftp using filename /pub/ietf-hosts.rfc.txt) All of your three solutions are legal, but somewhat distasteful to me, especially #2, which probably "ought" to be illegal. For the case you describe, I think the preferred solution is to fill the buffer as full as possible with any available data, and set the Push indication. Why should a Push indication be passed from the destination TCP to the client application? True, it is often not very useful, and it should never be NECESSARY (if it seems to be necessary to the application, the application/TCP service mapping is flawed, given the facts described above). However, it has a little value once in a while. Here is an example. A few years ago I was working with some timesharing host software which used windows on a 24x80 display terminal and could have connections to various other hosts whose output might be sent to various windows. This was originally designed for a different protocol stack and I added support for TCP connections driving windows. Since bandwidth to the terminal and CPU usage (context switches..) were of some concern, I contrived code such that window repaints were only scheduled when a Push came in for that window. This resulted in fewer process wakeups, better efficiency on the terminal-host interface, and yet allowed a window to be updated pretty promptly when a remote host felt the need to do that. Also, it saved me the nuisance of timer-driven connection polling or some other algorithm which would have taken more effort to code. I thought it worked out pretty well. Bill Barns / MITRE-Washington / barns@gateway.mitre.org
smb@ulysses.homer.nj.att.com (Steven M. Bellovin) (03/13/89)
In article <8903130939.AA05138@ucbvax.Berkeley.EDU>, BRUCE@UMDD.UMD.EDU (Bruce Crabill) writes: > You could interpret the PUSH bit as a end of logical record marker. That is definitely the wrong interpretation. The spec says, many times in many places, that the PUSH bit is *not* a record marker. See, for example, the bottom of page 7 of RFC 1011: Push: There are still some phrases in the document that give a "record mark" flavor to the push. These should be further clarified. The push is not a record mark. > Or you could interpret is as simply a mechanism to make sure all the data > that is currently in the pipe is pushed out to the client. The proper interpretation is that at least all data up to the PUSH point must be delivered promptly. Whether or not more data is delivered is entirely up to the implementation; any interpretation is in conformance with the spec. Applications that assume that the PUSH bit is an end-of- record mark are non-conforming.