[comp.protocols.tcp-ip] Proper handling of PUSH & small window by sender?

hascall@cs.iastate.edu (John Hascall) (02/13/90)

 [I sent this a few days ago (probably with a different subject), but
  never saw it here, so I'm trying again (sorry if you got this twice).]

   Hi!

      I am working on a TCP implementation and have a question about
   the proper handling of PUSH by the sender which doesn't seem to
   be addressed (at least clearly) in any RFC I can find.   I would
   greatly appreciate any information anyone might have.

      Say you have two chunks of data (chunk1 and chunk2) from the user
   and chunk1 was PUSHed but chunk2 was not.  These two chunks have been
   held for whatever reason (window closed, unACKed data, whatever).
      Now, however, you are clear to send, I see three cases (associated
   with three different window sizes) and I am unsure what is the "right"
   thing to do in any of them.


         3 3 3 3 3 3 3 3 3 3 4 4|4 4 4 4 4 4 4 4 5 5 5     (example sequence
         0 1 2 3 4 5 6 7 8 9 0 1|2 3 4 5 6 7 8 9 0 1 2      number space)
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |         chunk1        |        chunk2       |
        +-+-+-+-+-+-+-+-+-+-+-+p+-+-+-+-+-+-+-+-+-+-+-+

 case 1 |<--window--->|
 case 2 |<----------window----------->|
 case 3 |<--------------------window--------------------->|
     

    Case 1:  do I hold off, waiting for a bigger window?  (deadlock?)
             do I send what I can?                        (efficiency?)

    Case 2:  do I hold off, waiting for a bigger window?  (doesn't seem right)
             do I send only chunk1 (setting PUSH)         (my current guess)
             do I send all I can (setting PUSH)           (too much pushed?)

    Case 3:  do I send only chunk1 (setting PUSH)         (correct?)
             do I send it all (setting PUSH)              (too much pushed?)


Thanks for any help, pointers, references you might have,
John Hascall  /  Iowa State Univ  /  hascall@atanasoff.cs.iastate.edu

dls@mentor.cc.purdue.edu (David L Stevens) (02/13/90)

In article <589@dino.cs.iastate.edu>, hascall@cs.iastate.edu (John Hascall) writes:
>         +-+-+-+-+-+-+-+-+-+-+-+p+-+-+-+-+-+-+-+-+-+-+-+
>  case 1 |<--window--->|
>  case 2 |<----------window----------->|
>  case 3 |<--------------------window--------------------->|
> 
>     Case 1:  do I hold off, waiting for a bigger window?  (deadlock?)

	I'd say this depends on how big a segment you can send. If you can
send multiple full segments for chunk1, send all the full segments you can
up to the window (no "PUSH" set). When the window opens past chunk1, you
send that segment promptly (full or not) with PUSH set.

>     Case 2:  do I hold off, waiting for a bigger window?  (doesn't seem right)
>              do I send only chunk1 (setting PUSH)         (my current guess)
>              do I send all I can (setting PUSH)           (too much pushed?)

	I say the 3rd, because it says that "...PUSH bit will be set in the
last TCP segent created from the buffer." Since PUSH is not a record mark,
that segment can contain other data as well. It should not WAIT for other
data (buffering), but if the data is there already... In other words, this
interpretation is "send AT LEAST chunk1 promptly." Since PUSH is to avoid
buffering delays (and NOT, for example, for URGENT data), it's ok to use
the extra buffer the receiver has told you he has. The user will get a more
full buffer on his receive (better) and that's ok, because PUSH is not a
record mark.

>     Case 3:  do I send only chunk1 (setting PUSH)         (correct?)
>              do I send it all (setting PUSH)              (too much pushed?)

	Send it all. Set PUSH in the segment containing data that corresponded
to the last octets of "chunk1". Again, if the receiver has the buffer space, it
makes everything better.
-- 
					+-DLS  (dls@mentor.cc.purdue.edu)

BILLW@MATHOM.CISCO.COM (William "Chops" Westfield) (02/16/90)

PUSH is currently considered rather a bad idea.  It is more of a
user->tcp level thing, as opposed to something that belongs in the
protocol layer.

You should be doing Silly Window Syndrome avoidance regardless of
whether the user sets the PUSH bits, etc.

In theory, once you hand both chunks to the TCP, the boundry between
them dissappears, so if they both fit within a single packet, both
case 2 and case 3, you should probably send a single packet with the
push bit set (offhand, though, it sounds like your application is
not using PUSH correctly - you should read what the hosts requirement
RFC (RFC1122) says about push.)

        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |         chunk1        |        chunk2       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 case 1 |<--window--->|
 case 2 |<----------window----------->|
 case 3 |<--------------------window--------------------->|

BillW
-------

narten@CS.ALBANY.EDU (Thomas Narten) (02/20/90)

>PUSH is currently considered rather a bad idea.  It is more of a
>user->tcp level thing, as opposed to something that belongs in the
>protocol layer.

I'm not sure that PUSH can be swept under the rug as a "bad idea".  It
is a necessary compromise between deadlock avoidance and inefficiency.
For efficiency reasons, the transport layer wants to delay sending
data in order to coalesce several application write operations into a
single outgoing datagram.  (Likewise, the receiving TCP module might
delay handing data to the application layer until more data arrives.)
If the application sends one byte and then waits for a response,
however, delaying the sending of the data byte may produce a deadlock.
Applications use the PUSH operation to prevent the latter case.  It
directs TCP "flush its buffers" and hand any buffered data (up to the
PUSH mark) to the remote application.  In addition, PUSH does belong
in the protocol layer because it is the only way that the sending TCP
module can direct the receiving TCP module to flush its buffers.

Thomas Narten