support TCP Window Scale on sent segments.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20729 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
// constants for the fFlags field
|
// constants for the fFlags field
|
||||||
enum {
|
enum {
|
||||||
FLAG_OPTION_WINDOW_SHIFT = 0x01,
|
FLAG_OPTION_WINDOW_SCALE = 0x01,
|
||||||
FLAG_OPTION_TIMESTAMP = 0x02,
|
FLAG_OPTION_TIMESTAMP = 0x02,
|
||||||
// TODO: Should FLAG_NO_RECEIVE apply as well to received connections?
|
// TODO: Should FLAG_NO_RECEIVE apply as well to received connections?
|
||||||
// That is, what is expected from accept() after a shutdown()
|
// That is, what is expected from accept() after a shutdown()
|
||||||
@@ -180,9 +180,8 @@ TCPEndpoint::TCPEndpoint(net_socket *socket)
|
|||||||
fReceiveQueue(socket->receive.buffer_size),
|
fReceiveQueue(socket->receive.buffer_size),
|
||||||
fRoundTripTime(TCP_INITIAL_RTT),
|
fRoundTripTime(TCP_INITIAL_RTT),
|
||||||
fReceivedTSval(0),
|
fReceivedTSval(0),
|
||||||
fUsingTimestamps(false),
|
|
||||||
fState(CLOSED),
|
fState(CLOSED),
|
||||||
fFlags(0), //FLAG_OPTION_WINDOW_SHIFT),
|
fFlags(FLAG_OPTION_WINDOW_SCALE | FLAG_OPTION_TIMESTAMP),
|
||||||
fError(B_OK),
|
fError(B_OK),
|
||||||
fSpawned(false)
|
fSpawned(false)
|
||||||
{
|
{
|
||||||
@@ -366,10 +365,6 @@ TCPEndpoint::Connect(const struct sockaddr *address)
|
|||||||
fSendMax = fInitialSendSequence;
|
fSendMax = fInitialSendSequence;
|
||||||
fSendQueue.SetInitialSequence(fSendNext + 1);
|
fSendQueue.SetInitialSequence(fSendNext + 1);
|
||||||
|
|
||||||
// try to use timestamps, if the peer doesn't reply with the TS
|
|
||||||
// option as well we'll stop using them.
|
|
||||||
fUsingTimestamps = true;
|
|
||||||
|
|
||||||
// send SYN
|
// send SYN
|
||||||
status = _SendQueued();
|
status = _SendQueued();
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
@@ -693,7 +688,7 @@ TCPEndpoint::DelayedAcknowledge()
|
|||||||
if (gStackModule->cancel_timer(&fDelayedAcknowledgeTimer)) {
|
if (gStackModule->cancel_timer(&fDelayedAcknowledgeTimer)) {
|
||||||
// timer was active, send an ACK now (with the exception above,
|
// timer was active, send an ACK now (with the exception above,
|
||||||
// we send every other ACK)
|
// we send every other ACK)
|
||||||
return _SendQueued();
|
return SendAcknowledge();
|
||||||
}
|
}
|
||||||
|
|
||||||
gStackModule->set_timer(&fDelayedAcknowledgeTimer, TCP_DELAYED_ACKNOWLEDGE_TIMEOUT);
|
gStackModule->set_timer(&fDelayedAcknowledgeTimer, TCP_DELAYED_ACKNOWLEDGE_TIMEOUT);
|
||||||
@@ -808,10 +803,10 @@ TCPEndpoint::Spawn(TCPEndpoint *parent, tcp_segment_header &segment,
|
|||||||
else
|
else
|
||||||
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
|
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
|
||||||
if (segment.has_window_shift) {
|
if (segment.has_window_shift) {
|
||||||
fFlags |= FLAG_OPTION_WINDOW_SHIFT;
|
fFlags |= FLAG_OPTION_WINDOW_SCALE;
|
||||||
fSendWindowShift = segment.window_shift;
|
fSendWindowShift = segment.window_shift;
|
||||||
} else {
|
} else {
|
||||||
fFlags &= ~FLAG_OPTION_WINDOW_SHIFT;
|
fFlags &= ~FLAG_OPTION_WINDOW_SCALE;
|
||||||
fReceiveWindowShift = 0;
|
fReceiveWindowShift = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,10 +860,10 @@ TCPEndpoint::_SynchronizeSentReceive(tcp_segment_header &segment, net_buffer *bu
|
|||||||
else
|
else
|
||||||
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
|
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
|
||||||
if (segment.has_window_shift) {
|
if (segment.has_window_shift) {
|
||||||
fFlags |= FLAG_OPTION_WINDOW_SHIFT;
|
fFlags |= FLAG_OPTION_WINDOW_SCALE;
|
||||||
fSendWindowShift = segment.window_shift;
|
fSendWindowShift = segment.window_shift;
|
||||||
} else {
|
} else {
|
||||||
fFlags &= ~FLAG_OPTION_WINDOW_SHIFT;
|
fFlags &= ~FLAG_OPTION_WINDOW_SCALE;
|
||||||
fReceiveWindowShift = 0;
|
fReceiveWindowShift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,19 +970,10 @@ TCPEndpoint::_SegmentReceived(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
&& fReceiveQueue.IsContiguous()
|
&& fReceiveQueue.IsContiguous()
|
||||||
&& fReceiveQueue.Free() >= buffer->size
|
&& fReceiveQueue.Free() >= buffer->size
|
||||||
&& !(fFlags & FLAG_NO_RECEIVE)) {
|
&& !(fFlags & FLAG_NO_RECEIVE)) {
|
||||||
TRACE("Receive(): header prediction receive!");
|
_AddData(segment, buffer);
|
||||||
// we're on the receiving end of the connection, and this segment
|
|
||||||
// is the one we were expecting, in-sequence
|
|
||||||
fReceiveNext += buffer->size;
|
|
||||||
TRACE("Receive(): receive next = %lu", (uint32)fReceiveNext);
|
|
||||||
fReceiveQueue.Add(buffer, segment.sequence);
|
|
||||||
if (segment.flags & TCP_FLAG_PUSH)
|
|
||||||
fReceiveQueue.SetPushPointer();
|
|
||||||
|
|
||||||
_NotifyReader();
|
_NotifyReader();
|
||||||
|
return KEEP | ((segment.flags & TCP_FLAG_PUSH) ?
|
||||||
return KEEP | (segment.flags & TCP_FLAG_PUSH ?
|
IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE);
|
||||||
IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1104,10 +1090,10 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
segment.flags = _CurrentFlags();
|
segment.flags = _CurrentFlags();
|
||||||
segment.urgent_offset = 0;
|
segment.urgent_offset = 0;
|
||||||
|
|
||||||
if (fUsingTimestamps) {
|
if (fOptions & FLAG_OPTION_TIMESTAMP) {
|
||||||
segment.has_timestamps = true;
|
segment.has_timestamps = true;
|
||||||
segment.TSecr = fReceivedTSval;
|
segment.TSecr = fReceivedTSval;
|
||||||
segment.TSval = system_time();
|
segment.TSval = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 sendWindow = fSendWindow;
|
uint32 sendWindow = fSendWindow;
|
||||||
@@ -1138,8 +1124,13 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
segment.flags &= ~TCP_FLAG_FINISH;
|
segment.flags &= ~TCP_FLAG_FINISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
segment.advertised_window = min_c(65535, fReceiveQueue.Free());
|
size_t availableBytes = fReceiveQueue.Free();
|
||||||
// TODO: support shift option!
|
|
||||||
|
if (fOptions & FLAG_OPTION_WINDOW_SCALE)
|
||||||
|
segment.advertised_window = availableBytes >> fReceiveWindowShift;
|
||||||
|
else
|
||||||
|
segment.advertised_window = min_c(TCP_MAX_WINDOW, availableBytes);
|
||||||
|
|
||||||
segment.acknowledge = fReceiveNext;
|
segment.acknowledge = fReceiveNext;
|
||||||
segment.urgent_offset = 0;
|
segment.urgent_offset = 0;
|
||||||
|
|
||||||
@@ -1150,7 +1141,6 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
&& !gStackModule->is_timer_active(&fPersistTimer)
|
&& !gStackModule->is_timer_active(&fPersistTimer)
|
||||||
&& !gStackModule->is_timer_active(&fRetransmitTimer))
|
&& !gStackModule->is_timer_active(&fRetransmitTimer))
|
||||||
_StartPersistTimer();
|
_StartPersistTimer();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1181,7 +1171,7 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
&& (fOptions & TCP_NOOPT) == 0) {
|
&& (fOptions & TCP_NOOPT) == 0) {
|
||||||
// add connection establishment options
|
// add connection establishment options
|
||||||
segment.max_segment_size = fReceiveMaxSegmentSize;
|
segment.max_segment_size = fReceiveMaxSegmentSize;
|
||||||
if ((fFlags & FLAG_OPTION_WINDOW_SHIFT) != 0) {
|
if (fFlags & FLAG_OPTION_WINDOW_SCALE) {
|
||||||
segment.has_window_shift = true;
|
segment.has_window_shift = true;
|
||||||
segment.window_shift = fReceiveWindowShift;
|
segment.window_shift = fReceiveWindowShift;
|
||||||
}
|
}
|
||||||
@@ -1487,17 +1477,10 @@ TCPEndpoint::_Receive(tcp_segment_header &segment, net_buffer *buffer)
|
|||||||
bool notify = false;
|
bool notify = false;
|
||||||
|
|
||||||
if (buffer->size > 0 && _ShouldReceive()) {
|
if (buffer->size > 0 && _ShouldReceive()) {
|
||||||
fReceiveQueue.Add(buffer, segment.sequence);
|
_AddData(segment, buffer);
|
||||||
fReceiveNext += buffer->size;
|
|
||||||
notify = true;
|
notify = true;
|
||||||
TRACE("Receive(): adding data, receive next = %lu. Now have %lu bytes.",
|
} else
|
||||||
(uint32)fReceiveNext, fReceiveQueue.Available());
|
|
||||||
|
|
||||||
if (segment.flags & TCP_FLAG_PUSH)
|
|
||||||
fReceiveQueue.SetPushPointer();
|
|
||||||
} else {
|
|
||||||
action = (action & ~KEEP) | DROP;
|
action = (action & ~KEEP) | DROP;
|
||||||
}
|
|
||||||
|
|
||||||
if (segment.flags & TCP_FLAG_FINISH) {
|
if (segment.flags & TCP_FLAG_FINISH) {
|
||||||
segmentLength++;
|
segmentLength++;
|
||||||
@@ -1550,9 +1533,12 @@ void
|
|||||||
TCPEndpoint::_UpdateTimestamps(tcp_segment_header &segment, size_t segmentLength,
|
TCPEndpoint::_UpdateTimestamps(tcp_segment_header &segment, size_t segmentLength,
|
||||||
bool checkSequence)
|
bool checkSequence)
|
||||||
{
|
{
|
||||||
fUsingTimestamps = segment.has_timestamps;
|
if (segment.has_timestamps)
|
||||||
|
fOptions |= FLAG_OPTION_TIMESTAMP;
|
||||||
|
else
|
||||||
|
fOptions &= ~FLAG_OPTION_TIMESTAMP;
|
||||||
|
|
||||||
if (fUsingTimestamps) {
|
if (fOptions & FLAG_OPTION_TIMESTAMP) {
|
||||||
tcp_sequence sequence(segment.sequence);
|
tcp_sequence sequence(segment.sequence);
|
||||||
|
|
||||||
if (!checkSequence || (fLastAcknowledgeSent >= sequence
|
if (!checkSequence || (fLastAcknowledgeSent >= sequence
|
||||||
@@ -1589,6 +1575,20 @@ TCPEndpoint::_WaitForEstablished(RecursiveLocker &locker, bigtime_t timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TCPEndpoint::_AddData(tcp_segment_header &segment, net_buffer *buffer)
|
||||||
|
{
|
||||||
|
fReceiveNext += buffer->size;
|
||||||
|
fReceiveQueue.Add(buffer, segment.sequence);
|
||||||
|
|
||||||
|
TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.",
|
||||||
|
(uint32)fReceiveNext, fReceiveQueue.Available());
|
||||||
|
|
||||||
|
if (segment.flags & TCP_FLAG_PUSH)
|
||||||
|
fReceiveQueue.SetPushPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - timer
|
// #pragma mark - timer
|
||||||
|
|
||||||
|
|
||||||
@@ -1629,7 +1629,7 @@ TCPEndpoint::_DelayedAcknowledgeTimer(struct net_timer *timer, void *data)
|
|||||||
if (!locker.IsLocked())
|
if (!locker.IsLocked())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
endpoint->_SendQueued(true);
|
endpoint->SendAcknowledge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class TCPEndpoint : public net_protocol {
|
|||||||
size_t segmentLength, bool checkSequence);
|
size_t segmentLength, bool checkSequence);
|
||||||
void _MarkEstablished();
|
void _MarkEstablished();
|
||||||
status_t _WaitForEstablished(RecursiveLocker &lock, bigtime_t timeout);
|
status_t _WaitForEstablished(RecursiveLocker &lock, bigtime_t timeout);
|
||||||
|
void _AddData(tcp_segment_header &segment, net_buffer *buffer);
|
||||||
|
|
||||||
static void _TimeWaitTimer(net_timer *timer, void *data);
|
static void _TimeWaitTimer(net_timer *timer, void *data);
|
||||||
static void _RetransmitTimer(net_timer *timer, void *data);
|
static void _RetransmitTimer(net_timer *timer, void *data);
|
||||||
@@ -153,7 +154,6 @@ class TCPEndpoint : public net_protocol {
|
|||||||
bool fTracking;
|
bool fTracking;
|
||||||
|
|
||||||
uint32 fReceivedTSval;
|
uint32 fReceivedTSval;
|
||||||
bool fUsingTimestamps;
|
|
||||||
|
|
||||||
uint32 fCongestionWindow;
|
uint32 fCongestionWindow;
|
||||||
uint32 fSlowStartThreshold;
|
uint32 fSlowStartThreshold;
|
||||||
|
|||||||
Reference in New Issue
Block a user