From 05743f6a13319a9dc332603eb5d98ba4c5374b25 Mon Sep 17 00:00:00 2001 From: A-star-ayush Date: Tue, 15 Aug 2017 01:11:58 +0530 Subject: [PATCH] tcp: slow start@rfc5681 : updated rules for congestion window Signed-off-by: Jessica Hamilton --- .../network/protocols/tcp/TCPEndpoint.cpp | 70 +++++++++++++------ .../network/protocols/tcp/TCPEndpoint.h | 1 + .../kernel/network/protocols/tcp/tcp.h | 2 + 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index eb8ed479eb..1cbe2627bd 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -427,6 +428,7 @@ TCPEndpoint::TCPEndpoint(net_socket* socket) fSendWindow(0), fSendMaxWindow(0), fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE), + fSendMaxSegments(0), fSendQueue(socket->send.buffer_size), fInitialSendSequence(0), fDuplicateAcknowledgeCount(0), @@ -1392,7 +1394,14 @@ TCPEndpoint::_PrepareReceivePath(tcp_segment_header& segment) fFlags &= ~FLAG_OPTION_TIMESTAMP; } - fCongestionWindow = 2 * fSendMaxSegmentSize; + if (fSendMaxSegmentSize > 2190) + fCongestionWindow = 2 * fSendMaxSegmentSize; + else if (fSendMaxSegmentSize > 1095) + fCongestionWindow = 3 * fSendMaxSegmentSize; + else + fCongestionWindow = 4 * fSendMaxSegmentSize; + + fSendMaxSegments = fCongestionWindow / fSendMaxSegmentSize; fSlowStartThreshold = (uint32)segment.advertised_window << fSendWindowShift; } @@ -1897,6 +1906,9 @@ inline bool TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length, uint32 segmentMaxSize, uint32 flightSize) { + if (fState == ESTABLISHED && fSendMaxSegments == 0) + return false; + if (length > 0) { // Avoid the silly window syndrome - we only send a segment in case: // - we have a full segment to send, or @@ -2114,6 +2126,9 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow) fReceiveMaxAdvertised = fReceiveNext + ((uint32)segment.advertised_window << fReceiveWindowShift); + if (segmentLength != 0 && fState == ESTABLISHED) + --fSendMaxSegments; + status = next->module->send_routed_data(next, fRoute, buffer); if (status < B_OK) { gBufferModule->free(buffer); @@ -2207,6 +2222,26 @@ TCPEndpoint::_Acknowledged(tcp_segment_header& segment) if (fSendUnacknowledged < segment.acknowledge) { fSendQueue.RemoveUntil(segment.acknowledge); + + // the acknowledgment of the SYN/ACK MUST NOT increase the size of the congestion window + if (fSendUnacknowledged != fInitialSendSequence) { + if (fCongestionWindow < fSlowStartThreshold) + fCongestionWindow += min_c(segment.acknowledge - fSendUnacknowledged.Number(), + fSendMaxSegmentSize); + else { + uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; + + if (increment < fCongestionWindow) + increment = 1; + else + increment /= fCongestionWindow; + + fCongestionWindow += increment; + } + + fSendMaxSegments = UINT32_MAX; + } + fSendUnacknowledged = segment.acknowledge; if (fSendNext < fSendUnacknowledged) fSendNext = fSendUnacknowledged; @@ -2236,20 +2271,6 @@ TCPEndpoint::_Acknowledged(tcp_segment_header& segment) fSendCondition.NotifyAll(); gSocketModule->notify(socket, B_SELECT_WRITE, fSendQueue.Free()); } - - if (fCongestionWindow < fSlowStartThreshold) - fCongestionWindow += fSendMaxSegmentSize; - } - - if (fCongestionWindow >= fSlowStartThreshold) { - uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; - - if (increment < fCongestionWindow) - increment = 1; - else - increment /= fCongestionWindow; - - fCongestionWindow += increment; } // if there is data left to be sent, send it now @@ -2261,16 +2282,21 @@ TCPEndpoint::_Acknowledged(tcp_segment_header& segment) void TCPEndpoint::_Retransmit() { + if (fState < ESTABLISHED) { + fRetransmitTimeout = TCP_SYN_RETRANSMIT_TIMEOUT; + fCongestionWindow = fSendMaxSegmentSize; + } else { + _ResetSlowStart(); + + // Do exponential back off of the retransmit timeout + fRetransmitTimeout *= 2; + if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) + fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; + } + TRACE("Retransmit()"); - _ResetSlowStart(); fSendNext = fSendUnacknowledged; - - // Do exponential back off of the retransmit timeout - fRetransmitTimeout *= 2; - if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) - fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; - _SendQueued(); } diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h index 1ff167b5bb..f0bd4e4e1f 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h @@ -145,6 +145,7 @@ private: uint32 fSendWindow; uint32 fSendMaxWindow; uint32 fSendMaxSegmentSize; + uint32 fSendMaxSegments; BufferQueue fSendQueue; tcp_sequence fLastAcknowledgeSent; tcp_sequence fInitialSendSequence; diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.h b/src/add-ons/kernel/network/protocols/tcp/tcp.h index 6f30ec2943..24890a32aa 100644 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.h +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.h @@ -193,6 +193,8 @@ operator==(tcp_sequence a, tcp_sequence b) #define TCP_MIN_RETRANSMIT_TIMEOUT 200000 // 200 msecs // Maximum retransmit timeout (per RFC6298) #define TCP_MAX_RETRANSMIT_TIMEOUT 60000000 // 60 secs +// New value for timeout in case of lost SYN (RFC 6298) +#define TCP_SYN_RETRANSMIT_TIMEOUT 3000000 // 3 secs struct tcp_sack { uint32 left_edge;