diff --git a/src/internet/model/tcp-congestion-ops.cc b/src/internet/model/tcp-congestion-ops.cc index c82cf0609..bed4d5f04 100644 --- a/src/internet/model/tcp-congestion-ops.cc +++ b/src/internet/model/tcp-congestion-ops.cc @@ -48,6 +48,48 @@ TcpCongestionOps::~TcpCongestionOps () { } +void +TcpCongestionOps::IncreaseWindow (Ptr tcb, uint32_t segmentsAcked) +{ + NS_LOG_FUNCTION (this << tcb << segmentsAcked); +} + +void +TcpCongestionOps::PktsAcked (Ptr tcb, uint32_t segmentsAcked, + const Time& rtt) +{ + NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt); +} + +void +TcpCongestionOps::CongestionStateSet (Ptr tcb, + const TcpSocketState::TcpCongState_t newState) +{ + NS_LOG_FUNCTION (this << tcb << newState); +} + +void +TcpCongestionOps::CwndEvent (Ptr tcb, + const TcpSocketState::TcpCAEvent_t event) +{ + NS_LOG_FUNCTION (this << tcb << event); +} + +bool +TcpCongestionOps::HasCongControl () const +{ + return false; +} + +void +TcpCongestionOps::CongControl (Ptr tcb, + const TcpRateOps::TcpRateConnection &rc, + const TcpRateOps::TcpRateSample &rs) +{ + NS_LOG_FUNCTION (this << tcb); + NS_UNUSED (rc); + NS_UNUSED (rs); +} // RENO diff --git a/src/internet/model/tcp-congestion-ops.h b/src/internet/model/tcp-congestion-ops.h index 1341604b9..7d5c0a3ff 100644 --- a/src/internet/model/tcp-congestion-ops.h +++ b/src/internet/model/tcp-congestion-ops.h @@ -20,6 +20,7 @@ #define TCPCONGESTIONOPS_H #include "ns3/tcp-socket-state.h" +#include "ns3/tcp-rate-ops.h" namespace ns3 { @@ -101,7 +102,7 @@ public: * \param tcb internal congestion state * \param segmentsAcked count of segments acked */ - virtual void IncreaseWindow (Ptr tcb, uint32_t segmentsAcked) = 0; + virtual void IncreaseWindow (Ptr tcb, uint32_t segmentsAcked); /** * \brief Timing information on received ACK @@ -116,12 +117,7 @@ public: * \param rtt last rtt */ virtual void PktsAcked (Ptr tcb, uint32_t segmentsAcked, - const Time& rtt) - { - NS_UNUSED (tcb); - NS_UNUSED (segmentsAcked); - NS_UNUSED (rtt); - } + const Time& rtt); /** * \brief Trigger events/calculations specific to a congestion state @@ -140,11 +136,7 @@ public: * \param newState new congestion state to which the TCP is going to switch */ virtual void CongestionStateSet (Ptr tcb, - const TcpSocketState::TcpCongState_t newState) - { - NS_UNUSED (tcb); - NS_UNUSED (newState); - } + const TcpSocketState::TcpCongState_t newState); /** * \brief Trigger events/calculations on occurrence of congestion window event @@ -156,11 +148,36 @@ public: * \param event the event which triggered this function */ virtual void CwndEvent (Ptr tcb, - const TcpSocketState::TcpCAEvent_t event) - { - NS_UNUSED (tcb); - NS_UNUSED (event); - } + const TcpSocketState::TcpCAEvent_t event); + + /** + * \brief Returns true when Congestion Control Algorithm implements CongControl + * + * \return true if CC implements CongControl function + * + * This function is the equivalent in C++ of the C checks that are used + * in the Linux kernel to see if an optional function has been defined. + * Since CongControl is optional, not all congestion controls have it. But, + * from the perspective of TcpSocketBase, the behavior is different if + * CongControl is present. Therefore, this check should return true for any + * congestion controls that implements the CongControl optional function. + */ + virtual bool HasCongControl () const; + + /** + * \brief Called when packets are delivered to update cwnd and pacing rate + * + * This function mimics the function cong_control in Linux. It is allowed to + * change directly cWnd and pacing rate. + * + * \param tcb internal congestion state + * \param rc Rate information for the connection + * \param rs Rate sample (over a period of time) information + */ + virtual void CongControl (Ptr tcb, + const TcpRateOps::TcpRateConnection &rc, + const TcpRateOps::TcpRateSample &rs); + // Present in Linux but not in ns-3 yet: /* call when ack arrives (optional) */ // void (*in_ack_event)(struct sock *sk, u32 flags); diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index 4d76e3aa2..46bf151a9 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -1576,12 +1576,16 @@ TcpSocketBase::EnterRecovery (uint32_t currentDelivered) // compatibility with old ns-3 versions uint32_t bytesInFlight = m_sackEnabled ? BytesInFlight () : BytesInFlight () + m_tcb->m_segmentSize; m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, bytesInFlight); - m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered); - NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." << - "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << - m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover << - " calculated in flight: " << bytesInFlight); + if (!m_congestionControl->HasCongControl ()) + { + m_recoveryOps->EnterRecovery (m_tcb, m_dupAckCount, UnAckDataCount (), currentDelivered); + NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." << + "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << + m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover << + " calculated in flight: " << bytesInFlight); + } + // (4.3) Retransmit the first data segment presumed dropped DoRetransmit (); @@ -1634,9 +1638,12 @@ TcpSocketBase::DupAck (uint32_t currentDelivered) // has left the network. This is equivalent to a SACK of one block. m_txBuffer->AddRenoSack (); } - m_recoveryOps->DoRecovery (m_tcb, currentDelivered); - NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode." - "Increase cwnd to " << m_tcb->m_cWnd); + if (!m_congestionControl->HasCongControl ()) + { + m_recoveryOps->DoRecovery (m_tcb, currentDelivered); + NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode." + "Increase cwnd to " << m_tcb->m_cWnd); + } } else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER) { @@ -1718,6 +1725,20 @@ TcpSocketBase::ReceivedAck (Ptr packet, const TcpHeader& tcpHeader) // are inside the function ProcessAck ProcessAck (ackNumber, (bytesSacked > 0), currentDelivered, oldHeadSequence); + if (m_congestionControl->HasCongControl ()) + { + uint32_t previousLost = m_txBuffer->GetLost (); + uint32_t priorInFlight = m_tcb->m_bytesInFlight.Get (); + uint32_t currentLost = m_txBuffer->GetLost (); + uint32_t lost = (currentLost > previousLost) ? + currentLost - previousLost : + previousLost - currentLost; + auto rateSample = m_rateOps->GenerateSample (currentDelivered, lost, + false, priorInFlight, m_tcb->m_minRtt); + auto rateConn = m_rateOps->GetConnectionRate (); + m_congestionControl->CongControl(m_tcb, rateConn, rateSample); + } + // If there is any data piggybacked, store it into m_rxBuffer if (packet->GetSize () > 0) { @@ -1856,7 +1877,7 @@ TcpSocketBase::ProcessAck(const SequenceNumber32 &ackNumber, bool scoreboardUpda } DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet m_tcb->m_cWndInfl = SafeSubtraction (m_tcb->m_cWndInfl, bytesAcked); - if (segsAcked >= 1) + if (!m_congestionControl->HasCongControl () && segsAcked >= 1) { m_recoveryOps->DoRecovery (m_tcb, currentDelivered); }