tcp: (fixes #1013) Sync TcpBbr::m_appLimited with TcpRateOps::TcpRateConnection::m_appLimited
This commit is contained in:
@@ -1125,6 +1125,36 @@ please refer to:
|
|||||||
|
|
||||||
* Vivek Jain, Viyom Mittal and Mohit P. Tahiliani. "Design and Implementation of TCP BBR in ns-3." In Proceedings of the 10th Workshop on ns-3, pp. 16-22. 2018. (https://dl.acm.org/doi/abs/10.1145/3199902.3199911)
|
* Vivek Jain, Viyom Mittal and Mohit P. Tahiliani. "Design and Implementation of TCP BBR in ns-3." In Proceedings of the 10th Workshop on ns-3, pp. 16-22. 2018. (https://dl.acm.org/doi/abs/10.1145/3199902.3199911)
|
||||||
|
|
||||||
|
Integration with TcpRateOps
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
In the older version of the TCP BBR algorithm, the ``appLimited`` variable was handled directly inside the ``TcpBbr`` class. To make the code more modular and similar to how things are done in Linux TCP, a pointer to the ``TcpRateOps`` class called ``Ptr<TcpRateOps> m_rateOps`` was introduced. This change helps manage the ``appLimited`` state through the rate operations interface instead of directly in ``TcpBbr``.
|
||||||
|
|
||||||
|
Now, the ``appLimited`` value can be accessed with:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m_rateOps->GetConnectionRate().m_appLimited;
|
||||||
|
|
||||||
|
And it can be updated using:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m_rateOps->SetAppLimited(tcb->m_bytesInFlight.Get());
|
||||||
|
|
||||||
|
The ``SetAppLimited`` function, which is part of the ``TcpRateLinux`` class, takes care of updating the ``appLimited`` value based on the current amount of data in flight.
|
||||||
|
|
||||||
|
Here's an example of the ``SetRateOps`` method in ``TcpBbr``:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void TcpBbr::SetRateOps(Ptr<TcpRateOps> rateOps)
|
||||||
|
{
|
||||||
|
m_rateOps = rateOps;
|
||||||
|
}
|
||||||
|
|
||||||
|
This setup makes the code more organized and reflects how Linux TCP handles the ``appLimited`` state, where it's managed within the TCP socket and updated by rate operations.
|
||||||
|
|
||||||
Support for Explicit Congestion Notification (ECN)
|
Support for Explicit Congestion Notification (ECN)
|
||||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ TcpBbr::TcpBbr(const TcpBbr& sock)
|
|||||||
m_isInitialized(sock.m_isInitialized),
|
m_isInitialized(sock.m_isInitialized),
|
||||||
m_uv(sock.m_uv),
|
m_uv(sock.m_uv),
|
||||||
m_delivered(sock.m_delivered),
|
m_delivered(sock.m_delivered),
|
||||||
m_appLimited(sock.m_appLimited),
|
|
||||||
m_extraAckedGain(sock.m_extraAckedGain),
|
m_extraAckedGain(sock.m_extraAckedGain),
|
||||||
m_extraAckedWinRtt(sock.m_extraAckedWinRtt),
|
m_extraAckedWinRtt(sock.m_extraAckedWinRtt),
|
||||||
m_extraAckedWinRttLength(sock.m_extraAckedWinRttLength),
|
m_extraAckedWinRttLength(sock.m_extraAckedWinRttLength),
|
||||||
@@ -132,6 +131,12 @@ TcpBbr::TcpBbr(const TcpBbr& sock)
|
|||||||
NS_LOG_FUNCTION(this);
|
NS_LOG_FUNCTION(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TcpBbr::SetRateOps(Ptr<TcpRateOps> rateOps)
|
||||||
|
{
|
||||||
|
m_rateOps = rateOps;
|
||||||
|
}
|
||||||
|
|
||||||
const char* const TcpBbr::BbrModeName[BBR_PROBE_RTT + 1] = {
|
const char* const TcpBbr::BbrModeName[BBR_PROBE_RTT + 1] = {
|
||||||
"BBR_STARTUP",
|
"BBR_STARTUP",
|
||||||
"BBR_DRAIN",
|
"BBR_DRAIN",
|
||||||
@@ -415,8 +420,7 @@ TcpBbr::HandleProbeRTT(Ptr<TcpSocketState> tcb)
|
|||||||
{
|
{
|
||||||
NS_LOG_FUNCTION(this << tcb);
|
NS_LOG_FUNCTION(this << tcb);
|
||||||
|
|
||||||
uint32_t totalBytes = m_delivered + tcb->m_bytesInFlight.Get();
|
m_rateOps->SetAppLimited(tcb->m_bytesInFlight.Get());
|
||||||
m_appLimited = (totalBytes > 0 ? totalBytes : 1);
|
|
||||||
|
|
||||||
if (m_probeRttDoneStamp.IsZero() && tcb->m_bytesInFlight <= m_minPipeCwnd)
|
if (m_probeRttDoneStamp.IsZero() && tcb->m_bytesInFlight <= m_minPipeCwnd)
|
||||||
{
|
{
|
||||||
@@ -763,7 +767,8 @@ TcpBbr::CwndEvent(Ptr<TcpSocketState> tcb, const TcpSocketState::TcpCAEvent_t ev
|
|||||||
m_packetConservation = false;
|
m_packetConservation = false;
|
||||||
RestoreCwnd(tcb);
|
RestoreCwnd(tcb);
|
||||||
}
|
}
|
||||||
else if (event == TcpSocketState::CA_EVENT_TX_START && m_appLimited)
|
else if (event == TcpSocketState::CA_EVENT_TX_START &&
|
||||||
|
m_rateOps->GetConnectionRate().m_appLimited)
|
||||||
{
|
{
|
||||||
NS_LOG_DEBUG("CwndEvent triggered to CA_EVENT_TX_START :: " << event);
|
NS_LOG_DEBUG("CwndEvent triggered to CA_EVENT_TX_START :: " << event);
|
||||||
m_idleRestart = true;
|
m_idleRestart = true;
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ class TcpBbr : public TcpCongestionOps
|
|||||||
const TcpSocketState::TcpCongState_t newState) override;
|
const TcpSocketState::TcpCongState_t newState) override;
|
||||||
void CwndEvent(Ptr<TcpSocketState> tcb, const TcpSocketState::TcpCAEvent_t event) override;
|
void CwndEvent(Ptr<TcpSocketState> tcb, const TcpSocketState::TcpCAEvent_t event) override;
|
||||||
uint32_t GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight) override;
|
uint32_t GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight) override;
|
||||||
|
void SetRateOps(Ptr<TcpRateOps> rateOps) override;
|
||||||
Ptr<TcpCongestionOps> Fork() override;
|
Ptr<TcpCongestionOps> Fork() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -375,9 +376,8 @@ class TcpBbr : public TcpCongestionOps
|
|||||||
Time m_minRttStamp; //!< The wall clock time at which the current BBR.RTProp sample was obtained
|
Time m_minRttStamp; //!< The wall clock time at which the current BBR.RTProp sample was obtained
|
||||||
bool m_isInitialized{false}; //!< Set to true after first time initialization variables
|
bool m_isInitialized{false}; //!< Set to true after first time initialization variables
|
||||||
Ptr<UniformRandomVariable> m_uv{nullptr}; //!< Uniform Random Variable
|
Ptr<UniformRandomVariable> m_uv{nullptr}; //!< Uniform Random Variable
|
||||||
uint64_t m_delivered{0}; //!< The total amount of data in bytes delivered so far
|
uint64_t m_delivered{0}; //!< The total amount of data in bytes delivered so far
|
||||||
uint32_t m_appLimited{
|
Ptr<TcpRateOps> m_rateOps; //!< Rate operations
|
||||||
0}; //!< The index of the last transmitted packet marked as application-limited
|
|
||||||
uint32_t m_extraAckedGain{1}; //!< Gain factor for adding extra ack to cwnd
|
uint32_t m_extraAckedGain{1}; //!< Gain factor for adding extra ack to cwnd
|
||||||
uint32_t m_extraAcked[2]{0, 0}; //!< Maximum excess data acked in epoch
|
uint32_t m_extraAcked[2]{0, 0}; //!< Maximum excess data acked in epoch
|
||||||
uint32_t m_extraAckedWinRtt{0}; //!< Age of extra acked in rtt
|
uint32_t m_extraAckedWinRtt{0}; //!< Age of extra acked in rtt
|
||||||
|
|||||||
@@ -72,6 +72,15 @@ class TcpCongestionOps : public Object
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set rate operation required by the congestion control algorithm
|
||||||
|
*
|
||||||
|
* @param rateOps a pointer to the rate operation object used to manage rate control
|
||||||
|
*/
|
||||||
|
virtual void SetRateOps(Ptr<TcpRateOps> rateOps [[maybe_unused]])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the slow start threshold after a loss event
|
* @brief Get the slow start threshold after a loss event
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -144,8 +144,7 @@ TcpRateLinux::CalculateAppLimited(uint32_t cWnd,
|
|||||||
&& in_flight < cWnd // We are not limited by CWND.
|
&& in_flight < cWnd // We are not limited by CWND.
|
||||||
&& lostOut <= retransOut) // All lost packets have been retransmitted.
|
&& lostOut <= retransOut) // All lost packets have been retransmitted.
|
||||||
{
|
{
|
||||||
m_rate.m_appLimited = std::max<uint32_t>(m_rate.m_delivered + in_flight, 1);
|
SetAppLimited(in_flight);
|
||||||
m_rateTrace(m_rate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_appLimited will be reset once in GenerateSample, if it has to be.
|
// m_appLimited will be reset once in GenerateSample, if it has to be.
|
||||||
@@ -155,6 +154,13 @@ TcpRateLinux::CalculateAppLimited(uint32_t cWnd,
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TcpRateLinux::SetAppLimited(uint32_t in_flight)
|
||||||
|
{
|
||||||
|
m_rate.m_appLimited = std::max<uint32_t>(m_rate.m_delivered + in_flight, 1);
|
||||||
|
m_rateTrace(m_rate);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TcpRateLinux::SkbDelivered(TcpTxItem* skb)
|
TcpRateLinux::SkbDelivered(TcpTxItem* skb)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ class TcpRateOps : public Object
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
virtual const TcpRateConnection& GetConnectionRate() = 0;
|
virtual const TcpRateConnection& GetConnectionRate() = 0;
|
||||||
|
/**
|
||||||
|
* @brief Updates the app-limited state based on in-flight data.
|
||||||
|
* @param in_flight In Flight size (in bytes)
|
||||||
|
*/
|
||||||
|
virtual void SetAppLimited(uint32_t in_flight) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Rate Sample structure
|
* @brief Rate Sample structure
|
||||||
@@ -212,6 +217,12 @@ class TcpRateLinux : public TcpRateOps
|
|||||||
return m_rate;
|
return m_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates the app-limited state based on in-flight data.
|
||||||
|
* @param in_flight In Flight size (in bytes)
|
||||||
|
*/
|
||||||
|
void SetAppLimited(uint32_t in_flight) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TracedCallback signature for tcp rate update events.
|
* TracedCallback signature for tcp rate update events.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -429,10 +429,13 @@ TcpSocketBase::TcpSocketBase(const TcpSocketBase& sock)
|
|||||||
m_tcb->m_pacingRate = m_tcb->m_maxPacingRate;
|
m_tcb->m_pacingRate = m_tcb->m_maxPacingRate;
|
||||||
m_pacingTimer.SetFunction(&TcpSocketBase::NotifyPacingPerformed, this);
|
m_pacingTimer.SetFunction(&TcpSocketBase::NotifyPacingPerformed, this);
|
||||||
|
|
||||||
|
m_rateOps = CreateObject<TcpRateLinux>();
|
||||||
|
|
||||||
if (sock.m_congestionControl)
|
if (sock.m_congestionControl)
|
||||||
{
|
{
|
||||||
m_congestionControl = sock.m_congestionControl->Fork();
|
m_congestionControl = sock.m_congestionControl->Fork();
|
||||||
m_congestionControl->Init(m_tcb);
|
m_congestionControl->Init(m_tcb);
|
||||||
|
m_congestionControl->SetRateOps(m_rateOps);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock.m_recoveryOps)
|
if (sock.m_recoveryOps)
|
||||||
@@ -440,7 +443,6 @@ TcpSocketBase::TcpSocketBase(const TcpSocketBase& sock)
|
|||||||
m_recoveryOps = sock.m_recoveryOps->Fork();
|
m_recoveryOps = sock.m_recoveryOps->Fork();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rateOps = CreateObject<TcpRateLinux>();
|
|
||||||
if (m_tcb->m_sendEmptyPacketCallback.IsNull())
|
if (m_tcb->m_sendEmptyPacketCallback.IsNull())
|
||||||
{
|
{
|
||||||
m_tcb->m_sendEmptyPacketCallback = MakeCallback(&TcpSocketBase::SendEmptyPacket, this);
|
m_tcb->m_sendEmptyPacketCallback = MakeCallback(&TcpSocketBase::SendEmptyPacket, this);
|
||||||
@@ -4657,6 +4659,7 @@ TcpSocketBase::SetCongestionControlAlgorithm(Ptr<TcpCongestionOps> algo)
|
|||||||
NS_LOG_FUNCTION(this << algo);
|
NS_LOG_FUNCTION(this << algo);
|
||||||
m_congestionControl = algo;
|
m_congestionControl = algo;
|
||||||
m_congestionControl->Init(m_tcb);
|
m_congestionControl->Init(m_tcb);
|
||||||
|
m_congestionControl->SetRateOps(m_rateOps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user