From f0ba8f6aca070164190a769a09099e935ff3aa11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Mon, 11 Mar 2019 00:31:10 +0100 Subject: [PATCH] TCP: Fix Zero Window Probes. I did some tcpdump recording, and I believe we confuse the receiver with our Zero Window Probe, because we don't resent even though it only ACKs the previous segment, and we keep sending things after it: * we send the last segment before window is closed, next seg = N, * we get ACK for N, with window=0 * we send Zero Window Probe with 1 byte, next seg = N+1, * we eventually get a window>0 ACK still at N, * we start sending stuff again, but starting from N+1, * receiver keeps ACKing N because it never accepted it. It seems sending either 1 or 0 byte is valid for a ZWP, although I'm not entirely sure. At least it's easier to handle 0 than 1, and it seems to work. Wireshark shows them as duplicate ACKs, but they get the thing going. References: * RFC 793: https://tools.ietf.org/html/rfc793#section-3.7 * RFC 6429: https://tools.ietf.org/html/rfc6429 * Wireshark wiki: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvTCPAnalysis.html Should fix #13769. Change-Id: I95264ebbbb8c66c23411dfce6fc41871e0427166 Reviewed-on: https://review.haiku-os.org/c/haiku/+/1188 Reviewed-by: waddlesplash --- src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index 642564cca2..509f58418b 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -2084,12 +2084,6 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow) } else sendWindow -= consumedWindow; - if (force && sendWindow == 0 && fSendNext <= fSendQueue.LastSequence()) { - // send one byte of data to ask for a window update - // (triggered by the persist timer) - sendWindow = 1; - } - uint32 length = min_c(fSendQueue.Available(fSendNext), sendWindow); bool shouldStartRetransmitTimer = fSendNext == fSendUnacknowledged; bool retransmit = fSendNext < fSendMax; @@ -2104,7 +2098,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow) - tcp_options_length(segment); uint32 segmentLength = min_c(length, segmentMaxSize); - if (fSendNext + segmentLength == fSendQueue.LastSequence()) { + if (fSendNext + segmentLength == fSendQueue.LastSequence() && !force) { if (state_needs_finish(fState)) segment.flags |= TCP_FLAG_FINISH; if (length > 0)