* If a new buffer had its last part in common with an existing larger buffer,

BufferQueue::Add() tried to remove a negative amount of bytes. This could
  bring a download to a complete halt (as could the other one due to the list
  link mixup).
* While the RTT computation still seems to work not that good (with a drop quote
  of 50% I would easily reach retransmit timeouts of 80 secs), TCP should now
  work a lot better on a flaky connection.
* Renamed _GetMSS() to _MaxSegmentSize().
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22677 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-10-23 10:42:46 +00:00
parent c76695a275
commit 1d0b34faae
4 changed files with 32 additions and 19 deletions
@@ -72,7 +72,8 @@ 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));
TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n", (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
buffer->sequence = sequence;
@@ -80,14 +81,18 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
// we usually just add the buffer to the end of the queue
fList.Add(buffer);
if (sequence == fLastSequence && fLastSequence - fFirstSequence == fNumBytes) {
// there is no hole in the buffer, we can make the whole buffer available
if (sequence == fLastSequence
&& fLastSequence - fFirstSequence == fNumBytes) {
// there is no hole in the buffer, we can make the whole buffer
// available
fContiguousBytes += buffer->size;
}
fLastSequence = sequence + buffer->size;
fNumBytes += buffer->size;
TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n", (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
return;
}
@@ -100,7 +105,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
sequence = fFirstSequence;
}
// find for the place where to insert the buffer into the queue
// find the place where to insert the buffer into the queue
SegmentList::ReverseIterator iterator = fList.GetReverseIterator();
net_buffer *previous = NULL;
@@ -117,9 +122,9 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
// check if we have duplicate data, and remove it if that is the case
if (previous != NULL) {
if (sequence == previous->sequence) {
// we already have at least part of this data - ignore new data whenever
// it makes sense (because some TCP implementations send bogus data when
// probing the window)
// we already have at least part of this data - ignore new data
// whenever it makes sense (because some TCP implementations send
// bogus data when probing the window)
if (previous->size >= buffer->size) {
gBufferModule->free(buffer);
buffer = NULL;
@@ -127,8 +132,10 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
fList.Remove(previous);
gBufferModule->free(previous);
}
} else if (tcp_sequence(previous->sequence + previous->size) > sequence)
gBufferModule->remove_header(buffer, previous->sequence + previous->size - sequence);
} else if (tcp_sequence(previous->sequence + previous->size) > sequence) {
gBufferModule->remove_header(buffer,
previous->sequence + previous->size - sequence);
}
}
if (buffer != NULL && next != NULL
@@ -140,12 +147,15 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
fList.Remove(remove);
gBufferModule->free(remove);
} else
gBufferModule->remove_trailer(buffer, next->sequence - (sequence + buffer->size));
} else {
gBufferModule->remove_trailer(buffer,
sequence + buffer->size - next->sequence);
}
}
if (buffer == NULL) {
TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n", (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
return;
}
@@ -164,10 +174,12 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
fContiguousBytes += buffer->size;
buffer = (struct net_buffer *)buffer->link.next;
} while (buffer != NULL && fFirstSequence + fContiguousBytes == buffer->sequence);
} while (buffer != NULL
&& fFirstSequence + fContiguousBytes == buffer->sequence);
}
TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n", (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
}
@@ -64,7 +64,7 @@
#ifdef PROBE_TCP
# define PROBE(buffer, window) \
dprintf("TCP PROBE %llu %s %s %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu\n", \
dprintf("TCP PROBE %llu %s %s %ld snxt %lu suna %lu cw %lu sst %lu win %lu swin %lu smax-suna %lu savail %lu sqused %lu rto %llu\n", \
system_time(), PrintAddress(buffer->source), \
PrintAddress(buffer->destination), buffer->size, (uint32)fSendNext, \
(uint32)fSendUnacknowledged, fCongestionWindow, fSlowStartThreshold, \
@@ -1320,7 +1320,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
int
TCPEndpoint::_GetMSS(const sockaddr *address) const
TCPEndpoint::_MaxSegmentSize(const sockaddr *address) const
{
return next->module->get_mtu(next, address) - sizeof(tcp_header);
}
@@ -1714,7 +1714,7 @@ TCPEndpoint::_PrepareSendPath(const sockaddr *peer)
// we are counting the SYN here
fSendQueue.SetInitialSequence(fSendNext + 1);
fReceiveMaxSegmentSize = _GetMSS(peer);
fReceiveMaxSegmentSize = _MaxSegmentSize(peer);
// Compute the window shift we advertise to our peer - if it doesn't support
// this option, this will be reset to 0 (when its SYN is received)
@@ -94,7 +94,7 @@ class TCPEndpoint : public net_protocol, public ProtocolSocket {
uint32 segmentMaxSize, uint32 flightSize);
status_t _SendQueued(bool force = false);
status_t _SendQueued(bool force, uint32 sendWindow);
int _GetMSS(const struct sockaddr *) const;
int _MaxSegmentSize(const struct sockaddr *) const;
status_t _ShutdownEgress(bool closing);
ssize_t _AvailableData() const;
void _NotifyReader();
@@ -30,6 +30,7 @@
#include <NetBufferUtilities.h>
#include <NetUtilities.h>
//#define TRACE_TCP
#ifdef TRACE_TCP
# define TRACE(x) dprintf x