--- 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)
{