From 077e0ba92809d0a7306bbabe13729774c717d1b1 Mon Sep 17 00:00:00 2001
From: A-star-ayush <myselfthebest@yahoo.com>
Date: Tue, 15 Aug 2017 01:16:31 +0530
Subject: [PATCH] tcp: rfc 5681: implemented fast retransmit and recovery
---
.../kernel/network/protocols/tcp/TCPEndpoint.cpp | 43 ++++++++++++++++------
.../kernel/network/protocols/tcp/TCPEndpoint.h | 1 +
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
index 061df2a..44dfc9b 100644
a
|
b
|
TCPEndpoint::TCPEndpoint(net_socket* socket)
|
432 | 432 | fSendQueue(socket->send.buffer_size), |
433 | 433 | fInitialSendSequence(0), |
434 | 434 | fDuplicateAcknowledgeCount(0), |
| 435 | fPreviousFlightSize(0), |
435 | 436 | fRoute(NULL), |
436 | 437 | fReceiveNext(0), |
437 | 438 | fReceiveMaxAdvertised(0), |
… |
… |
TCPEndpoint::_HandleReset(status_t error)
|
1277 | 1278 | void |
1278 | 1279 | TCPEndpoint::_DuplicateAcknowledge(tcp_segment_header &segment) |
1279 | 1280 | { |
| 1281 | if (fDuplicateAcknowledgeCount == 0) |
| 1282 | fPreviousFlightSize = (fSendMax - fSendUnacknowledged).Number(); |
| 1283 | |
1280 | 1284 | if (++fDuplicateAcknowledgeCount < 3) |
1281 | 1285 | return; |
1282 | 1286 | |
1283 | 1287 | if (fDuplicateAcknowledgeCount == 3) { |
1284 | | _ResetSlowStart(); |
| 1288 | fSlowStartThreshold = max_c(fPreviousFlightSize / 2, 2 * fSendMaxSegmentSize); |
1285 | 1289 | fCongestionWindow = fSlowStartThreshold + 3 * fSendMaxSegmentSize; |
1286 | 1290 | fSendNext = segment.acknowledge; |
1287 | | } else if (fDuplicateAcknowledgeCount > 3) |
1288 | | fCongestionWindow += fSendMaxSegmentSize; |
1289 | | |
1290 | | _SendQueued(); |
| 1291 | _SendQueued(); |
| 1292 | TRACE("_DuplicateAcknowledge(): packet sent under fast restransmit on the receipt of 3rd dup ack"); |
| 1293 | |
| 1294 | } else if (fDuplicateAcknowledgeCount > 3) { |
| 1295 | uint32 flightSize = (fSendMax - fSendUnacknowledged).Number(); |
| 1296 | if ((fDuplicateAcknowledgeCount - 3) * fSendMaxSegmentSize <= flightSize) |
| 1297 | fCongestionWindow += fSendMaxSegmentSize; |
| 1298 | if (fSendQueue.Available(fSendMax) != 0) { |
| 1299 | fSendNext = fSendMax; |
| 1300 | _SendQueued(); |
| 1301 | } |
| 1302 | } |
1291 | 1303 | } |
1292 | 1304 | |
1293 | 1305 | |
… |
… |
TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
1641 | 1653 | |
1642 | 1654 | int32 action = KEEP; |
1643 | 1655 | |
| 1656 | // immediately acknowledge out-of-order segment to trigger fast-retransmit at the sender |
| 1657 | if (drop != 0) |
| 1658 | action |= IMMEDIATE_ACKNOWLEDGE; |
| 1659 | |
1644 | 1660 | drop = (int32)(segment.sequence + buffer->size |
1645 | 1661 | - (fReceiveNext + fReceiveWindow)).Number(); |
1646 | 1662 | if (drop > 0) { |
… |
… |
TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
1685 | 1701 | if (fSendMax < segment.acknowledge) |
1686 | 1702 | return DROP | IMMEDIATE_ACKNOWLEDGE; |
1687 | 1703 | |
1688 | | if (segment.acknowledge < fSendUnacknowledged) { |
| 1704 | if (segment.acknowledge == fSendUnacknowledged) { |
1689 | 1705 | if (buffer->size == 0 && advertisedWindow == fSendWindow |
1690 | | && (segment.flags & TCP_FLAG_FINISH) == 0) { |
| 1706 | && (segment.flags & TCP_FLAG_FINISH) == 0 && fSendUnacknowledged != fSendMax) { |
1691 | 1707 | TRACE("Receive(): duplicate ack!"); |
1692 | | |
1693 | 1708 | _DuplicateAcknowledge(segment); |
1694 | 1709 | } |
1695 | | |
| 1710 | } else if (segment.acknowledge < fSendUnacknowledged) { |
1696 | 1711 | return DROP; |
1697 | 1712 | } else { |
1698 | 1713 | // this segment acknowledges in flight data |
… |
… |
TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
1702 | 1717 | fCongestionWindow = fSlowStartThreshold; |
1703 | 1718 | } |
1704 | 1719 | |
1705 | | fDuplicateAcknowledgeCount = 0; |
1706 | | |
1707 | 1720 | if (fSendMax == segment.acknowledge) |
1708 | 1721 | TRACE("Receive(): all inflight data ack'd!"); |
1709 | 1722 | |
… |
… |
TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
2044 | 2057 | bool shouldStartRetransmitTimer = fSendNext == fSendUnacknowledged; |
2045 | 2058 | bool retransmit = fSendNext < fSendMax; |
2046 | 2059 | |
| 2060 | if (fDuplicateAcknowledgeCount != 0) { |
| 2061 | // send at most 1 SMSS of data when under limited transmit, fast transmit/recovery |
| 2062 | length = min_c(length, fSendMaxSegmentSize); |
| 2063 | } |
| 2064 | |
2047 | 2065 | do { |
2048 | 2066 | uint32 segmentMaxSize = fSendMaxSegmentSize |
2049 | 2067 | - tcp_options_length(segment); |
… |
… |
TCPEndpoint::_Acknowledged(tcp_segment_header& segment)
|
2221 | 2239 | ASSERT(fSendUnacknowledged <= segment.acknowledge); |
2222 | 2240 | |
2223 | 2241 | if (fSendUnacknowledged < segment.acknowledge) { |
| 2242 | fDuplicateAcknowledgeCount = 0; |
2224 | 2243 | fSendQueue.RemoveUntil(segment.acknowledge); |
2225 | 2244 | |
2226 | 2245 | // the acknowledgment of the SYN/ACK MUST NOT increase the size of the congestion window |
… |
… |
TCPEndpoint::_Retransmit()
|
2287 | 2306 | fCongestionWindow = fSendMaxSegmentSize; |
2288 | 2307 | } else { |
2289 | 2308 | _ResetSlowStart(); |
2290 | | |
| 2309 | fDuplicateAcknowledgeCount = 0; |
2291 | 2310 | // Do exponential back off of the retransmit timeout |
2292 | 2311 | fRetransmitTimeout *= 2; |
2293 | 2312 | if (fRetransmitTimeout > TCP_MAX_RETRANSMIT_TIMEOUT) |
diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h
index f0bd4e4..fd59c46 100644
a
|
b
|
private:
|
150 | 150 | tcp_sequence fLastAcknowledgeSent; |
151 | 151 | tcp_sequence fInitialSendSequence; |
152 | 152 | uint32 fDuplicateAcknowledgeCount; |
| 153 | uint32 fPreviousFlightSize; |
153 | 154 | |
154 | 155 | net_route *fRoute; |
155 | 156 | // TODO: don't use a net_route, but a net_route_info!!! |