Author: axeld Date: 2010-02-15 14:27:26 +0100 (Mon, 15 Feb 2010) New Revision: 35468 Changeset: http://dev.haiku-os.org/changeset/35468/haiku Modified: haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.cpp haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.h haiku/trunk/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp haiku/trunk/src/add-ons/kernel/network/protocols/tcp/tcp.h Log: * BufferQueue::Free() no longer will return negative values. As is, the max bytes restriction is only a soft limit. This fixes stalling TCP connections because everything received would be out of window once this happened. * Added a TODO to look into TCP's window management - it doesn't seem to be right. * Fixed build with tracing turned on. * Made the fNumber member of tcp_sequence private. Modified: haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.cpp 2010-02-15 13:23:48 UTC (rev 35467) +++ haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.cpp 2010-02-15 13:27:26 UTC (rev 35468) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -59,7 +59,8 @@ void BufferQueue::SetInitialSequence(tcp_sequence sequence) { - TRACE(("BufferQueue@%p::SetInitialSequence(%lu)\n", this, (uint32)sequence)); + TRACE(("BufferQueue@%p::SetInitialSequence(%lu)\n", this, + sequence.Number())); fFirstSequence = fLastSequence = sequence; } @@ -77,9 +78,9 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence) { TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n", - this, buffer, buffer->size, (uint32)sequence)); + this, buffer, buffer->size, sequence.Number())); TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n", - (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, + fFirstSequence.Number(), fLastSequence.Number(), fNumBytes, fContiguousBytes)); VERIFY(); @@ -112,7 +113,7 @@ fNumBytes += buffer->size; TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n", - (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, + fFirstSequence.Number(), fLastSequence.Number(), fNumBytes, fContiguousBytes)); VERIFY(); return; @@ -190,7 +191,7 @@ if (buffer == NULL) { TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n", - (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, + fFirstSequence.Number(), fLastSequence.Number(), fNumBytes, fContiguousBytes)); VERIFY(); return; @@ -217,7 +218,8 @@ } TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n", - (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes)); + fFirstSequence.Number(), fLastSequence.Number(), fNumBytes, + fContiguousBytes)); VERIFY(); } @@ -230,7 +232,8 @@ status_t BufferQueue::RemoveUntil(tcp_sequence sequence) { - TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this, (uint32)sequence)); + TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this, + sequence.Number())); VERIFY(); if (sequence < fFirstSequence) @@ -280,7 +283,7 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes) { TRACE(("BufferQueue@%p::Get(sequence %lu, bytes %lu)\n", this, - (uint32)sequence, bytes)); + sequence.Number(), bytes)); VERIFY(); if (bytes == 0) Modified: haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.h =================================================================== --- haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.h 2010-02-15 13:23:48 UTC (rev 35467) +++ haiku/trunk/src/add-ons/kernel/network/protocols/tcp/BufferQueue.h 2010-02-15 13:27:26 UTC (rev 35468) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -23,61 +23,74 @@ class BufferQueue { public: - BufferQueue(size_t maxBytes); - ~BufferQueue(); + BufferQueue(size_t maxBytes); + ~BufferQueue(); - void SetMaxBytes(size_t maxBytes); - void SetInitialSequence(tcp_sequence sequence); + void SetMaxBytes(size_t maxBytes); + void SetInitialSequence(tcp_sequence sequence); - void Add(net_buffer* buffer); - void Add(net_buffer* buffer, tcp_sequence sequence); - status_t RemoveUntil(tcp_sequence sequence); - status_t Get(net_buffer* buffer, tcp_sequence sequence, - size_t bytes); - status_t Get(size_t bytes, bool remove, - net_buffer** _buffer); + void Add(net_buffer* buffer); + void Add(net_buffer* buffer, tcp_sequence sequence); + status_t RemoveUntil(tcp_sequence sequence); + status_t Get(net_buffer* buffer, tcp_sequence sequence, + size_t bytes); + status_t Get(size_t bytes, bool remove, + net_buffer** _buffer); - size_t Available() const { return fContiguousBytes; } - size_t Available(tcp_sequence sequence) const; + size_t Available() const { return fContiguousBytes; } + size_t Available(tcp_sequence sequence) const; - inline size_t PushedData() const; - void SetPushPointer(); + inline size_t PushedData() const; + void SetPushPointer(); - size_t Used() const { return fNumBytes; } - size_t Free() const { return fMaxBytes - fNumBytes; } - size_t Size() const { return fMaxBytes; } + size_t Used() const { return fNumBytes; } + inline size_t Free() const; + size_t Size() const { return fMaxBytes; } - bool IsContiguous() const - { return fNumBytes == fContiguousBytes; } + bool IsContiguous() const + { return fNumBytes == fContiguousBytes; } - tcp_sequence FirstSequence() const { return fFirstSequence; } - tcp_sequence LastSequence() const { return fLastSequence; } - tcp_sequence NextSequence() const - { return fFirstSequence + fContiguousBytes; } + tcp_sequence FirstSequence() const { return fFirstSequence; } + tcp_sequence LastSequence() const { return fLastSequence; } + tcp_sequence NextSequence() const + { return fFirstSequence + fContiguousBytes; } #if DEBUG_BUFFER_QUEUE - void Verify() const; - void Dump() const; + void Verify() const; + void Dump() const; #endif private: - SegmentList fList; - size_t fMaxBytes; - size_t fNumBytes; - size_t fContiguousBytes; - tcp_sequence fFirstSequence; - tcp_sequence fLastSequence; - tcp_sequence fPushPointer; + SegmentList fList; + size_t fMaxBytes; + size_t fNumBytes; + size_t fContiguousBytes; + tcp_sequence fFirstSequence; + tcp_sequence fLastSequence; + tcp_sequence fPushPointer; }; size_t BufferQueue::PushedData() const { - // we must check if fPushPointer is not 0 here due to + // We must check if fPushPointer is not 0 here due to // tcp_sequence's special handling of > return fPushPointer != 0 && fPushPointer > fFirstSequence ? (fPushPointer - fFirstSequence).Number() : 0; } + +size_t +BufferQueue::Free() const +{ + // Max bytes is a soft limit, so it can be lower than the actual amount of + // data in the queue. TCP should never advertize a window outside the max + // buffer size, though. + if (fMaxBytes > fNumBytes) + return fMaxBytes - fNumBytes; + + return 0; +} + #endif // BUFFER_QUEUE_H Modified: haiku/trunk/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp 2010-02-15 13:23:48 UTC (rev 35467) +++ haiku/trunk/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp 2010-02-15 13:27:26 UTC (rev 35468) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -411,7 +411,8 @@ TCPEndpoint::TCPEndpoint(net_socket* socket) - : ProtocolSocket(socket), + : + ProtocolSocket(socket), fManager(NULL), fReceiveList("tcp receive"), fSendList("tcp send"), @@ -1301,7 +1302,7 @@ fReceiveNext = fReceiveQueue.NextSequence(); TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.", - (uint32)fReceiveNext, fReceiveQueue.Available()); + fReceiveNext.Number(), fReceiveQueue.Available()); if (segment.flags & TCP_FLAG_PUSH) fReceiveQueue.SetPushPointer(); @@ -1515,8 +1516,8 @@ if (!segment_in_sequence(segment, segmentLength, fReceiveNext, fReceiveWindow)) { TRACE(" Receive(): segment out of window, next: %lu wnd: %lu", - (uint32)fReceiveNext, fReceiveWindow); - if (segment.flags & TCP_FLAG_RESET) { + fReceiveNext.Number(), fReceiveWindow); + if ((segment.flags & TCP_FLAG_RESET) != 0) { // TODO: this doesn't look right - review! return DROP; } @@ -1524,7 +1525,7 @@ } } - if (segment.flags & TCP_FLAG_RESET) { + if ((segment.flags & TCP_FLAG_RESET) != 0) { // Is this a valid reset? // We generally ignore resets in time wait state (see RFC 1337) if (fLastAcknowledgeSent <= segment.sequence @@ -1556,9 +1557,11 @@ return DROP | RESET; } + // TODO: Check this! Why do we advertize a window outside of what we should + // buffer? fReceiveWindow = max_c(fReceiveQueue.Free(), fReceiveWindow); // the window must not shrink - + // trim buffer to be within the receive window int32 drop = (int32)(fReceiveNext - segment.sequence).Number(); if (drop > 0) { @@ -1959,7 +1962,7 @@ if (consumedWindow > sendWindow) { sendWindow = 0; - // TODO enter persist state? try to get a window update. + // TODO: enter persist state? try to get a window update. } else sendWindow -= consumedWindow; @@ -2019,8 +2022,8 @@ PrintAddress(buffer->destination), segment.flags, segment.sequence, segment.acknowledge, segment.advertised_window, fCongestionWindow, fSlowStartThreshold, segmentLength, - (uint32)fSendQueue.FirstSequence(), - (uint32)fSendQueue.LastSequence()); + fSendQueue.FirstSequence().Number(), + fSendQueue.LastSequence().Number()); T(Send(this, segment, buffer, fSendQueue.FirstSequence(), fSendQueue.LastSequence())); Modified: haiku/trunk/src/add-ons/kernel/network/protocols/tcp/tcp.h =================================================================== --- haiku/trunk/src/add-ons/kernel/network/protocols/tcp/tcp.h 2010-02-15 13:23:48 UTC (rev 35467) +++ haiku/trunk/src/add-ons/kernel/network/protocols/tcp/tcp.h 2010-02-15 13:27:26 UTC (rev 35468) @@ -108,8 +108,7 @@ return fNumber - 1; } -// Conceptually private, but used in global operators. -//private: +private: uint32 fNumber; }; @@ -120,56 +119,56 @@ inline bool operator>(tcp_sequence a, tcp_sequence b) { - return (int32)(a.fNumber - b.fNumber) > 0; + return (int32)(a.Number() - b.Number()) > 0; } inline bool operator>=(tcp_sequence a, tcp_sequence b) { - return (int32)(a.fNumber - b.fNumber) >= 0; + return (int32)(a.Number() - b.Number()) >= 0; } inline bool operator<(tcp_sequence a, tcp_sequence b) { - return (int32)(a.fNumber - b.fNumber) < 0; + return (int32)(a.Number() - b.Number()) < 0; } inline bool operator<=(tcp_sequence a, tcp_sequence b) { - return (int32)(a.fNumber - b.fNumber) <= 0; + return (int32)(a.Number() - b.Number()) <= 0; } inline tcp_sequence operator+(tcp_sequence a, tcp_sequence b) { - return a.fNumber + b.fNumber; + return a.Number() + b.Number(); } inline tcp_sequence operator-(tcp_sequence a, tcp_sequence b) { - return a.fNumber - b.fNumber; + return a.Number() - b.Number(); } inline bool operator!=(tcp_sequence a, tcp_sequence b) { - return a.fNumber != b.fNumber; + return a.Number() != b.Number(); } inline bool operator==(tcp_sequence a, tcp_sequence b) { - return a.fNumber == b.fNumber; + return a.Number() == b.Number(); }