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.