Re: [tcpm] On the implementation of TCP urgent data (IETF Internet Draft)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tcpm] On the implementation of TCP urgent data (IETF Internet Draft)



Jerry,

On Mar 12, 2009, at 5:32 PM, Jerry Leichter wrote:

On Mar 12, 2009, at 4:45 PM, David Borman wrote:
On Mar 3, 2009, at 10:50 AM, Fernando Gont wrote:

Jerry Leichter wrote:

You refer to the data pointed to by the urgent pointer as the urgent data. This is incorrect. TCP doesn't directly have a concept of urgent
*data*; what it has is an urgent *mode*.
[....]

This was the intent of the text. I'll go through the I-D again and will
try to remove any instances of what you describe.

RFC 793 specifies all three: the urgent pointer, urgent mode, and urgent data. Urgent data is *all* the data before the urgent pointer. Urgent mode is when you are reading the urgent data. What TCP does not have is out of band (OOB) data. Writing just one byte in urgent mode makes all the previously written and unread data urgent data....
A couple of comments:

	- *TCP* has no notion of "unread data" - as it has no notion of
	  *read* data either.  TCP can't possibly be altered to introduce
	  any such concept without first adding in a whole model of
	  the interaction between the TCP stack and its buffering and
	  user mode and its interaction with that buffering.  I can't
	  imagine why you would want to do that - or how you would do it
	  in a way that accurately reflects all existing implementations.

TCP buffers in sequence received data until the application reads it, that is what I mean by unread data. TCP can even buffer data and defer making it available to the application until more data arrives; that is why there is a PUSH bit, so that the sender can indicate that no further data is coming, and any buffered data up to that point should be made available to the application for reading. When you have unread data, and a new packet arrives with the URG bit, all that unread data becomes urgent data.


	- Because of this, "urgent data" is not a very interesting concept.
	  Urgent mode is to some degree, but even that's a mess.  Actual
	  TCP implementations involve two weakly-synchronized state
	  machines, one implementing TCP, one implementing the user code.
	  Urgent mode is a property of the former.  You mention later that
	  you can use the exception flags from select() to tell if you
	  entered urgent mode - one of the synchronization points between
	  the two machines.  However, it's a very limited synchronization.
	  For one thing, entering urgent mode is not the only thing that
	  causes the exception flag to be set - and you have no effective
	  way to check what the bit really means.  For another, if you're
	  executing a read() at user level when a segment with URG bit
	  set arrives, you're stuck.  I suppose you could alternate
	  select()'s with one-byte read()'s, but let's get real here.

You can register for the SIGURG signal to get out of band notification when urgent data has arrived. If you have more than one file descriptor, you can use select() to determine which descriptor has the urgent condition. You then use read() and SIOCATMARK to read the urgent data. You can do reasonable read() calls, because read() will not return data that spans the mark in a single read() call. The mechanisms for dealing with TCP urgent pointer through the socket interface have been around for at least 20 years, since the days of 4.3/4.4 BSD networking, none of this is new.


	- I completely agree with you that TCP doesn't have OOB data.  I
	  said as much.  So?  TCP doesn't "have" ASCII or Unicode or HTTP
	  either.  All of these can be *built on top of* TCP.

	- Then again, *TCP* doesn't have a user API either.  That, too, is
	  built over a TCP implementation.



	- *The socket API* has OOB data.  The implementer's problem is how
	  to build a correct implementation of the socket API's OOB data
	  on top of the TCP primitives.  In fact, as I showed in a separate
	  message to Mr. Gont (which I'd be happy for forward if you're
	  interested; it's a bit long, and I don't want to just dump it
	  on a list of unknown size), it's actually not hard to implement
	  the socket OOB semantics of TCP, using urgent mode, as it is
	  specified today.  The implementation can even be equivalent in
	  performance to today's implementations, for streams that never
	  use OOB data.  It's true that one can improve the implementation
	  by making minor changes to TCP - but realistically the costs
	  would far outweigh the benefits.

In summary: This is not, and has never been, a TCP problem. The issues are at the boundary between the TCP stack and the socket API, affecting code on both sides of that boundary.

The only TCP issue is the mismatch between the definition of the Urgent pointer as being the last byte of the Urgent data, and the typical implementation of it being the first byte of non-urgent data.


Finally, on the question of whether the socket API should be changed to eliminate OOB data: That's perhaps an arguable position, exactly because the implementations are so bad; but the implicit message in the way you state it - that TCP is what matters, and the socket API is just some minor thing - is exactly backwards. There are at most, what, a couple of hundred engineers in the entire world, working on at most a few tens of distinct code bases, who actually deal with *TCP*. There are hundreds of thousands of engineers dealing with millions of applications that depend on the socket API.



Changing TCP is a big job, but one that would be doable if there were sufficient need: Look at IPv6. Changing the socket API is impossible - if you think IPv6 is taking a long time to roll out, that's nothing compared to how long it would take a new, incompatible socket API replacement. Chances are it would never happen.


I never said the socket API should be changed. The mechanisms for dealing with TCP urgent data have existed for a long time. The MSG_OOB flag provides a mechanism for an application to set the Urgent pointer when writing to a TCP socket. On the receiver side, setting SO_OOBINLINE leaves all the TCP data inline (as it should). Using SIGURG, SIOCATMARK and read() (and select() when needed), the application is notified when it should go into Urgent mode, and is able to identify when it has read up to the mark. This all works today. There is nothing to change at either the socket or TCP level.

			-David Borman




                                                       -- Jerry



Note: Messages sent to this list are the opinions of the senders and do not imply endorsement by the IETF.