Discussion:
[lwip-users] TCP [TCP Window Update]
Alain Mouette
2009-08-07 21:56:17 UTC
Permalink
Hi, I am getting quite a lot of these in WireShark:

TCP [TCP Window Update]

0) I am using the socket interface :)
1) lwip sends a 15 byte packet to the server
2) the server responds an 11 byte packet, with ACK
3) lwip sends an ACK with a reduced window, from 2048 to 2037, delay is
between 5 and 66ms
4) lwip sends an extra ACK with the full window size, delay is around 250ms.
5) next packet is sent usualy many minutes later...

What I can understand that is happening is this: I take a little too
long to read the received data. I am using select to poll for data, with
1ms delay, but it is with FreeRTOS and so it might take a little longer
sometimes...

My question is: is there a way to delay that ack so that it only goes
after I read the data? Or store it somewhere (like buffers)?

This is to be with GPRS and I am getting over 20% extra trafic just for
that :(

Thanks,
Alain
g***@gmx.de
2009-08-09 08:11:35 UTC
Permalink
Unfortunately, I think there is currently no way to change this
behaviour when using the socket API. The reason is this:
1) the ACK packet gets sent from the tcpip_thread, when the received
data is put into the mbox.
2) Then there's a thread change to your application thread. After
reading the data from that thread,
3) there's again a thread change back to tcpip_thread to tell the stack
the data is actually processed.

Step three results in the window being changed. However, the window
update is not sent right away but after 250 ms (delayed ACK mechanism):
with full duplex application-protocols, the window update would just be
sent with the next packet. Since you don't send a packet in this
timespan, an extra packet is generated for the window update.

Looking at the steps above, it would not even matter if your application
was faster than 1ms, it's just the way lwIP is designed currently.

You *could* change the behaviour if you would use the raw API and tell
the stack about the window update right away - but I guess that would be
a pretty big change to your application. Another way to solve it would
be to set a new flag in the pcb and update the window when putting the
data into the mbox (when that flag is set) - however, that would mean
you have to change the lwIP core code - or you'd have to wait until such
a behaviour is implemented in CVS.

Simon
Post by Alain Mouette
TCP [TCP Window Update]
0) I am using the socket interface :)
1) lwip sends a 15 byte packet to the server
2) the server responds an 11 byte packet, with ACK
3) lwip sends an ACK with a reduced window, from 2048 to 2037, delay is
between 5 and 66ms
4) lwip sends an extra ACK with the full window size, delay is around 250ms.
5) next packet is sent usualy many minutes later...
What I can understand that is happening is this: I take a little too
long to read the received data. I am using select to poll for data, with
1ms delay, but it is with FreeRTOS and so it might take a little longer
sometimes...
My question is: is there a way to delay that ack so that it only goes
after I read the data? Or store it somewhere (like buffers)?
This is to be with GPRS and I am getting over 20% extra trafic just for
that :(
Thanks,
Alain
_______________________________________________
lwip-users mailing list
http://lists.nongnu.org/mailman/listinfo/lwip-users
Kieran Mansley
2009-08-10 10:30:54 UTC
Permalink
Post by g***@gmx.de
Step three results in the window being changed. However, the window
with full duplex application-protocols, the window update would just be
sent with the next packet. Since you don't send a packet in this
timespan, an extra packet is generated for the window update.
Looking at the steps above, it would not even matter if your application
was faster than 1ms, it's just the way lwIP is designed currently.
You *could* change the behaviour if you would use the raw API and tell
the stack about the window update right away - but I guess that would be
a pretty big change to your application. Another way to solve it would
be to set a new flag in the pcb and update the window when putting the
data into the mbox (when that flag is set) - however, that would mean
you have to change the lwIP core code - or you'd have to wait until such
a behaviour is implemented in CVS.
I haven't looked at the code in question, so this might not make total
sense, but from what you describe you could tailor lwIP to your current
application by either (i) getting the tcpip_thread to just use tcp_ack()
rather than tcp_ack_now(), so it too would use the delayed ACK
mechanism, and then your window update would be combined with the normal
ACK; and/or (ii) change the window update threshold so that you don't
always send a window update for such small changes in the window. To be
honest I'm a bit surprised that lwIP sends a window update for a change
of just 11 bytes. Which version of lwIP are you using?

Kieran
Alain Mouette
2009-08-10 23:49:01 UTC
Permalink
Post by Kieran Mansley
Post by g***@gmx.de
Step three results in the window being changed. However, the window
with full duplex application-protocols, the window update would just be
sent with the next packet. Since you don't send a packet in this
timespan, an extra packet is generated for the window update.
Looking at the steps above, it would not even matter if your application
was faster than 1ms, it's just the way lwIP is designed currently.
You *could* change the behaviour if you would use the raw API and tell
the stack about the window update right away - but I guess that would be
a pretty big change to your application. Another way to solve it would
be to set a new flag in the pcb and update the window when putting the
data into the mbox (when that flag is set) - however, that would mean
you have to change the lwIP core code - or you'd have to wait until such
a behaviour is implemented in CVS.
I haven't looked at the code in question, so this might not make total
sense, but from what you describe you could tailor lwIP to your current
application by either (i) getting the tcpip_thread to just use tcp_ack()
rather than tcp_ack_now(), so it too would use the delayed ACK
mechanism, and then your window update would be combined with the normal
ACK; and/or (ii) change the window update threshold so that you don't
always send a window update for such small changes in the window. To be
honest I'm a bit surprised that lwIP sends a window update for a change
of just 11 bytes. Which version of lwIP are you using?
I am using lwip 1.3.0.

the (ii) option seems to fullfill my needs :) can you give me a hint on
where to look for that? Bigger packet sizes are not important because
they don't happen very often and thus wil cause no traffic cost problem.

Alain
Kieran Mansley
2009-08-11 08:01:39 UTC
Permalink
Post by Alain Mouette
I am using lwip 1.3.0.
The window update code changed significantly between 1.3.0 and 1.3.1, so
it might be worth upgrading to see if this has already been solved for
you. There were some problems with the old code, so it was completely
re-written.
Post by Alain Mouette
the (ii) option seems to fullfill my needs :) can you give me a hint on
where to look for that? Bigger packet sizes are not important because
they don't happen very often and thus wil cause no traffic cost problem.
In tcp_recved() (src/core/tcp.c) there is now some code that looks like
this:

/* If the change in the right edge of window is significant (default
* watermark is TCP_WND/2), then send an explicit update now.
* Otherwise wait for a packet to be sent in the normal course of
* events (or more window to be available later) */
if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD)
tcp_ack_now(pcb);

You should be able to configure TCP_WND_UPDATE_THRESHOLD and see the
change that you require, but with the current code it will only send an
explicit window update if there is a change greater than half the window
(so a lot more than 11 bytes!)

Kieran

Loading...