some TCP tweaks.
- check the effective window against the flight size. - start the RTT estimates relatively high. - introduced a TCP PROBE debug message for offline processing and TCP debugging. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20750 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -46,7 +46,11 @@
|
|||||||
// SACK, Selective Acknowledgment - RFC 2018, RFC 2883, RFC 3517
|
// SACK, Selective Acknowledgment - RFC 2018, RFC 2883, RFC 3517
|
||||||
// Forward RTO-Recovery, RFC 4138
|
// Forward RTO-Recovery, RFC 4138
|
||||||
|
|
||||||
|
#define PrintAddress(address) \
|
||||||
|
AddressString(Domain(), (const sockaddr *)(address), true).Data()
|
||||||
|
|
||||||
//#define TRACE_TCP
|
//#define TRACE_TCP
|
||||||
|
//#define PROBE_TCP
|
||||||
|
|
||||||
#ifdef TRACE_TCP
|
#ifdef TRACE_TCP
|
||||||
// the space before ', ##args' is important in order for this to work with cpp 2.95
|
// the space before ', ##args' is important in order for this to work with cpp 2.95
|
||||||
@@ -56,6 +60,18 @@
|
|||||||
# define TRACE(args...) do { } while (0)
|
# define TRACE(args...) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PROBE_TCP
|
||||||
|
# define PROBE(buffer, window) \
|
||||||
|
dprintf("TCP PROBE %llu %s %s %ld %lu %lu %lu %lu %lu %lu %lu %lu %llu\n", \
|
||||||
|
system_time(), PrintAddress(&buffer->source), \
|
||||||
|
PrintAddress(&buffer->destination), buffer->size, (uint32)fSendNext, \
|
||||||
|
(uint32)fSendUnacknowledged, fCongestionWindow, fSlowStartThreshold, \
|
||||||
|
window, fSendWindow, (uint32)(fSendMax - fSendUnacknowledged), \
|
||||||
|
fSendQueue.Used(), fRetransmitTimeout)
|
||||||
|
#else
|
||||||
|
# define PROBE(buffer, window) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initial estimate for packet round trip time (RTT)
|
// Initial estimate for packet round trip time (RTT)
|
||||||
#define TCP_INITIAL_RTT 4000000
|
#define TCP_INITIAL_RTT 4000000
|
||||||
|
|
||||||
@@ -201,7 +217,8 @@ TCPEndpoint::TCPEndpoint(net_socket *socket)
|
|||||||
fSendWindowShift(0),
|
fSendWindowShift(0),
|
||||||
fReceiveWindowShift(0),
|
fReceiveWindowShift(0),
|
||||||
fSendUnacknowledged(0),
|
fSendUnacknowledged(0),
|
||||||
fSendNext(fSendUnacknowledged),
|
fSendNext(0),
|
||||||
|
fSendMax(0),
|
||||||
fSendWindow(0),
|
fSendWindow(0),
|
||||||
fSendMaxWindow(0),
|
fSendMaxWindow(0),
|
||||||
fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE),
|
fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE),
|
||||||
@@ -214,8 +231,8 @@ TCPEndpoint::TCPEndpoint(net_socket *socket)
|
|||||||
fReceiveWindow(socket->receive.buffer_size),
|
fReceiveWindow(socket->receive.buffer_size),
|
||||||
fReceiveMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE),
|
fReceiveMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE),
|
||||||
fReceiveQueue(socket->receive.buffer_size),
|
fReceiveQueue(socket->receive.buffer_size),
|
||||||
fRoundTripTime(0),
|
fRoundTripTime(TCP_INITIAL_RTT / kTimestampFactor),
|
||||||
fRoundTripDeviation(0),
|
fRoundTripDeviation(TCP_INITIAL_RTT / kTimestampFactor),
|
||||||
fRetransmitTimeout(TCP_INITIAL_RTT),
|
fRetransmitTimeout(TCP_INITIAL_RTT),
|
||||||
fReceivedTSval(0),
|
fReceivedTSval(0),
|
||||||
fCongestionWindow(0),
|
fCongestionWindow(0),
|
||||||
@@ -356,8 +373,7 @@ TCPEndpoint::Free()
|
|||||||
status_t
|
status_t
|
||||||
TCPEndpoint::Connect(const sockaddr *address)
|
TCPEndpoint::Connect(const sockaddr *address)
|
||||||
{
|
{
|
||||||
TRACE("Connect() on address %s",
|
TRACE("Connect() on address %s", PrintAddress(address));
|
||||||
AddressString(Domain(), address, true).Data());
|
|
||||||
|
|
||||||
RecursiveLocker locker(fLock);
|
RecursiveLocker locker(fLock);
|
||||||
|
|
||||||
@@ -444,8 +460,7 @@ TCPEndpoint::Bind(sockaddr *address)
|
|||||||
|
|
||||||
RecursiveLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
|
|
||||||
TRACE("Bind() on address %s",
|
TRACE("Bind() on address %s", PrintAddress(address));
|
||||||
AddressString(Domain(), address, true).Data());
|
|
||||||
|
|
||||||
if (fState != CLOSED)
|
if (fState != CLOSED)
|
||||||
return EISCONN;
|
return EISCONN;
|
||||||
@@ -460,9 +475,8 @@ TCPEndpoint::Bind(sockaddr *address)
|
|||||||
else
|
else
|
||||||
status = fManager->Bind(this);
|
status = fManager->Bind(this);
|
||||||
|
|
||||||
TRACE(" Bind() bound to %s (status %i)",
|
TRACE(" Bind() bound to %s (status %i)", PrintAddress(&socket->address),
|
||||||
AddressString(Domain(), (sockaddr *)&socket->address, true).Data(),
|
(int)status);
|
||||||
(int)status);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -849,9 +863,8 @@ TCPEndpoint::SegmentReceived(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
RecursiveLocker locker(fLock);
|
RecursiveLocker locker(fLock);
|
||||||
|
|
||||||
TRACE("SegmentReceived(): buffer %p (%lu bytes) address %s to %s",
|
TRACE("SegmentReceived(): buffer %p (%lu bytes) address %s to %s",
|
||||||
buffer, buffer->size, AddressString(Domain(),
|
buffer, buffer->size, PrintAddress(&buffer->source),
|
||||||
(sockaddr *)&buffer->source, true).Data(), AddressString(Domain(),
|
PrintAddress(&buffer->destination));
|
||||||
(sockaddr *)&buffer->destination, true).Data());
|
|
||||||
TRACE(" flags 0x%x, seq %lu, ack %lu, wnd %lu",
|
TRACE(" flags 0x%x, seq %lu, ack %lu, wnd %lu",
|
||||||
segment.flags, segment.sequence, segment.acknowledge,
|
segment.flags, segment.sequence, segment.acknowledge,
|
||||||
(uint32)segment.advertised_window << fSendWindowShift);
|
(uint32)segment.advertised_window << fSendWindowShift);
|
||||||
@@ -1063,23 +1076,23 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
if (fCongestionWindow > 0)
|
if (fCongestionWindow > 0)
|
||||||
sendWindow = min_c(sendWindow, fCongestionWindow);
|
sendWindow = min_c(sendWindow, fCongestionWindow);
|
||||||
|
|
||||||
|
// a TCP may not send more data to the network than the
|
||||||
|
// currently unacknowledged sequence (SND.UNA) plus the
|
||||||
|
// calculated send window.
|
||||||
|
|
||||||
|
uint32 flightSize = fSendMax - fSendUnacknowledged;
|
||||||
|
if (flightSize > sendWindow) {
|
||||||
|
sendWindow = 0;
|
||||||
|
// TODO enter persist state? try to get a window update.
|
||||||
|
} else
|
||||||
|
sendWindow -= flightSize;
|
||||||
|
|
||||||
if (force && sendWindow == 0 && fSendNext <= fSendQueue.LastSequence()) {
|
if (force && sendWindow == 0 && fSendNext <= fSendQueue.LastSequence()) {
|
||||||
// send one byte of data to ask for a window update
|
// send one byte of data to ask for a window update
|
||||||
// (triggered by the persist timer)
|
// (triggered by the persist timer)
|
||||||
sendWindow = 1;
|
sendWindow = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// a TCP may not send more data to the network than the
|
|
||||||
// currently unacknowledged sequence (SND.UNA) plus the
|
|
||||||
// calculated send window.
|
|
||||||
|
|
||||||
if ((fSendNext - fSendUnacknowledged) > sendWindow) {
|
|
||||||
sendWindow = 0;
|
|
||||||
// TODO enter persist state? try to get a window update.
|
|
||||||
} else
|
|
||||||
sendWindow -= (fSendNext - fSendUnacknowledged);
|
|
||||||
|
|
||||||
uint32 flightSize = fSendMax - fSendUnacknowledged;
|
|
||||||
uint32 length = min_c(fSendQueue.Available(fSendNext), sendWindow);
|
uint32 length = min_c(fSendQueue.Available(fSendNext), sendWindow);
|
||||||
tcp_sequence previousSendNext = fSendNext;
|
tcp_sequence previousSendNext = fSendNext;
|
||||||
|
|
||||||
@@ -1124,14 +1137,16 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
segment.sequence = fSendNext;
|
segment.sequence = fSendNext;
|
||||||
|
|
||||||
TRACE("SendQueued(): buffer %p (%lu bytes) address %s to %s",
|
TRACE("SendQueued(): buffer %p (%lu bytes) address %s to %s",
|
||||||
buffer, buffer->size, AddressString(Domain(),
|
buffer, buffer->size, PrintAddress(&buffer->source),
|
||||||
(sockaddr *)&buffer->source, true).Data(), AddressString(Domain(),
|
PrintAddress(&buffer->destination));
|
||||||
(sockaddr *)&buffer->destination, true).Data());
|
|
||||||
TRACE(" flags 0x%x, seq %lu, ack %lu, rwnd %hu, cwnd %lu"
|
TRACE(" flags 0x%x, seq %lu, ack %lu, rwnd %hu, cwnd %lu"
|
||||||
", ssthresh %lu", segment.flags, segment.sequence,
|
", ssthresh %lu", segment.flags, segment.sequence,
|
||||||
segment.acknowledge, segment.advertised_window,
|
segment.acknowledge, segment.advertised_window,
|
||||||
fCongestionWindow, fSlowStartThreshold);
|
fCongestionWindow, fSlowStartThreshold);
|
||||||
|
|
||||||
|
PROBE(buffer, sendWindow);
|
||||||
|
sendWindow -= buffer->size;
|
||||||
|
|
||||||
status = add_tcp_header(AddressModule(), segment, buffer);
|
status = add_tcp_header(AddressModule(), segment, buffer);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user