From 58bef2f444947af261189df60c5231ab69a9601d Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Tue, 17 Apr 2007 01:07:58 +0000 Subject: [PATCH] support TCP Window Scale on sent segments. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20729 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/protocols/tcp/TCPEndpoint.cpp | 84 +++++++++---------- .../network/protocols/tcp/TCPEndpoint.h | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index a0dc0c76bb..24a9135e26 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -61,7 +61,7 @@ // constants for the fFlags field enum { - FLAG_OPTION_WINDOW_SHIFT = 0x01, + FLAG_OPTION_WINDOW_SCALE = 0x01, FLAG_OPTION_TIMESTAMP = 0x02, // TODO: Should FLAG_NO_RECEIVE apply as well to received connections? // That is, what is expected from accept() after a shutdown() @@ -180,9 +180,8 @@ TCPEndpoint::TCPEndpoint(net_socket *socket) fReceiveQueue(socket->receive.buffer_size), fRoundTripTime(TCP_INITIAL_RTT), fReceivedTSval(0), - fUsingTimestamps(false), fState(CLOSED), - fFlags(0), //FLAG_OPTION_WINDOW_SHIFT), + fFlags(FLAG_OPTION_WINDOW_SCALE | FLAG_OPTION_TIMESTAMP), fError(B_OK), fSpawned(false) { @@ -366,10 +365,6 @@ TCPEndpoint::Connect(const struct sockaddr *address) fSendMax = fInitialSendSequence; fSendQueue.SetInitialSequence(fSendNext + 1); - // try to use timestamps, if the peer doesn't reply with the TS - // option as well we'll stop using them. - fUsingTimestamps = true; - // send SYN status = _SendQueued(); if (status != B_OK) { @@ -693,7 +688,7 @@ TCPEndpoint::DelayedAcknowledge() if (gStackModule->cancel_timer(&fDelayedAcknowledgeTimer)) { // timer was active, send an ACK now (with the exception above, // we send every other ACK) - return _SendQueued(); + return SendAcknowledge(); } gStackModule->set_timer(&fDelayedAcknowledgeTimer, TCP_DELAYED_ACKNOWLEDGE_TIMEOUT); @@ -808,10 +803,10 @@ TCPEndpoint::Spawn(TCPEndpoint *parent, tcp_segment_header &segment, else fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE; if (segment.has_window_shift) { - fFlags |= FLAG_OPTION_WINDOW_SHIFT; + fFlags |= FLAG_OPTION_WINDOW_SCALE; fSendWindowShift = segment.window_shift; } else { - fFlags &= ~FLAG_OPTION_WINDOW_SHIFT; + fFlags &= ~FLAG_OPTION_WINDOW_SCALE; fReceiveWindowShift = 0; } } @@ -865,10 +860,10 @@ TCPEndpoint::_SynchronizeSentReceive(tcp_segment_header &segment, net_buffer *bu else fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE; if (segment.has_window_shift) { - fFlags |= FLAG_OPTION_WINDOW_SHIFT; + fFlags |= FLAG_OPTION_WINDOW_SCALE; fSendWindowShift = segment.window_shift; } else { - fFlags &= ~FLAG_OPTION_WINDOW_SHIFT; + fFlags &= ~FLAG_OPTION_WINDOW_SCALE; fReceiveWindowShift = 0; } @@ -975,19 +970,10 @@ TCPEndpoint::_SegmentReceived(tcp_segment_header &segment, net_buffer *buffer) && fReceiveQueue.IsContiguous() && fReceiveQueue.Free() >= buffer->size && !(fFlags & FLAG_NO_RECEIVE)) { - TRACE("Receive(): header prediction receive!"); - // we're on the receiving end of the connection, and this segment - // is the one we were expecting, in-sequence - fReceiveNext += buffer->size; - TRACE("Receive(): receive next = %lu", (uint32)fReceiveNext); - fReceiveQueue.Add(buffer, segment.sequence); - if (segment.flags & TCP_FLAG_PUSH) - fReceiveQueue.SetPushPointer(); - + _AddData(segment, buffer); _NotifyReader(); - - return KEEP | (segment.flags & TCP_FLAG_PUSH ? - IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE); + return KEEP | ((segment.flags & TCP_FLAG_PUSH) ? + IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE); } } @@ -1104,10 +1090,10 @@ TCPEndpoint::_SendQueued(bool force) segment.flags = _CurrentFlags(); segment.urgent_offset = 0; - if (fUsingTimestamps) { + if (fOptions & FLAG_OPTION_TIMESTAMP) { segment.has_timestamps = true; segment.TSecr = fReceivedTSval; - segment.TSval = system_time(); + segment.TSval = 0; } uint32 sendWindow = fSendWindow; @@ -1138,8 +1124,13 @@ TCPEndpoint::_SendQueued(bool force) segment.flags &= ~TCP_FLAG_FINISH; } - segment.advertised_window = min_c(65535, fReceiveQueue.Free()); - // TODO: support shift option! + size_t availableBytes = fReceiveQueue.Free(); + + if (fOptions & FLAG_OPTION_WINDOW_SCALE) + segment.advertised_window = availableBytes >> fReceiveWindowShift; + else + segment.advertised_window = min_c(TCP_MAX_WINDOW, availableBytes); + segment.acknowledge = fReceiveNext; segment.urgent_offset = 0; @@ -1150,7 +1141,6 @@ TCPEndpoint::_SendQueued(bool force) && !gStackModule->is_timer_active(&fPersistTimer) && !gStackModule->is_timer_active(&fRetransmitTimer)) _StartPersistTimer(); - return B_OK; } @@ -1181,7 +1171,7 @@ TCPEndpoint::_SendQueued(bool force) && (fOptions & TCP_NOOPT) == 0) { // add connection establishment options segment.max_segment_size = fReceiveMaxSegmentSize; - if ((fFlags & FLAG_OPTION_WINDOW_SHIFT) != 0) { + if (fFlags & FLAG_OPTION_WINDOW_SCALE) { segment.has_window_shift = true; segment.window_shift = fReceiveWindowShift; } @@ -1487,17 +1477,10 @@ TCPEndpoint::_Receive(tcp_segment_header &segment, net_buffer *buffer) bool notify = false; if (buffer->size > 0 && _ShouldReceive()) { - fReceiveQueue.Add(buffer, segment.sequence); - fReceiveNext += buffer->size; + _AddData(segment, buffer); notify = true; - TRACE("Receive(): adding data, receive next = %lu. Now have %lu bytes.", - (uint32)fReceiveNext, fReceiveQueue.Available()); - - if (segment.flags & TCP_FLAG_PUSH) - fReceiveQueue.SetPushPointer(); - } else { + } else action = (action & ~KEEP) | DROP; - } if (segment.flags & TCP_FLAG_FINISH) { segmentLength++; @@ -1550,9 +1533,12 @@ void TCPEndpoint::_UpdateTimestamps(tcp_segment_header &segment, size_t segmentLength, bool checkSequence) { - fUsingTimestamps = segment.has_timestamps; + if (segment.has_timestamps) + fOptions |= FLAG_OPTION_TIMESTAMP; + else + fOptions &= ~FLAG_OPTION_TIMESTAMP; - if (fUsingTimestamps) { + if (fOptions & FLAG_OPTION_TIMESTAMP) { tcp_sequence sequence(segment.sequence); if (!checkSequence || (fLastAcknowledgeSent >= sequence @@ -1589,6 +1575,20 @@ TCPEndpoint::_WaitForEstablished(RecursiveLocker &locker, bigtime_t timeout) } +void +TCPEndpoint::_AddData(tcp_segment_header &segment, net_buffer *buffer) +{ + fReceiveNext += buffer->size; + fReceiveQueue.Add(buffer, segment.sequence); + + TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.", + (uint32)fReceiveNext, fReceiveQueue.Available()); + + if (segment.flags & TCP_FLAG_PUSH) + fReceiveQueue.SetPushPointer(); +} + + // #pragma mark - timer @@ -1629,7 +1629,7 @@ TCPEndpoint::_DelayedAcknowledgeTimer(struct net_timer *timer, void *data) if (!locker.IsLocked()) return; - endpoint->_SendQueued(true); + endpoint->SendAcknowledge(); } diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h index 48f334c38f..54f8ad5a1b 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h @@ -101,6 +101,7 @@ class TCPEndpoint : public net_protocol { size_t segmentLength, bool checkSequence); void _MarkEstablished(); status_t _WaitForEstablished(RecursiveLocker &lock, bigtime_t timeout); + void _AddData(tcp_segment_header &segment, net_buffer *buffer); static void _TimeWaitTimer(net_timer *timer, void *data); static void _RetransmitTimer(net_timer *timer, void *data); @@ -153,7 +154,6 @@ class TCPEndpoint : public net_protocol { bool fTracking; uint32 fReceivedTSval; - bool fUsingTimestamps; uint32 fCongestionWindow; uint32 fSlowStartThreshold;