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:
Hugo Santos 2007-04-17 01:07:58 +00:00
parent 31ebfe61e4
commit 58bef2f444
2 changed files with 43 additions and 43 deletions

View File

@ -61,7 +61,7 @@
// constants for the fFlags field
enum {
FLAG_OPTION_WINDOW_SHIFT = 0x01,
FLAG_OPTION_WINDOW_SCALE = 0x01,
FLAG_OPTION_TIMESTAMP = 0x02,
// TODO: Should FLAG_NO_RECEIVE apply as well to received connections?
// That is, what is expected from accept() after a shutdown()
@ -180,9 +180,8 @@ TCPEndpoint::TCPEndpoint(net_socket *socket)
fReceiveQueue(socket->receive.buffer_size),
fRoundTripTime(TCP_INITIAL_RTT),
fReceivedTSval(0),
fUsingTimestamps(false),
fState(CLOSED),
fFlags(0), //FLAG_OPTION_WINDOW_SHIFT),
fFlags(FLAG_OPTION_WINDOW_SCALE | FLAG_OPTION_TIMESTAMP),
fError(B_OK),
fSpawned(false)
{
@ -366,10 +365,6 @@ TCPEndpoint::Connect(const struct sockaddr *address)
fSendMax = fInitialSendSequence;
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
status = _SendQueued();
if (status != B_OK) {
@ -693,7 +688,7 @@ TCPEndpoint::DelayedAcknowledge()
if (gStackModule->cancel_timer(&fDelayedAcknowledgeTimer)) {
// timer was active, send an ACK now (with the exception above,
// we send every other ACK)
return _SendQueued();
return SendAcknowledge();
}
gStackModule->set_timer(&fDelayedAcknowledgeTimer, TCP_DELAYED_ACKNOWLEDGE_TIMEOUT);
@ -808,10 +803,10 @@ TCPEndpoint::Spawn(TCPEndpoint *parent, tcp_segment_header &segment,
else
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
if (segment.has_window_shift) {
fFlags |= FLAG_OPTION_WINDOW_SHIFT;
fFlags |= FLAG_OPTION_WINDOW_SCALE;
fSendWindowShift = segment.window_shift;
} else {
fFlags &= ~FLAG_OPTION_WINDOW_SHIFT;
fFlags &= ~FLAG_OPTION_WINDOW_SCALE;
fReceiveWindowShift = 0;
}
}
@ -865,10 +860,10 @@ TCPEndpoint::_SynchronizeSentReceive(tcp_segment_header &segment, net_buffer *bu
else
fReceiveMaxSegmentSize = TCP_DEFAULT_MAX_SEGMENT_SIZE;
if (segment.has_window_shift) {
fFlags |= FLAG_OPTION_WINDOW_SHIFT;
fFlags |= FLAG_OPTION_WINDOW_SCALE;
fSendWindowShift = segment.window_shift;
} else {
fFlags &= ~FLAG_OPTION_WINDOW_SHIFT;
fFlags &= ~FLAG_OPTION_WINDOW_SCALE;
fReceiveWindowShift = 0;
}
@ -975,19 +970,10 @@ TCPEndpoint::_SegmentReceived(tcp_segment_header &segment, net_buffer *buffer)
&& fReceiveQueue.IsContiguous()
&& fReceiveQueue.Free() >= buffer->size
&& !(fFlags & FLAG_NO_RECEIVE)) {
TRACE("Receive(): header prediction receive!");
// 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();
_AddData(segment, buffer);
_NotifyReader();
return KEEP | (segment.flags & TCP_FLAG_PUSH ?
IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE);
return KEEP | ((segment.flags & TCP_FLAG_PUSH) ?
IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE);
}
}
@ -1104,10 +1090,10 @@ TCPEndpoint::_SendQueued(bool force)
segment.flags = _CurrentFlags();
segment.urgent_offset = 0;
if (fUsingTimestamps) {
if (fOptions & FLAG_OPTION_TIMESTAMP) {
segment.has_timestamps = true;
segment.TSecr = fReceivedTSval;
segment.TSval = system_time();
segment.TSval = 0;
}
uint32 sendWindow = fSendWindow;
@ -1138,8 +1124,13 @@ TCPEndpoint::_SendQueued(bool force)
segment.flags &= ~TCP_FLAG_FINISH;
}
segment.advertised_window = min_c(65535, fReceiveQueue.Free());
// TODO: support shift option!
size_t availableBytes = fReceiveQueue.Free();
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.urgent_offset = 0;
@ -1150,7 +1141,6 @@ TCPEndpoint::_SendQueued(bool force)
&& !gStackModule->is_timer_active(&fPersistTimer)
&& !gStackModule->is_timer_active(&fRetransmitTimer))
_StartPersistTimer();
return B_OK;
}
@ -1181,7 +1171,7 @@ TCPEndpoint::_SendQueued(bool force)
&& (fOptions & TCP_NOOPT) == 0) {
// add connection establishment options
segment.max_segment_size = fReceiveMaxSegmentSize;
if ((fFlags & FLAG_OPTION_WINDOW_SHIFT) != 0) {
if (fFlags & FLAG_OPTION_WINDOW_SCALE) {
segment.has_window_shift = true;
segment.window_shift = fReceiveWindowShift;
}
@ -1487,17 +1477,10 @@ TCPEndpoint::_Receive(tcp_segment_header &segment, net_buffer *buffer)
bool notify = false;
if (buffer->size > 0 && _ShouldReceive()) {
fReceiveQueue.Add(buffer, segment.sequence);
fReceiveNext += buffer->size;
_AddData(segment, buffer);
notify = true;
TRACE("Receive(): adding data, receive next = %lu. Now have %lu bytes.",
(uint32)fReceiveNext, fReceiveQueue.Available());
if (segment.flags & TCP_FLAG_PUSH)
fReceiveQueue.SetPushPointer();
} else {
} else
action = (action & ~KEEP) | DROP;
}
if (segment.flags & TCP_FLAG_FINISH) {
segmentLength++;
@ -1550,9 +1533,12 @@ void
TCPEndpoint::_UpdateTimestamps(tcp_segment_header &segment, size_t segmentLength,
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);
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
@ -1629,7 +1629,7 @@ TCPEndpoint::_DelayedAcknowledgeTimer(struct net_timer *timer, void *data)
if (!locker.IsLocked())
return;
endpoint->_SendQueued(true);
endpoint->SendAcknowledge();
}

View File

@ -101,6 +101,7 @@ class TCPEndpoint : public net_protocol {
size_t segmentLength, bool checkSequence);
void _MarkEstablished();
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 _RetransmitTimer(net_timer *timer, void *data);
@ -153,7 +154,6 @@ class TCPEndpoint : public net_protocol {
bool fTracking;
uint32 fReceivedTSval;
bool fUsingTimestamps;
uint32 fCongestionWindow;
uint32 fSlowStartThreshold;