From 321433cfc32c3715a9a9cdca9a0f19143dbe17dc Mon Sep 17 00:00:00 2001
From: A-star-ayush <myselfthebest@yahoo.com>
Date: Wed, 26 Jul 2017 00:41:19 +0530
Subject: [PATCH] tcp: slow start@rfc5681 : updated rules for congestion window
---
.../kernel/network/protocols/tcp/TCPEndpoint.cpp | 78 ++++++++++++++--------
.../kernel/network/protocols/tcp/TCPEndpoint.h | 1 +
src/add-ons/kernel/network/protocols/tcp/tcp.h | 2 +
3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
index 0a7c5fa..8589e29 100644
a
|
b
|
|
18 | 18 | #include <signal.h> |
19 | 19 | #include <stdlib.h> |
20 | 20 | #include <string.h> |
| 21 | #include <stdint.h> |
21 | 22 | |
22 | 23 | #include <KernelExport.h> |
23 | 24 | #include <Select.h> |
… |
… |
TCPEndpoint::TCPEndpoint(net_socket* socket)
|
427 | 428 | fSendWindow(0), |
428 | 429 | fSendMaxWindow(0), |
429 | 430 | fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE), |
| 431 | fSendMaxSegments(0), |
430 | 432 | fSendQueue(socket->send.buffer_size), |
431 | 433 | fInitialSendSequence(0), |
432 | 434 | fDuplicateAcknowledgeCount(0), |
… |
… |
TCPEndpoint::_PrepareReceivePath(tcp_segment_header& segment)
|
1392 | 1394 | fFlags &= ~FLAG_OPTION_TIMESTAMP; |
1393 | 1395 | } |
1394 | 1396 | |
1395 | | fCongestionWindow = 2 * fSendMaxSegmentSize; |
| 1397 | if (fSendMaxSegmentSize > 2190) |
| 1398 | fCongestionWindow = 2 * fSendMaxSegmentSize; |
| 1399 | else if (fSendMaxSegmentSize > 1095) |
| 1400 | fCongestionWindow = 3 * fSendMaxSegmentSize; |
| 1401 | else |
| 1402 | fCongestionWindow = 4 * fSendMaxSegmentSize; |
| 1403 | |
| 1404 | fSendMaxSegments = fCongestionWindow / fSendMaxSegmentSize; |
1396 | 1405 | fSlowStartThreshold = (uint32)segment.advertised_window << fSendWindowShift; |
1397 | 1406 | } |
1398 | 1407 | |
… |
… |
inline bool
|
1897 | 1906 | TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length, |
1898 | 1907 | uint32 segmentMaxSize, uint32 flightSize) |
1899 | 1908 | { |
| 1909 | if(fSendMaxSegments == 0) |
| 1910 | return false; |
| 1911 | |
1900 | 1912 | if (length > 0) { |
1901 | 1913 | // Avoid the silly window syndrome - we only send a segment in case: |
1902 | 1914 | // - we have a full segment to send, or |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2033 | 2045 | bool retransmit = fSendNext < fSendMax; |
2034 | 2046 | |
2035 | 2047 | do { |
2036 | | uint32 segmentMaxSize = fSendMaxSegmentSize |
2037 | | - tcp_options_length(segment); |
2038 | | uint32 segmentLength = min_c(length, segmentMaxSize); |
| 2048 | uint32 segmentLength = min_c(length, fSendMaxSegmentSize); |
2039 | 2049 | |
2040 | 2050 | if (fSendNext + segmentLength == fSendQueue.LastSequence()) { |
2041 | 2051 | if (state_needs_finish(fState)) |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2046 | 2056 | |
2047 | 2057 | // Determine if we should really send this segment |
2048 | 2058 | if (!force && !retransmit && !_ShouldSendSegment(segment, segmentLength, |
2049 | | segmentMaxSize, flightSize)) { |
| 2059 | fSendMaxSegmentSize, flightSize)) { |
2050 | 2060 | if (fSendQueue.Available() |
2051 | 2061 | && !gStackModule->is_timer_active(&fPersistTimer) |
2052 | 2062 | && !gStackModule->is_timer_active(&fRetransmitTimer)) |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2114 | 2124 | fReceiveMaxAdvertised = fReceiveNext |
2115 | 2125 | + ((uint32)segment.advertised_window << fReceiveWindowShift); |
2116 | 2126 | |
| 2127 | if (segmentLength !=0 && fState == ESTABLISHED) |
| 2128 | fSendMaxSegments -= 1; |
| 2129 | |
2117 | 2130 | status = next->module->send_routed_data(next, fRoute, buffer); |
2118 | 2131 | if (status < B_OK) { |
2119 | 2132 | gBufferModule->free(buffer); |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2207 | 2220 | |
2208 | 2221 | if (fSendUnacknowledged < segment.acknowledge) { |
2209 | 2222 | fSendQueue.RemoveUntil(segment.acknowledge); |
| 2223 | |
| 2224 | // the acknowledgment of the SYN/ACK MUST NOT increase the size of the congestion window |
| 2225 | if (fSendUnacknowledged != fInitialSendSequence) { |
| 2226 | if (fCongestionWindow < fSlowStartThreshold) |
| 2227 | fCongestionWindow += min_c(segment.acknowledge - fSendUnacknowledged.Number(), |
| 2228 | fSendMaxSegmentSize); |
| 2229 | else { |
| 2230 | uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; |
| 2231 | |
| 2232 | if (increment < fCongestionWindow) |
| 2233 | increment = 1; |
| 2234 | else |
| 2235 | increment /= fCongestionWindow; |
| 2236 | |
| 2237 | fCongestionWindow += increment; |
| 2238 | } |
| 2239 | |
| 2240 | fSendMaxSegments = UINT32_MAX; |
| 2241 | } |
| 2242 | |
2210 | 2243 | fSendUnacknowledged = segment.acknowledge; |
2211 | 2244 | if (fSendNext < fSendUnacknowledged) |
2212 | 2245 | fSendNext = fSendUnacknowledged; |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2236 | 2269 | fSendCondition.NotifyAll(); |
2237 | 2270 | gSocketModule->notify(socket, B_SELECT_WRITE, fSendQueue.Free()); |
2238 | 2271 | } |
2239 | | |
2240 | | if (fCongestionWindow < fSlowStartThreshold) |
2241 | | fCongestionWindow += fSendMaxSegmentSize; |
2242 | | } |
2243 | | |
2244 | | if (fCongestionWindow >= fSlowStartThreshold) { |
2245 | | uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; |
2246 | | |
2247 | | if (increment < fCongestionWindow) |
2248 | | increment = 1; |
2249 | | else |
2250 | | increment /= fCongestionWindow; |
2251 | | |
2252 | | fCongestionWindow += increment; |
2253 | 2272 | } |
2254 | 2273 | |
2255 | 2274 | // if there is data left to be sent, send it now |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2261 | 2280 | void |
2262 | 2281 | TCPEndpoint::_Retransmit() |
2263 | 2282 | { |
2264 | | TRACE("Retransmit()"); |
| 2283 | if (fState < ESTABLISHED) { |
| 2284 | fRetransmitTimeout = TCP_SYN_RETRANSMIT_TIMEOUT; |
| 2285 | fCongestionWindow = fSendMaxSegmentSize; |
| 2286 | } else { |
| 2287 | TRACE("Retransmit()"); |
2265 | 2288 | |
2266 | | _ResetSlowStart(); |
2267 | | fSendNext = fSendUnacknowledged; |
| 2289 | _ResetSlowStart(); |
| 2290 | fSendNext = fSendUnacknowledged; |
2268 | 2291 | |
2269 | | // Do exponential back off of the retransmit timeout |
2270 | | fRetransmitTimeout *= 2; |
2271 | | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
2272 | | fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; |
| 2292 | // Do exponential back off of the retransmit timeout |
| 2293 | fRetransmitTimeout *= 2; |
| 2294 | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
| 2295 | fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; |
2273 | 2296 | |
2274 | | _SendQueued(); |
| 2297 | _SendQueued(); |
| 2298 | } |
2275 | 2299 | } |
2276 | 2300 | |
2277 | 2301 | |
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h
index 1ff167b..f0bd4e4 100644
a
|
b
|
private:
|
145 | 145 | uint32 fSendWindow; |
146 | 146 | uint32 fSendMaxWindow; |
147 | 147 | uint32 fSendMaxSegmentSize; |
| 148 | uint32 fSendMaxSegments; |
148 | 149 | BufferQueue fSendQueue; |
149 | 150 | tcp_sequence fLastAcknowledgeSent; |
150 | 151 | 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 6f30ec2..24890a3 100644
a
|
b
|
operator==(tcp_sequence a, tcp_sequence b)
|
193 | 193 | #define TCP_MIN_RETRANSMIT_TIMEOUT 200000 // 200 msecs |
194 | 194 | // Maximum retransmit timeout (per RFC6298) |
195 | 195 | #define TCP_MAX_RETRANSMIT_TIMEOUT 60000000 // 60 secs |
| 196 | // New value for timeout in case of lost SYN (RFC 6298) |
| 197 | #define TCP_SYN_RETRANSMIT_TIMEOUT 3000000 // 3 secs |
196 | 198 | |
197 | 199 | struct tcp_sack { |
198 | 200 | uint32 left_edge; |