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