From 70803e884d205af7ac435d828531dbdde450fa3d Mon Sep 17 00:00:00 2001 From: Natale Patriciello Date: Fri, 16 Oct 2015 10:38:51 -0700 Subject: [PATCH] Merged Fast Recovery and Fast Retransmit in TcpSocketBase Since RFC 5681 defines Fast Recovery and Fast Retransmit, it has no sense to replicate these algorithms over all TCP variants. The only thing that a variant is allowed to do is using a different slow start threshold: for example, TcpWestwood uses an estimate of the bandwidth to calculate it. So, its calculus has been delegated to a virtual function GetSsThresh which replaces the old DupAck(). Fixed a bug in Tcp Tahoe implementation (slow start threshold diminuished only from an RTO). Fixed a bug on the inflation of the cWnd; it should be inflated of m_dupAckCount segments (and not only 3, which is OK for the default value of m_reTxThresh, but not for the others). --- src/internet/model/tcp-newreno.cc | 89 +++------------------------ src/internet/model/tcp-newreno.h | 9 +-- src/internet/model/tcp-socket-base.cc | 87 ++++++++++++++++++++++++-- src/internet/model/tcp-socket-base.h | 43 +++++++++++-- src/internet/model/tcp-tahoe.cc | 54 +++++----------- src/internet/model/tcp-tahoe.h | 6 +- src/internet/model/tcp-westwood.cc | 71 +++------------------ src/internet/model/tcp-westwood.h | 5 +- 8 files changed, 153 insertions(+), 211 deletions(-) diff --git a/src/internet/model/tcp-newreno.cc b/src/internet/model/tcp-newreno.cc index 42161d7c0..db4316fbd 100644 --- a/src/internet/model/tcp-newreno.cc +++ b/src/internet/model/tcp-newreno.cc @@ -41,31 +41,18 @@ TcpNewReno::GetTypeId (void) .SetParent () .SetGroupName ("Internet") .AddConstructor () - .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit", - UintegerValue (3), - MakeUintegerAccessor (&TcpNewReno::m_retxThresh), - MakeUintegerChecker ()) - .AddAttribute ("LimitedTransmit", "Enable limited transmit", - BooleanValue (false), - MakeBooleanAccessor (&TcpNewReno::m_limitedTx), - MakeBooleanChecker ()) ; return tid; } TcpNewReno::TcpNewReno (void) - : m_retxThresh (3), // mute valgrind, actual value set by the attribute system - m_inFastRec (false), - m_limitedTx (false) // mute valgrind, actual value set by the attribute system + : TcpSocketBase () { NS_LOG_FUNCTION (this); } TcpNewReno::TcpNewReno (const TcpNewReno& sock) - : TcpSocketBase (sock), - m_retxThresh (sock.m_retxThresh), - m_inFastRec (false), - m_limitedTx (sock.m_limitedTx) + : TcpSocketBase (sock) { NS_LOG_FUNCTION (this); NS_LOG_LOGIC ("Invoked the copy constructor"); @@ -90,22 +77,12 @@ TcpNewReno::NewAck (const SequenceNumber32& seq) " cwnd " << m_cWnd << " ssthresh " << m_ssThresh); - // Check for exit condition of fast recovery + // No cWnd management while recovering if (m_inFastRec && seq < m_recover) - { // Partial ACK, partial window deflation (RFC2582 sec.3 bullet #5 paragraph 3) - m_cWnd += m_segmentSize - (seq - m_txBuffer->HeadSequence ()); - NS_LOG_INFO ("Partial ACK for seq " << seq << " in fast recovery: cwnd set to " << m_cWnd); - m_txBuffer->DiscardUpTo(seq); //Bug 1850: retransmit before newack - DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet - TcpSocketBase::NewAck (seq); // update m_nextTxSequence and send new data if allowed by window + { + TcpSocketBase::NewAck (seq); return; } - else if (m_inFastRec && seq >= m_recover) - { // Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1) - m_cWnd = std::min (m_ssThresh.Get (), BytesInFlight () + m_segmentSize); - m_inFastRec = false; - NS_LOG_INFO ("Received full ACK for seq " << seq <<". Leaving fast recovery with cwnd set to " << m_cWnd); - } // Increase of cwnd based on current phase (slow start or congestion avoidance) if (m_cWnd < m_ssThresh) @@ -126,60 +103,10 @@ TcpNewReno::NewAck (const SequenceNumber32& seq) TcpSocketBase::NewAck (seq); } -/* Cut cwnd and enter fast recovery mode upon triple dupack */ -void -TcpNewReno::DupAck (const TcpHeader& t, uint32_t count) +uint32_t +TcpNewReno::GetSsThresh () { - NS_LOG_FUNCTION (this << count); - if (count == m_retxThresh && !m_inFastRec) - { // triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet #1) - m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2); - m_cWnd = m_ssThresh + 3 * m_segmentSize; - m_recover = m_highTxMark; - m_inFastRec = true; - NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd << - ", ssthresh to " << m_ssThresh << " at fast recovery seqnum " << m_recover); - DoRetransmit (); - } - else if (m_inFastRec) - { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3) - m_cWnd += m_segmentSize; - NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd); - if (!m_sendPendingDataEvent.IsRunning ()) - { - SendPendingData (m_connected); - } - } - else if (!m_inFastRec && m_limitedTx && m_txBuffer->SizeFromSequence (m_nextTxSequence) > 0) - { // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit - NS_LOG_INFO ("Limited transmit"); - uint32_t sz = SendDataPacket (m_nextTxSequence, m_segmentSize, true); - m_nextTxSequence += sz; // Advance next tx sequence - }; -} - -/* Retransmit timeout */ -void -TcpNewReno::Retransmit (void) -{ - NS_LOG_FUNCTION (this); - NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ()); - m_inFastRec = false; - - // If erroneous timeout in closed/timed-wait state, just return - if (m_state == CLOSED || m_state == TIME_WAIT) return; - // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; - - // According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight - // size and cwnd is set to 1*MSS, then the lost packet is retransmitted and - // TCP back to slow start - m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2); - m_cWnd = m_segmentSize; - m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack - NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << - ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); - DoRetransmit (); // Retransmit the packet + return std::max (2 * m_segmentSize, BytesInFlight () / 2); } } // namespace ns3 diff --git a/src/internet/model/tcp-newreno.h b/src/internet/model/tcp-newreno.h index b7a8fb68d..4a22a2f60 100644 --- a/src/internet/model/tcp-newreno.h +++ b/src/internet/model/tcp-newreno.h @@ -55,14 +55,7 @@ public: protected: virtual Ptr Fork (void); // Call CopyObject to clone me virtual void NewAck (SequenceNumber32 const& seq); // Inc cwnd and call NewAck() of parent - virtual void DupAck (const TcpHeader& t, uint32_t count); // Halving cwnd and reset nextTxSequence - virtual void Retransmit (void); // Exit fast recovery upon retransmit timeout - -protected: - SequenceNumber32 m_recover; //!< Previous highest Tx seqnum for fast recovery - uint32_t m_retxThresh; //!< Fast Retransmit threshold - bool m_inFastRec; //!< currently in fast recovery - bool m_limitedTx; //!< perform limited transmit + virtual uint32_t GetSsThresh (); }; } // namespace ns3 diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index 76e0bf726..cd4ba94a1 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -118,6 +118,14 @@ TcpSocketBase::GetTypeId (void) PointerValue (), MakePointerAccessor (&TcpSocketBase::GetRxBuffer), MakePointerChecker ()) + .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit", + UintegerValue (3), + MakeUintegerAccessor (&TcpSocketBase::m_retxThresh), + MakeUintegerChecker ()) + .AddAttribute ("LimitedTransmit", "Enable limited transmit", + BooleanValue (true), + MakeBooleanAccessor (&TcpSocketBase::m_limitedTx), + MakeBooleanChecker ()) .AddTraceSource ("RTO", "Retransmission timeout", MakeTraceSourceAccessor (&TcpSocketBase::m_rto), @@ -195,7 +203,10 @@ TcpSocketBase::TcpSocketBase (void) m_rcvScaleFactor (0), m_timestampEnabled (true), m_timestampToEcho (0), - m_ackState (OPEN) + m_ackState (OPEN), + m_retxThresh (3), + m_inFastRec (false), + m_limitedTx (false) { NS_LOG_FUNCTION (this); @@ -243,7 +254,10 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock) m_rcvScaleFactor (sock.m_rcvScaleFactor), m_timestampEnabled (sock.m_timestampEnabled), m_timestampToEcho (sock.m_timestampToEcho), - m_ackState (sock.m_ackState) + m_ackState (sock.m_ackState), + m_retxThresh (sock.m_retxThresh), + m_inFastRec (false), + m_limitedTx (sock.m_limitedTx) { NS_LOG_FUNCTION (this); @@ -1196,7 +1210,38 @@ TcpSocketBase::ReceivedAck (Ptr packet, const TcpHeader& tcpHeader) if (tcpHeader.GetAckNumber () < m_nextTxSequence && packet->GetSize() == 0) { NS_LOG_LOGIC ("Dupack of " << tcpHeader.GetAckNumber ()); - DupAck (tcpHeader, ++m_dupAckCount); + ++m_dupAckCount; + + if (m_dupAckCount == m_retxThresh && !m_inFastRec) + { // triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet #1) + m_recover = m_highTxMark; + m_inFastRec = true; + + m_ssThresh = GetSsThresh (); + m_cWnd = m_ssThresh + m_dupAckCount * m_segmentSize; + + NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." << + "Reset cwnd to " << m_cWnd << ", ssthresh to " << + m_ssThresh << " at fast recovery seqnum " << m_recover); + DoRetransmit (); + + NS_LOG_DEBUG ("DISORDER -> RECOVERY"); + } + else if (m_inFastRec) + { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3) + m_cWnd += m_segmentSize; + NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd); + if (!m_sendPendingDataEvent.IsRunning ()) + { + SendPendingData (m_connected); + } + } + else if (!m_inFastRec && m_limitedTx && m_txBuffer->SizeFromSequence (m_nextTxSequence) > 0) + { // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit + NS_LOG_INFO ("Limited transmit"); + uint32_t sz = SendDataPacket (m_nextTxSequence, m_segmentSize, true); + m_nextTxSequence += sz; // Advance next tx sequence + } } // otherwise, the ACK is precisely equal to the nextTxSequence NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence); @@ -1204,6 +1249,24 @@ TcpSocketBase::ReceivedAck (Ptr packet, const TcpHeader& tcpHeader) else if (tcpHeader.GetAckNumber () > m_txBuffer->HeadSequence ()) { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer NS_LOG_LOGIC ("New ack of " << tcpHeader.GetAckNumber ()); + + // Check for exit condition of fast recovery + if (m_inFastRec && tcpHeader.GetAckNumber () < m_recover) + { // Partial ACK, partial window deflation (RFC2582 sec.3 bullet #5 paragraph 3) + m_cWnd += m_segmentSize - (tcpHeader.GetAckNumber () - m_txBuffer->HeadSequence ()); + NS_LOG_INFO ("Partial ACK for seq " << tcpHeader.GetAckNumber () << " in fast recovery: cwnd set to " << m_cWnd); + m_txBuffer->DiscardUpTo(tcpHeader.GetAckNumber ()); //Bug 1850: retransmit before newack + DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet + TcpSocketBase::NewAck (tcpHeader.GetAckNumber ()); // update m_nextTxSequence and send new data if allowed by window + return; + } + else if (m_inFastRec && tcpHeader.GetAckNumber () >= m_recover) + { // Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1) + m_cWnd = std::min (m_ssThresh.Get (), BytesInFlight () + m_segmentSize); + m_inFastRec = false; + NS_LOG_INFO ("Received full ACK for seq " << tcpHeader.GetAckNumber () <<". Leaving fast recovery with cwnd set to " << m_cWnd); + } + NewAck (tcpHeader.GetAckNumber ()); m_dupAckCount = 0; } @@ -2400,9 +2463,23 @@ TcpSocketBase::PersistTimeout () void TcpSocketBase::Retransmit () { - m_nextTxSequence = m_txBuffer->HeadSequence (); // Start from highest Ack + m_inFastRec = false; + + // If erroneous timeout in closed/timed-wait state, just return + if (m_state == CLOSED || m_state == TIME_WAIT) return; + // If all data are received (non-closing socket and nothing to send), just return + if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; + + // According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight + // size and cwnd is set to 1*MSS, then the lost packet is retransmitted and + // TCP back to slow start + m_ssThresh = GetSsThresh (); + m_cWnd = m_segmentSize; + m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack m_dupAckCount = 0; - DoRetransmit (); // Retransmit the packet + NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << + ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); + DoRetransmit (); // Retransmit the packet } void diff --git a/src/internet/model/tcp-socket-base.h b/src/internet/model/tcp-socket-base.h index 6566aa163..732ad8e3d 100644 --- a/src/internet/model/tcp-socket-base.h +++ b/src/internet/model/tcp-socket-base.h @@ -87,6 +87,34 @@ typedef std::deque RttHistory_t; * provides connection orientation and sliding window flow control. Part of * this class is modified from the original NS-3 TCP socket implementation * (TcpSocketImpl) by Raj Bhattacharjea of Georgia Tech. + * + * + * Fast retransmit + * --------------------------- + * + * The fast retransmit enhancement is introduced in RFC 2581 and updated in + * RFC 5681. It basically reduces the time a sender waits before retransmitting + * a lost segment, through the assumption that if it receives a certain number + * of duplicate ACKs, a segment has been lost and it can be retransmitted. + * Usually it is coupled with the Limited Transmit algorithm, defined in + * RFC 3042. + * + * In ns-3, these algorithms are included in this class, and it is implemented inside + * the ReceivedAck method. The attribute which manages the number of dup ACKs + * necessary to start the fast retransmit algorithm is named "ReTxThreshold", + * and its default value is 3, while the Limited Transmit one can be enabled + * by setting the attribute "LimitedTransmit" to true. + * + * Fast recovery + * -------------------------- + * + * The fast recovery algorithm is introduced RFC 2001, and it basically + * avoids to reset cWnd to 1 segment after sensing a loss on the channel. Instead, + * the slow start threshold is halved, and the cWnd is set equal to such value, + * plus segments for the cWnd inflation. + * + * The algorithm is implemented in the ReceivedAck method. + * */ class TcpSocketBase : public TcpSocket { @@ -612,11 +640,9 @@ protected: virtual void NewAck (SequenceNumber32 const& seq); /** - * \brief Received dupack (duplicate ACK) - * \param tcpHeader the packet's TCP header - * \param count counter of duplicate ACKs - */ - virtual void DupAck (const TcpHeader& tcpHeader, uint32_t count) = 0; + * \brief Get the new value of slow start threshold after a loss event + */ + virtual uint32_t GetSsThresh () = 0; /** * \brief Call Retransmit() upon RTO event @@ -809,7 +835,14 @@ protected: EventId m_sendPendingDataEvent; //!< micro-delay event to send pending data + // Ack state TracedValue m_ackState; //!< State in the ACK state machine + + // Fast Retransmit and Recovery + SequenceNumber32 m_recover; //!< Previous highest Tx seqnum for fast recovery + uint32_t m_retxThresh; //!< Fast Retransmit threshold + bool m_inFastRec; //!< currently in fast recovery + bool m_limitedTx; //!< perform limited transmit }; /** diff --git a/src/internet/model/tcp-tahoe.cc b/src/internet/model/tcp-tahoe.cc index 5eba3d654..a0343a39a 100644 --- a/src/internet/model/tcp-tahoe.cc +++ b/src/internet/model/tcp-tahoe.cc @@ -41,22 +41,17 @@ TcpTahoe::GetTypeId (void) .SetParent () .SetGroupName ("Internet") .AddConstructor () - .AddAttribute ("ReTxThreshold", "Threshold for fast retransmit", - UintegerValue (3), - MakeUintegerAccessor (&TcpTahoe::m_retxThresh), - MakeUintegerChecker ()) ; return tid; } -TcpTahoe::TcpTahoe (void) : m_retxThresh (3) +TcpTahoe::TcpTahoe (void) { NS_LOG_FUNCTION (this); } TcpTahoe::TcpTahoe (const TcpTahoe& sock) - : TcpSocketBase (sock), - m_retxThresh (sock.m_retxThresh) + : TcpSocketBase (sock) { NS_LOG_FUNCTION (this); NS_LOG_LOGIC ("Invoked the copy constructor"); @@ -96,40 +91,21 @@ TcpTahoe::NewAck (SequenceNumber32 const& seq) TcpSocketBase::NewAck (seq); // Complete newAck processing } -/* Cut down ssthresh upon triple dupack */ -void -TcpTahoe::DupAck (const TcpHeader& t, uint32_t count) +uint32_t +TcpTahoe::GetSsThresh () { - NS_LOG_FUNCTION (this << "t " << count); - if (count == m_retxThresh) - { // triple duplicate ack triggers fast retransmit (RFC2001, sec.3) - NS_LOG_INFO ("Triple Dup Ack: old ssthresh " << m_ssThresh << " cwnd " << m_cWnd); - // fast retransmit in Tahoe means triggering RTO earlier. Tx is restarted - // from the highest ack and run slow start again. - // (Fall & Floyd 1996, sec.1) - m_ssThresh = std::max (static_cast (m_cWnd / 2), m_segmentSize * 2); // Half ssthresh - m_cWnd = m_segmentSize; // Run slow start again - m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack - NS_LOG_INFO ("Triple Dup Ack: new ssthresh " << m_ssThresh << " cwnd " << m_cWnd); - NS_LOG_LOGIC ("Triple Dup Ack: retransmit missing segment at " << Simulator::Now ().GetSeconds ()); - DoRetransmit (); + /* Common Tahoe implementations detect congestion only from an RTO. + * Since this function is called in two part (Retransmit and when a DupAck is + * received, depending on the value of m_inFastRec we know if an RTO is expired + * or a triple dupack received */ + if (m_inFastRec) + { + return 0; + } + else + { + return std::max (2 * m_segmentSize, BytesInFlight () / 2); } } -/* Retransmit timeout */ -void TcpTahoe::Retransmit (void) -{ - NS_LOG_FUNCTION (this); - NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ()); - // If erroneous timeout in closed/timed-wait state, just return - if (m_state == CLOSED || m_state == TIME_WAIT) return; - // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; - - m_ssThresh = std::max (static_cast (m_cWnd / 2), m_segmentSize * 2); // Half ssthresh - m_cWnd = m_segmentSize; // Set cwnd to 1 segSize (RFC2001, sec.2) - m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack - DoRetransmit (); // Retransmit the packet -} - } // namespace ns3 diff --git a/src/internet/model/tcp-tahoe.h b/src/internet/model/tcp-tahoe.h index f9ae0367d..9a612975f 100644 --- a/src/internet/model/tcp-tahoe.h +++ b/src/internet/model/tcp-tahoe.h @@ -61,11 +61,7 @@ public: protected: virtual Ptr Fork (void); // Call CopyObject to clone me virtual void NewAck (SequenceNumber32 const& seq); // Inc cwnd and call NewAck() of parent - virtual void DupAck (const TcpHeader& t, uint32_t count); // Treat 3 dupack as timeout - virtual void Retransmit (void); // Retransmit time out - -protected: - uint32_t m_retxThresh; //!< Fast Retransmit threshold + virtual uint32_t GetSsThresh (); }; } // namespace ns3 diff --git a/src/internet/model/tcp-westwood.cc b/src/internet/model/tcp-westwood.cc index 0e9346428..58d7298f6 100644 --- a/src/internet/model/tcp-westwood.cc +++ b/src/internet/model/tcp-westwood.cc @@ -63,13 +63,13 @@ TcpWestwood::GetTypeId (void) MakeEnumAccessor(&TcpWestwood::m_pType), MakeEnumChecker(TcpWestwood::WESTWOOD, "Westwood",TcpWestwood::WESTWOODPLUS, "WestwoodPlus")) .AddTraceSource("EstimatedBW", "The estimated bandwidth", - MakeTraceSourceAccessor(&TcpWestwood::m_currentBW), - "ns3::TracedValueCallback::Double"); + MakeTraceSourceAccessor(&TcpWestwood::m_currentBW), + "ns3::TracedValueCallback::Double") + ; return tid; } TcpWestwood::TcpWestwood (void) : - m_inFastRec(false), m_currentBW(0), m_lastSampleBW(0), m_lastBW(0), @@ -85,7 +85,6 @@ TcpWestwood::TcpWestwood (void) : TcpWestwood::TcpWestwood (const TcpWestwood& sock) : TcpSocketBase(sock), - m_inFastRec(false), m_currentBW(sock.m_currentBW), m_lastSampleBW(sock.m_lastSampleBW), m_lastBW(sock.m_lastBW), @@ -121,14 +120,6 @@ TcpWestwood::NewAck (const SequenceNumber32& seq) " cwnd " << m_cWnd << " ssthresh " << m_ssThresh); - // Check for exit condition of fast recovery - if (m_inFastRec) - {// First new ACK after fast recovery, reset cwnd as in Reno - m_cWnd = m_ssThresh; - m_inFastRec = false; - NS_LOG_INFO ("Reset cwnd to " << m_cWnd); - }; - // Increase of cwnd based on current phase (slow start or congestion avoidance) if (m_cWnd < m_ssThresh) { // Slow start mode, add one segSize to cWnd as in Reno @@ -238,59 +229,11 @@ TcpWestwood::UpdateAckedSegments (int acked) m_ackedSegments += acked; } -void -TcpWestwood::DupAck (const TcpHeader& header, uint32_t count) + +uint32_t +TcpWestwood::GetSsThresh () { - NS_LOG_FUNCTION (this << count << m_cWnd); - - if (count == 3 && !m_inFastRec) - {// Triple duplicate ACK triggers fast retransmit - // Adjust cwnd and ssthresh based on the estimated BW - m_ssThresh = uint32_t(m_currentBW * static_cast (m_minRtt.GetSeconds())); - if (m_cWnd > m_ssThresh) - { - m_cWnd = m_ssThresh; - } - m_inFastRec = true; - NS_LOG_INFO ("Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<", ssthresh to " << m_ssThresh); - DoRetransmit (); - } - else if (m_inFastRec) - {// Increase cwnd for every additional DUPACK as in Reno - m_cWnd += m_segmentSize; - NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd); - if (!m_sendPendingDataEvent.IsRunning ()) - { - SendPendingData (m_connected); - } - } -} - -void -TcpWestwood::Retransmit (void) -{ - NS_LOG_FUNCTION (this); - NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ()); - m_inFastRec = false; - - // If erroneous timeout in closed/timed-wait state, just return - if (m_state == CLOSED || m_state == TIME_WAIT) - return; - // If all data are received, just return - if (m_txBuffer->HeadSequence () >= m_nextTxSequence) - return; - - // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW - m_ssThresh = std::max (static_cast (2 * m_segmentSize), m_currentBW.Get () * static_cast (m_minRtt.GetSeconds ())); - m_cWnd = m_segmentSize; - - // Restart from highest ACK - m_nextTxSequence = m_txBuffer->HeadSequence (); - NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << - ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); - - // Retransmit the packet - DoRetransmit (); + return uint32_t(m_currentBW * static_cast (m_minRtt.GetSeconds())); } void diff --git a/src/internet/model/tcp-westwood.h b/src/internet/model/tcp-westwood.h index b9b78435f..919378187 100644 --- a/src/internet/model/tcp-westwood.h +++ b/src/internet/model/tcp-westwood.h @@ -97,8 +97,7 @@ public: protected: virtual Ptr Fork (void); // Call CopyObject to clone me virtual void NewAck (SequenceNumber32 const& seq); // Inc cwnd and call NewAck() of parent - virtual void DupAck (const TcpHeader& t, uint32_t count); // Treat 3 dupack as timeout - virtual void Retransmit (void); // Retransmit time out + virtual uint32_t GetSsThresh (); /** * Process the newly received ACK @@ -146,8 +145,6 @@ private: void Filtering (void); protected: - bool m_inFastRec; //!< Currently in fast recovery if TRUE - TracedValue m_currentBW; //!< Current value of the estimated BW double m_lastSampleBW; //!< Last bandwidth sample double m_lastBW; //!< Last bandwidth sample after being filtered