* 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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user