diff -r b50198ab897d -r 917793d13817 src/internet/model/tcp-socket-base.cc --- a/src/internet/model/tcp-socket-base.cc Mon May 04 22:31:24 2015 -0700 +++ b/src/internet/model/tcp-socket-base.cc Mon May 04 22:39:00 2015 -0700 @@ -142,6 +142,14 @@ "Remote side's flow control window", MakeTraceSourceAccessor (&TcpSocketBase::m_rWnd), "ns3::TracedValue::Uint32Callback") + .AddTraceSource ("HighestRxSequence", + "Highest sequence number received from peer", + MakeTraceSourceAccessor (&TcpSocketBase::m_highRxMark), + "ns3::SequenceNumber32TracedValueCallback") + .AddTraceSource ("HighestRxAck", + "Highest ack received from peer", + MakeTraceSourceAccessor (&TcpSocketBase::m_highRxAckMark), + "ns3::SequenceNumber32TracedValueCallback") ; return tid; } @@ -169,6 +177,8 @@ m_segmentSize (0), // For attribute initialization consistency (quiet valgrind) m_rWnd (0), + m_highRxMark (0), + m_highRxAckMark (0), m_sndScaleFactor (0), m_rcvScaleFactor (0), m_timestampEnabled (true), @@ -209,6 +219,8 @@ m_segmentSize (sock.m_segmentSize), m_maxWinSize (sock.m_maxWinSize), m_rWnd (sock.m_rWnd), + m_highRxMark (sock.m_highRxMark), + m_highRxAckMark (sock.m_highRxAckMark), m_winScalingEnabled (sock.m_winScalingEnabled), m_sndScaleFactor (sock.m_sndScaleFactor), m_rcvScaleFactor (sock.m_rcvScaleFactor), @@ -945,14 +957,6 @@ EstimateRtt (tcpHeader); } - // Update Rx window size, i.e. the flow control window - if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0) - { // persist probes end - NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); - m_persistEvent.Cancel (); - } - m_rWnd = (uint32_t(tcpHeader.GetWindowSize ()) << m_rcvScaleFactor); - // Discard fully out of range data packets if (packet->GetSize () && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ())) @@ -970,6 +974,17 @@ return; } + // Update Rx window size, i.e. the flow control window + if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0 && m_persistEvent.IsRunning ()) + { // persist probes end + NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); + m_persistEvent.Cancel (); + } + if (tcpHeader.GetFlags () & TcpHeader::ACK) + { + UpdateWindowSize (tcpHeader); + } + // TCP state machine code in different process functions // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel switch (m_state) @@ -1048,14 +1063,6 @@ EstimateRtt (tcpHeader); } - // Update Rx window size, i.e. the flow control window - if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0) - { // persist probes end - NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); - m_persistEvent.Cancel (); - } - m_rWnd = (uint32_t(tcpHeader.GetWindowSize ()) << m_rcvScaleFactor); - // Discard fully out of range packets if (packet->GetSize () && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ())) @@ -1073,6 +1080,18 @@ return; } + // Update Rx window size, i.e. the flow control window + if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0 && m_persistEvent.IsRunning ()) + { // persist probes end + NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); + m_persistEvent.Cancel (); + } + + if (tcpHeader.GetFlags () & TcpHeader::ACK) + { + UpdateWindowSize (tcpHeader); + } + // TCP state machine code in different process functions // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel switch (m_state) @@ -2726,6 +2745,50 @@ option->GetTimestamp () << " echo=" << m_timestampToEcho); } +void TcpSocketBase::UpdateWindowSize (const TcpHeader &header) +{ + NS_LOG_FUNCTION (this << header); + // If the connection is not established, the window size is always + // updated + uint32_t receivedWindow = header.GetWindowSize (); + receivedWindow <<= m_rcvScaleFactor; + NS_LOG_DEBUG ("Received (scaled) window is " << receivedWindow << " bytes"); + if (m_state < ESTABLISHED) + { + m_rWnd = receivedWindow; + NS_LOG_DEBUG ("State less than ESTABLISHED; updating rWnd to " << m_rWnd); + return; + } + + // Test for conditions that allow updating of the window + // 1) segment contains new data (advancing the right edge of the receive + // buffer), + // 2) segment does not contain new data but the segment acks new data + // (highest sequence number acked advances), or + // 3) the advertised window is larger than the current send window + bool update = false; + if (header.GetAckNumber () == m_highRxAckMark && receivedWindow > m_rWnd) + { + // right edge of the send window is increased (window update) + update = true; + } + if (header.GetAckNumber () > m_highRxAckMark) + { + m_highRxAckMark = header.GetAckNumber (); + update = true; + } + if (header.GetSequenceNumber () > m_highRxMark) + { + m_highRxMark = header.GetSequenceNumber (); + update = true; + } + if (update == true) + { + m_rWnd = receivedWindow; + NS_LOG_DEBUG ("updating rWnd to " << m_rWnd); + } +} + void TcpSocketBase::SetMinRto (Time minRto) {