Hello everyone,

I have found uncommon issues in the TCP protocol that may be of interest to
you. This is a quite long post.

Before anything else, I do not use uIP. I use a self-made minimal TCP/IP
stack that is tailored specifically to a particular chipset and somewhat
tailored to the particular use that I have for it. That use is streaming
audio from Shoutcast & Icecast servers, which use (slightly modified) HTTP
for the data transfer. I do, however, look into the uIP source code for
guidance when the RFCs toy with my sanity.

In my stack, I set the TCP MSS to 512. I set the TCP window to twice the
MSS, though. I have noticed that both Linux and Microsoft Windows hosts will
send you packets of at most half the size of the window. I blame this to a
side effect of the Nagle algorithm (in the Nagle algorithm, a receiver sends
a single ACK for every two incoming packets, therefore a transmitter should
send at least two packets, whose summed size does not exceed the receiver's
window).

When streaming audio (from a Microsoft Windows Icecast server), I have
noticed that sometimes I receive a packet that contains partially old data
and partially new data. Say that I have already received and acknowledged
10000 bytes, and I get a packet with sequence number 9800 and size 500. If I
ignore this packet and send a new acknowledgement for 10000 bytes, I get the
same packet again (sequence number 9800, size 500). Repeating it a few times
does not help. I guess that the complete packet is kept in a queue for
retransmission and that the Windows host feels that I should just accept the
packet because 9800 + 500 is greater than my ACK number.

The fix is to process the 300 new byes and ACK these. This applies to uIP
too. In version 1.9 (that I just downloaded), line 1407 tests whether the
sequence number matches exactly the one that was expected. This was also my
strategy, and it will therefore fail similarly when a packet with
overlapping data is received.

One side remark: overlapping data packets are uncommon. I saw 4 of such
packets in 90 minutes of test streaming at 128 kb/s, which gives an average
of one "glitch" in every 20 megabytes received.

A second issue is even rarer: out of order reception. My window is 1024 and
my MSS is 512. It has happened that I receive a packet that drops into the
high part of the window before I get the packet that drops into the low part
of the window. So, let's say that I have received and acknowledged 10000
bytes and I am expecting a packet with 10001 to 10512, but I get 10513 to
11024. Dropping the packet and sending an ACK for 10000 does not help, I get
the same packet again.

Blame yourself, one might say, you put the window at 1024 bytes, so you
should not complain when you get what you asked for. However, this could
arrive, too, if the window size is the same as the MSS. Out of order
reception is just part of the TCP protocol. If you cannot handle it, bad
luck.

I cannot handle out of order reception. Since I lack RAM for sufficiently
large buffers, I am using a serial buffer. What I have implemented is to
reduce the TCP window once I get an out-of-order packet (and send an ACK
with the sequence number that I wish to receive next). If the remote host
monitors the window size, as it should, it cannot resend the packet, because
it is now beyond the window. I do not know yet if this works, because an
out-of-order reception has not happened since I implemented this (I have
only done a 90 minutes streaming audio test as of now).

Again, in uIP, this would need a modification of handling a received TCP
data packet.

I hope this is useful for anyone. I realise that uIP is probably used more
often for transmitting data rather than receiving data, and that the amount
of data typically is not as large as it is with streaming audio.
Anyway, best regards,
Thiadmer

Reply via email to