lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] Zero window and refused data problem


From: Valery Ushakov
Subject: Re: [lwip-users] Zero window and refused data problem
Date: Wed, 9 Nov 2016 00:15:37 +0300
User-agent: Mutt/1.6.1 (2016-04-27)

On Tue, Nov 08, 2016 at 09:53:52 +0100, Simon Goldschmidt wrote:

> 2) after storing a segment in "refused_data", no more ACKs are sent
> 
> The whole purpose of "refused_data" was to let the stack behave like
> a buffer overflowed: if your device cannot handle incoming data in
> the speed it is sent by the remote host, the remote host should
> throttle its sender. This is achieved by not handling/not answering
> a packet at all, just like it was dropped due to congestion. This
> should bring the remote host's TCP to send less. ACKing an old seqno
> instead might work for you, but I don't know what will be the result
> for all remote stacks, so I'm very reluctant to change this...
> 
> As you can see from this, TCP is meant to achieve the highest
> possible throughput possible for the combination of remote host,
> network and local host. What you want instead to make it a queue
> that keeps up a connection as long as possible without data being
> exchanged. I'm not fully convinced one can coexist with the other,
> but please come up with suggestions of how to fix this ;-)

I don't want to argue this for the general case but for the specific
zero window case this argument doesn't apply, I think, and quite
obviously (IMHO) so.

A PCB with zero window *explicitely* tells the peer to stop sending by
specifying zero window, so you don't have to pretend incoming packets
were lost and hope that the remote stack will correctly *infer* it
needs to throttle.  You just *tell* it to.

RFC1122 uses a printer out of paper as an example for zero window
state, something that can take ages (relatively speaking) to resolve
since it requires user intervention.  Stopping sending ACKs in this
case is problematic, since it causes connection to be aborted
relatively quickly.

RFCs actually do want zero window state to be able to "keep up a
connection as long as possible without data being exchanged".

E.g. RFC1122 says

     A TCP MAY keep its offered receive window closed indefinitely.
     As long as the receiving TCP continues to send acknowledgments in
     response to the probe segments, the sending TCP MUST allow the
     connection to stay open.

(There's RFC6429 that talks about potential for using that as a DoS
attack on the sender, but that's not what we are concerned about
here).

I think there are two options when the zero window probe may be
accepted because a tiny window has opened, but the window is still
small enough to advertise b/c we are avoiding silly window syndrome.

One course of action would be to ignore the probe.  It is most likely
partial data anyway, a byte borrowed from the next full batch that
will be sent when the window opens enough to advertise it.

Alternatively we can accept the probe as refused data, but then we
should relax the logic that decides to not send any ACKs when refused
data is present and do send the ACK if it also announces zero window.
In this case we can expect the next probe soon, that we will have to
reject and keep acking the first one.

The first option probably makes more sense in general as it will not
bother the app with that single probe byte that the app likely can't
process in isolation anyway.

But thinking a bit more about it - the refused data might have been
the last packet that completely filled the window and in this state we
want to send those acks with zero window when we have refused data
that was not a probe.

So i guess both bits of logic need to be implemented - refusing probes
if we can't advertise non-zero windows and keep sending the old ack,
and sending acks when refused data is present if the window is zero.

I don't think we should worry about the reaction of "all remote
stacks" to this as anything is better than actively causing the
connection to get aborted by not responding.

It might be argued indeed that the application shouldn't be "misusing
TCP as a queue", but I don't think punishing it with aborted
connections is proportional punishment.  If remote stacks will exhibit
suboptimal behaviour - *shrug* the app really shouldn't be misusing
TCP as a queue :), but at least lwip made its best effort (e.g. you
don't expect a kernel panic when you remove a file that doesn't
exist).

-uwe



reply via email to

[Prev in Thread] Current Thread [Next in Thread]