tcp: (fixes #1001) Add TCP-friendliness heuristic to TCP Cubic

This commit is contained in:
Tom Henderson
2024-01-08 07:37:08 -08:00
parent 2c86bc6ee9
commit a72b26a3fa
3 changed files with 42 additions and 3 deletions

View File

@@ -663,6 +663,9 @@ main(int argc, char* argv[])
Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(10));
Config::SetDefault("ns3::TcpL4Protocol::RecoveryType",
TypeIdValue(TcpPrrRecovery::GetTypeId()));
// Validation criteria were written for TCP Cubic without Reno-friendly behavior, so disable it
// for these tests
Config::SetDefault("ns3::TcpCubic::TcpFriendliness", BooleanValue(false));
////////////////////////////////////////////////////////////
// command-line argument parsing //

View File

@@ -45,6 +45,11 @@ TcpCubic::GetTypeId()
BooleanValue(true),
MakeBooleanAccessor(&TcpCubic::m_fastConvergence),
MakeBooleanChecker())
.AddAttribute("TcpFriendliness",
"Enable (true) or disable (false) TCP friendliness",
BooleanValue(true),
MakeBooleanAccessor(&TcpCubic::m_tcpFriendliness),
MakeBooleanChecker())
.AddAttribute("Beta",
"Beta for multiplicative decrease",
DoubleValue(0.7),
@@ -209,7 +214,7 @@ TcpCubic::IncreaseWindow(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
if (tcb->m_cWnd >= tcb->m_ssThresh && segmentsAcked > 0)
{
m_cWndCnt += segmentsAcked;
uint32_t cnt = Update(tcb);
uint32_t cnt = Update(tcb, segmentsAcked);
/* According to RFC 6356 even once the new cwnd is
* calculated you must compare this to the number of ACKs received since
@@ -232,19 +237,24 @@ TcpCubic::IncreaseWindow(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
}
uint32_t
TcpCubic::Update(Ptr<TcpSocketState> tcb)
TcpCubic::Update(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{
NS_LOG_FUNCTION(this);
Time t;
uint32_t delta;
uint32_t bicTarget;
uint32_t cnt = 0;
uint32_t maxCnt;
double offs;
uint32_t segCwnd = tcb->GetCwndInSegments();
m_ackCnt += segmentsAcked;
if (m_epochStart == Time::Min())
{
m_epochStart = Simulator::Now(); // record the beginning of an epoch
m_ackCnt = segmentsAcked;
m_tcpCwnd = segCwnd;
if (m_lastMaxCwnd <= segCwnd)
{
@@ -311,6 +321,26 @@ TcpCubic::Update(Ptr<TcpSocketState> tcb)
cnt = m_cntClamp;
}
if (m_tcpFriendliness)
{
auto scale = static_cast<uint32_t>(8 * (1024 + m_beta * 1024) / 3 / (1024 - m_beta * 1024));
delta = (segCwnd * scale) >> 3;
while (m_ackCnt > delta)
{
m_ackCnt -= delta;
m_tcpCwnd++;
}
if (m_tcpCwnd > segCwnd)
{
delta = m_tcpCwnd - segCwnd;
maxCnt = segCwnd / delta;
if (cnt > maxCnt)
{
cnt = maxCnt;
}
}
}
// The maximum rate of cwnd increase CUBIC allows is 1 packet per
// 2 packets ACKed, meaning cwnd grows at 1.5x per RTT.
return std::max(cnt, 2U);
@@ -463,6 +493,8 @@ TcpCubic::CubicReset(Ptr<const TcpSocketState> tcb)
m_lastMaxCwnd = 0;
m_bicOriginPoint = 0;
m_bicK = 0;
m_ackCnt = 0;
m_tcpCwnd = 0;
m_delayMin = Time::Min();
m_found = false;
}

View File

@@ -104,6 +104,7 @@ class TcpCubic : public TcpCongestionOps
private:
bool m_fastConvergence; //!< Enable or disable fast convergence algorithm
bool m_tcpFriendliness; //!< Enable or disable TCP-friendliness heuristic
double m_beta; //!< Beta for cubic multiplicative increase
bool m_hystart; //!< Enable or disable HyStart algorithm
@@ -134,6 +135,8 @@ class TcpCubic : public TcpCongestionOps
Time m_cubicDelta; //!< Time to wait after recovery before update
Time m_currRtt; //!< Current Rtt
uint32_t m_sampleCnt; //!< Count of samples for HyStart
uint32_t m_ackCnt; //!< Count the number of ACKed packets
uint32_t m_tcpCwnd; //!< Estimated tcp cwnd (for Reno-friendliness)
private:
/**
@@ -151,9 +154,10 @@ class TcpCubic : public TcpCongestionOps
/**
* \brief Cubic window update after a new ack received
* \param tcb Transmission Control Block of the connection
* \param segmentsAcked Segments acked
* \returns the congestion window update counter
*/
uint32_t Update(Ptr<TcpSocketState> tcb);
uint32_t Update(Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
/**
* \brief Update HyStart parameters