From 64dc0ded362b815bbb67cb04306921bf9fc6655c Mon Sep 17 00:00:00 2001
From: A-star-ayush <myselfthebest@yahoo.com>
Date: Mon, 4 Dec 2017 23:01:02 +0530
Subject: [PATCH] tcp : fixed RTO update and dup ACKs generation
---
.../kernel/network/protocols/tcp/TCPEndpoint.cpp | 38 +++++++++++++---------
.../kernel/network/protocols/tcp/TCPEndpoint.h | 3 +-
2 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
index e3194da..007f772 100644
a
|
b
|
TCPEndpoint::TCPEndpoint(net_socket* socket)
|
445 | 445 | fSmoothedRoundTripTime(0), |
446 | 446 | fRoundTripVariation(0), |
447 | 447 | fSendTime(0), |
| 448 | fRoundTripStartSequence(0), |
448 | 449 | fRetransmitTimeout(TCP_INITIAL_RTT), |
449 | 450 | fReceivedTimestamp(0), |
450 | 451 | fCongestionWindow(0), |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2035 | 2036 | } |
2036 | 2037 | |
2037 | 2038 | size_t availableBytes = fReceiveQueue.Free(); |
| 2039 | // window size must remain same for duplicate acknowledgements |
| 2040 | if (!fReceiveQueue.IsContiguous()) |
| 2041 | availableBytes = (fReceiveMaxAdvertised - fReceiveNext).Number(); |
| 2042 | |
2038 | 2043 | if (fFlags & FLAG_OPTION_WINDOW_SCALE) |
2039 | 2044 | segment.advertised_window = availableBytes >> fReceiveWindowShift; |
2040 | 2045 | else |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2189 | 2194 | return status; |
2190 | 2195 | } |
2191 | 2196 | |
2192 | | if (fSendTime == 0 && (segmentLength != 0 || (segment.flags & TCP_FLAG_SYNCHRONIZE ) == 1)) |
| 2197 | if (fSendTime == 0 && !retransmit |
| 2198 | && (segmentLength != 0 || (segment.flags & TCP_FLAG_SYNCHRONIZE) !=0)) { |
2193 | 2199 | fSendTime = tcp_now(); |
| 2200 | fRoundTripStartSequence = segment.sequence; |
| 2201 | } |
2194 | 2202 | |
2195 | 2203 | if (shouldStartRetransmitTimer && size > 0) { |
2196 | 2204 | TRACE("starting initial retransmit timer of: %" B_PRIdBIGTIME, |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2280 | 2288 | uint32 bytesAcknowledged = segment.acknowledge - fSendUnacknowledged.Number(); |
2281 | 2289 | fPreviousHighestAcknowledge = fSendUnacknowledged; |
2282 | 2290 | fSendUnacknowledged = segment.acknowledge; |
| 2291 | uint32 flightSize = (fSendMax - fSendUnacknowledged).Number(); |
| 2292 | int32 expectedSamples = flightSize / (fSendMaxSegmentSize << 1); |
2283 | 2293 | |
2284 | 2294 | if (fPreviousHighestAcknowledge > fSendUnacknowledged) { |
2285 | 2295 | // need to update the recover variable upon a sequence wraparound |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2320 | 2330 | fSendNext = fSendUnacknowledged; |
2321 | 2331 | |
2322 | 2332 | if (fFlags & FLAG_OPTION_TIMESTAMP) { |
2323 | | uint32 flightSize = (fSendMax - fSendUnacknowledged).Number(); |
2324 | 2333 | _UpdateRoundTripTime(tcp_diff_timestamp(segment.timestamp_reply), |
2325 | | 1 + ((flightSize - 1) / (fSendMaxSegmentSize << 1))); |
2326 | | } |
2327 | | |
2328 | | // Karn's algorithm: RTT measurement must not be made using segments that were retransmitted |
2329 | | else if (fSendTime > 1 && fSendNext == fSendMax) { |
| 2334 | expectedSamples > 0 ? expectedSamples : 1); |
| 2335 | } else if (fSendTime != 0 && fRoundTripStartSequence < segment.acknowledge) { |
2330 | 2336 | _UpdateRoundTripTime(tcp_diff_timestamp(fSendTime), 1); |
2331 | | fSendTime = 1; |
| 2337 | fSendTime = 0; |
2332 | 2338 | } |
2333 | 2339 | |
2334 | 2340 | if (fSendUnacknowledged == fSendMax) { |
2335 | 2341 | TRACE("all acknowledged, cancelling retransmission timer."); |
2336 | 2342 | gStackModule->cancel_timer(&fRetransmitTimer); |
2337 | 2343 | T(TimerSet(this, "retransmit", -1)); |
2338 | | fSendTime = 0; |
2339 | 2344 | } else { |
2340 | 2345 | TRACE("data acknowledged, resetting retransmission timer to: %" |
2341 | 2346 | B_PRIdBIGTIME, fRetransmitTimeout); |
… |
… |
TCPEndpoint::_Retransmit()
|
2383 | 2388 | |
2384 | 2389 | |
2385 | 2390 | void |
2386 | | TCPEndpoint::_UpdateRoundTripTime(int32 roundTripTime, uint32 expectedSamples) |
| 2391 | TCPEndpoint::_UpdateRoundTripTime(int32 roundTripTime, int32 expectedSamples) |
2387 | 2392 | { |
2388 | 2393 | if(fSmoothedRoundTripTime == 0) { |
2389 | 2394 | fSmoothedRoundTripTime = roundTripTime; |
2390 | | fRoundTripVariation = roundTripTime >> 1; |
2391 | | fRetransmitTimeout = (fSmoothedRoundTripTime + max_c(100, fRoundTripVariation << 2)) |
| 2395 | fRoundTripVariation = roundTripTime / 2; |
| 2396 | fRetransmitTimeout = (fSmoothedRoundTripTime + max_c(100, fRoundTripVariation * 4)) |
2392 | 2397 | * kTimestampFactor; |
2393 | 2398 | } else { |
2394 | 2399 | int32 delta = fSmoothedRoundTripTime - roundTripTime; |
2395 | 2400 | if (delta < 0) |
2396 | 2401 | delta = -delta; |
2397 | | fRoundTripVariation += ((delta - fRoundTripVariation) >> 2) / expectedSamples; |
2398 | | fSmoothedRoundTripTime += ((roundTripTime - fSmoothedRoundTripTime) >> 3) / expectedSamples; |
2399 | | fRetransmitTimeout = (fSmoothedRoundTripTime + max_c(100, fRoundTripVariation << 2)) |
| 2402 | fRoundTripVariation += (delta - fRoundTripVariation) / (expectedSamples * 4); |
| 2403 | fSmoothedRoundTripTime += (roundTripTime - fSmoothedRoundTripTime) / (expectedSamples * 8); |
| 2404 | fRetransmitTimeout = (fSmoothedRoundTripTime + max_c(100, fRoundTripVariation * 4)) |
2400 | 2405 | * kTimestampFactor; |
2401 | 2406 | } |
2402 | 2407 | |
| 2408 | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
| 2409 | fRetransmitTimeout = TCP_MAX_RETRANSMIT_TIMEOUT; |
| 2410 | |
2403 | 2411 | if (fRetransmitTimeout < TCP_MIN_RETRANSMIT_TIMEOUT) |
2404 | 2412 | fRetransmitTimeout = TCP_MIN_RETRANSMIT_TIMEOUT; |
2405 | 2413 | |
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h
index 6a62e07..e73cef0 100644
a
|
b
|
private:
|
106 | 106 | status_t _PrepareSendPath(const sockaddr* peer); |
107 | 107 | void _Acknowledged(tcp_segment_header& segment); |
108 | 108 | void _Retransmit(); |
109 | | void _UpdateRoundTripTime(int32 roundTripTime, uint32 expectedSamples); |
| 109 | void _UpdateRoundTripTime(int32 roundTripTime, int32 expectedSamples); |
110 | 110 | void _ResetSlowStart(); |
111 | 111 | void _DuplicateAcknowledge(tcp_segment_header& segment); |
112 | 112 | |
… |
… |
private:
|
171 | 171 | int32 fSmoothedRoundTripTime; |
172 | 172 | int32 fRoundTripVariation; |
173 | 173 | uint32 fSendTime; |
| 174 | tcp_sequence fRoundTripStartSequence; |
174 | 175 | bigtime_t fRetransmitTimeout; |
175 | 176 | |
176 | 177 | uint32 fReceivedTimestamp; |