From 5fb6e02242be840a99cd978d4681951551bb1bef Mon Sep 17 00:00:00 2001
From: A-star-ayush <myselfthebest@yahoo.com>
Date: Fri, 10 Nov 2017 01:46:37 +0530
Subject: [PATCH] tcp: fixed no response from window update, removed ideal
timer
---
.../kernel/network/protocols/tcp/TCPEndpoint.cpp | 106 ++++++++++++++-------
.../kernel/network/protocols/tcp/TCPEndpoint.h | 1 +
src/add-ons/kernel/network/protocols/tcp/tcp.h | 2 +
3 files changed, 76 insertions(+), 33 deletions(-)
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
index 49e85d2..e3194da 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)
|
428 | 429 | fSendWindow(0), |
429 | 430 | fSendMaxWindow(0), |
430 | 431 | fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE), |
| 432 | fSendMaxSegments(0), |
431 | 433 | fSendQueue(socket->send.buffer_size), |
432 | 434 | fInitialSendSequence(0), |
433 | 435 | fPreviousHighestAcknowledge(0), |
… |
… |
TCPEndpoint::_AddData(tcp_segment_header& segment, net_buffer* buffer)
|
1384 | 1386 | if ((segment.flags & TCP_FLAG_PUSH) != 0) |
1385 | 1387 | fReceiveQueue.SetPushPointer(); |
1386 | 1388 | |
1387 | | if (fSendUnacknowledged == fSendMax) { |
1388 | | TRACE("data received, resetting ideal timer to: %" |
1389 | | B_PRIdBIGTIME, fRetransmitTimeout); |
1390 | | gStackModule->set_timer(&fRetransmitTimer, fRetransmitTimeout); |
1391 | | T(TimerSet(this, "ideal", fRetransmitTimeout)); |
1392 | | } |
1393 | | |
1394 | 1389 | return fReceiveQueue.Available() > 0; |
1395 | 1390 | } |
1396 | 1391 | |
… |
… |
TCPEndpoint::_PrepareReceivePath(tcp_segment_header& segment)
|
1426 | 1421 | fFlags &= ~FLAG_OPTION_TIMESTAMP; |
1427 | 1422 | } |
1428 | 1423 | |
1429 | | fCongestionWindow = 2 * fSendMaxSegmentSize; |
| 1424 | if (fSendMaxSegmentSize > 2190) |
| 1425 | fCongestionWindow = 2 * fSendMaxSegmentSize; |
| 1426 | else if (fSendMaxSegmentSize > 1095) |
| 1427 | fCongestionWindow = 3 * fSendMaxSegmentSize; |
| 1428 | else |
| 1429 | fCongestionWindow = 4 * fSendMaxSegmentSize; |
| 1430 | |
| 1431 | fSendMaxSegments = fCongestionWindow / fSendMaxSegmentSize; |
1430 | 1432 | fSlowStartThreshold = (uint32)segment.advertised_window << fSendWindowShift; |
1431 | 1433 | } |
1432 | 1434 | |
… |
… |
TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
1709 | 1711 | } |
1710 | 1712 | #endif |
1711 | 1713 | |
| 1714 | if (advertisedWindow > fSendWindow) |
| 1715 | action |= IMMEDIATE_ACKNOWLEDGE; |
| 1716 | |
1712 | 1717 | fSendWindow = advertisedWindow; |
1713 | 1718 | if (advertisedWindow > fSendMaxWindow) |
1714 | 1719 | fSendMaxWindow = advertisedWindow; |
… |
… |
inline bool
|
1946 | 1951 | TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length, |
1947 | 1952 | uint32 segmentMaxSize, uint32 flightSize) |
1948 | 1953 | { |
| 1954 | if (fState == ESTABLISHED && fSendMaxSegments == 0) |
| 1955 | return false; |
| 1956 | |
1949 | 1957 | if (length > 0) { |
1950 | 1958 | // Avoid the silly window syndrome - we only send a segment in case: |
1951 | 1959 | // - we have a full segment to send, or |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2168 | 2176 | fReceiveMaxAdvertised = fReceiveNext |
2169 | 2177 | + ((uint32)segment.advertised_window << fReceiveWindowShift); |
2170 | 2178 | |
| 2179 | if (segmentLength != 0 && fState == ESTABLISHED) |
| 2180 | --fSendMaxSegments; |
| 2181 | |
2171 | 2182 | status = next->module->send_routed_data(next, fRoute, buffer); |
2172 | 2183 | if (status < B_OK) { |
2173 | 2184 | gBufferModule->free(buffer); |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2265 | 2276 | |
2266 | 2277 | if (fSendUnacknowledged < segment.acknowledge) { |
2267 | 2278 | fSendQueue.RemoveUntil(segment.acknowledge); |
| 2279 | |
| 2280 | uint32 bytesAcknowledged = segment.acknowledge - fSendUnacknowledged.Number(); |
| 2281 | fPreviousHighestAcknowledge = fSendUnacknowledged; |
2268 | 2282 | fSendUnacknowledged = segment.acknowledge; |
| 2283 | |
| 2284 | if (fPreviousHighestAcknowledge > fSendUnacknowledged) { |
| 2285 | // need to update the recover variable upon a sequence wraparound |
| 2286 | fRecover = segment.acknowledge - 1; |
| 2287 | } |
| 2288 | |
| 2289 | // the acknowledgment of the SYN/ACK MUST NOT increase the size of the congestion window |
| 2290 | if (fSendUnacknowledged != fInitialSendSequence) { |
| 2291 | if (fCongestionWindow < fSlowStartThreshold) |
| 2292 | fCongestionWindow += min_c(bytesAcknowledged, fSendMaxSegmentSize); |
| 2293 | else { |
| 2294 | uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; |
| 2295 | |
| 2296 | if (increment < fCongestionWindow) |
| 2297 | increment = 1; |
| 2298 | else |
| 2299 | increment /= fCongestionWindow; |
| 2300 | |
| 2301 | fCongestionWindow += increment; |
| 2302 | } |
| 2303 | |
| 2304 | fSendMaxSegments = UINT32_MAX; |
| 2305 | } |
| 2306 | |
| 2307 | if ((fFlags & FLAG_RECOVERY) != 0) { |
| 2308 | fSendNext = fSendUnacknowledged; |
| 2309 | _SendQueued(); |
| 2310 | fCongestionWindow -= bytesAcknowledged; |
| 2311 | |
| 2312 | if (bytesAcknowledged > fSendMaxSegmentSize) |
| 2313 | fCongestionWindow += fSendMaxSegmentSize; |
| 2314 | |
| 2315 | fSendNext = fSendMax; |
| 2316 | } else |
| 2317 | fDuplicateAcknowledgeCount = 0; |
| 2318 | |
2269 | 2319 | if (fSendNext < fSendUnacknowledged) |
2270 | 2320 | fSendNext = fSendUnacknowledged; |
2271 | 2321 | |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2282 | 2332 | } |
2283 | 2333 | |
2284 | 2334 | if (fSendUnacknowledged == fSendMax) { |
2285 | | TRACE("all acknowledged, cancelling retransmission timer. Using it as ideal timer for: %" |
2286 | | B_PRIdBIGTIME, fRetransmitTimeout); |
2287 | | gStackModule->set_timer(&fRetransmitTimer, fRetransmitTimeout); |
2288 | | T(TimerSet(this, "ideal", fRetransmitTimeout)); |
| 2335 | TRACE("all acknowledged, cancelling retransmission timer."); |
| 2336 | gStackModule->cancel_timer(&fRetransmitTimer); |
| 2337 | T(TimerSet(this, "retransmit", -1)); |
2289 | 2338 | fSendTime = 0; |
2290 | 2339 | } else { |
2291 | 2340 | TRACE("data acknowledged, resetting retransmission timer to: %" |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2299 | 2348 | fSendCondition.NotifyAll(); |
2300 | 2349 | gSocketModule->notify(socket, B_SELECT_WRITE, fSendQueue.Free()); |
2301 | 2350 | } |
2302 | | |
2303 | | if (fCongestionWindow < fSlowStartThreshold) |
2304 | | fCongestionWindow += fSendMaxSegmentSize; |
2305 | | } |
2306 | | |
2307 | | if (fCongestionWindow >= fSlowStartThreshold) { |
2308 | | uint32 increment = fSendMaxSegmentSize * fSendMaxSegmentSize; |
2309 | | |
2310 | | if (increment < fCongestionWindow) |
2311 | | increment = 1; |
2312 | | else |
2313 | | increment /= fCongestionWindow; |
2314 | | |
2315 | | fCongestionWindow += increment; |
2316 | 2351 | } |
2317 | 2352 | |
2318 | 2353 | // if there is data left to be sent, send it now |
… |
… |
TCPEndpoint::_Retransmit()
|
2326 | 2361 | { |
2327 | 2362 | TRACE("Retransmit()"); |
2328 | 2363 | |
2329 | | _ResetSlowStart(); |
2330 | | fSendNext = fSendUnacknowledged; |
2331 | | |
2332 | | // Do exponential back off of the retransmit timeout |
2333 | | fRetransmitTimeout *= 2; |
2334 | | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
2335 | | fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; |
| 2364 | if (fState < ESTABLISHED) { |
| 2365 | fRetransmitTimeout = TCP_SYN_RETRANSMIT_TIMEOUT; |
| 2366 | fCongestionWindow = fSendMaxSegmentSize; |
| 2367 | } else { |
| 2368 | _ResetSlowStart(); |
| 2369 | fDuplicateAcknowledgeCount = 0; |
| 2370 | // Do exponential back off of the retransmit timeout |
| 2371 | fRetransmitTimeout *= 2; |
| 2372 | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
| 2373 | fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; |
| 2374 | } |
2336 | 2375 | |
| 2376 | fSendNext = fSendUnacknowledged; |
2337 | 2377 | _SendQueued(); |
2338 | 2378 | |
2339 | 2379 | fRecover = fSendNext.Number() - 1; |
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h
index 22bf859..6a62e07 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; |