* 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",
|
TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n",
|
||||||
this, buffer, buffer->size, (uint32)sequence));
|
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;
|
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
|
// we usually just add the buffer to the end of the queue
|
||||||
fList.Add(buffer);
|
fList.Add(buffer);
|
||||||
|
|
||||||
if (sequence == fLastSequence && fLastSequence - fFirstSequence == fNumBytes) {
|
if (sequence == fLastSequence
|
||||||
// there is no hole in the buffer, we can make the whole buffer available
|
&& fLastSequence - fFirstSequence == fNumBytes) {
|
||||||
|
// there is no hole in the buffer, we can make the whole buffer
|
||||||
|
// available
|
||||||
fContiguousBytes += buffer->size;
|
fContiguousBytes += buffer->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
fLastSequence = sequence + buffer->size;
|
fLastSequence = sequence + buffer->size;
|
||||||
fNumBytes += 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +105,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
sequence = fFirstSequence;
|
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();
|
SegmentList::ReverseIterator iterator = fList.GetReverseIterator();
|
||||||
net_buffer *previous = NULL;
|
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
|
// check if we have duplicate data, and remove it if that is the case
|
||||||
if (previous != NULL) {
|
if (previous != NULL) {
|
||||||
if (sequence == previous->sequence) {
|
if (sequence == previous->sequence) {
|
||||||
// we already have at least part of this data - ignore new data whenever
|
// we already have at least part of this data - ignore new data
|
||||||
// it makes sense (because some TCP implementations send bogus data when
|
// whenever it makes sense (because some TCP implementations send
|
||||||
// probing the window)
|
// bogus data when probing the window)
|
||||||
if (previous->size >= buffer->size) {
|
if (previous->size >= buffer->size) {
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
@@ -127,8 +132,10 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
fList.Remove(previous);
|
fList.Remove(previous);
|
||||||
gBufferModule->free(previous);
|
gBufferModule->free(previous);
|
||||||
}
|
}
|
||||||
} else if (tcp_sequence(previous->sequence + previous->size) > sequence)
|
} else if (tcp_sequence(previous->sequence + previous->size) > sequence) {
|
||||||
gBufferModule->remove_header(buffer, previous->sequence + previous->size - sequence);
|
gBufferModule->remove_header(buffer,
|
||||||
|
previous->sequence + previous->size - sequence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer != NULL && next != NULL
|
if (buffer != NULL && next != NULL
|
||||||
@@ -140,12 +147,15 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
|
|
||||||
fList.Remove(remove);
|
fList.Remove(remove);
|
||||||
gBufferModule->free(remove);
|
gBufferModule->free(remove);
|
||||||
} else
|
} else {
|
||||||
gBufferModule->remove_trailer(buffer, next->sequence - (sequence + buffer->size));
|
gBufferModule->remove_trailer(buffer,
|
||||||
|
sequence + buffer->size - next->sequence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer == NULL) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,10 +174,12 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
fContiguousBytes += buffer->size;
|
fContiguousBytes += buffer->size;
|
||||||
|
|
||||||
buffer = (struct net_buffer *)buffer->link.next;
|
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
|
#ifdef PROBE_TCP
|
||||||
# define PROBE(buffer, window) \
|
# 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), \
|
system_time(), PrintAddress(buffer->source), \
|
||||||
PrintAddress(buffer->destination), buffer->size, (uint32)fSendNext, \
|
PrintAddress(buffer->destination), buffer->size, (uint32)fSendNext, \
|
||||||
(uint32)fSendUnacknowledged, fCongestionWindow, fSlowStartThreshold, \
|
(uint32)fSendUnacknowledged, fCongestionWindow, fSlowStartThreshold, \
|
||||||
@@ -1320,7 +1320,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
TCPEndpoint::_GetMSS(const sockaddr *address) const
|
TCPEndpoint::_MaxSegmentSize(const sockaddr *address) const
|
||||||
{
|
{
|
||||||
return next->module->get_mtu(next, address) - sizeof(tcp_header);
|
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
|
// we are counting the SYN here
|
||||||
fSendQueue.SetInitialSequence(fSendNext + 1);
|
fSendQueue.SetInitialSequence(fSendNext + 1);
|
||||||
|
|
||||||
fReceiveMaxSegmentSize = _GetMSS(peer);
|
fReceiveMaxSegmentSize = _MaxSegmentSize(peer);
|
||||||
|
|
||||||
// Compute the window shift we advertise to our peer - if it doesn't support
|
// 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)
|
// 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);
|
uint32 segmentMaxSize, uint32 flightSize);
|
||||||
status_t _SendQueued(bool force = false);
|
status_t _SendQueued(bool force = false);
|
||||||
status_t _SendQueued(bool force, uint32 sendWindow);
|
status_t _SendQueued(bool force, uint32 sendWindow);
|
||||||
int _GetMSS(const struct sockaddr *) const;
|
int _MaxSegmentSize(const struct sockaddr *) const;
|
||||||
status_t _ShutdownEgress(bool closing);
|
status_t _ShutdownEgress(bool closing);
|
||||||
ssize_t _AvailableData() const;
|
ssize_t _AvailableData() const;
|
||||||
void _NotifyReader();
|
void _NotifyReader();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <NetBufferUtilities.h>
|
#include <NetBufferUtilities.h>
|
||||||
#include <NetUtilities.h>
|
#include <NetUtilities.h>
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_TCP
|
//#define TRACE_TCP
|
||||||
#ifdef TRACE_TCP
|
#ifdef TRACE_TCP
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
|
|||||||
Reference in New Issue
Block a user