NS3学习——tcpNewReno算法代码详解(1)-CSDN博客
目录
二、详解
4.TCP NewReno的注册和构造部分
5. TcpNewReno慢启动算法
6. TcpNewReno拥塞避免算法
7.IncreaseWindow函数的实现
8.其他成员函数的实现
8.1 GetName函数
8.2 GetSsThresh函数
8.3 Fork函数
二、详解
4.TCP NewReno的注册和构造部分
// RENONS_OBJECT_ENSURE_REGISTERED (TcpNewReno); //宏定义 确保TcpNewReno类在NS-3的系统中注册TypeId
TcpNewReno::GetTypeId (void)
{static TypeId tid = TypeId ("ns3::TcpNewReno").SetParent<TcpCongestionOps> ().SetGroupName ("Internet").AddConstructor<TcpNewReno> ();return tid;
}
- 方法创建一个
TypeId
对象,名为tid
,其值为"ns3::TcpNewReno";
方法返回TcpNewReno
类的TypeId;
- .AddConstructor<TcpNewReno> ():添加一个构造函数
AddConstructor<TcpNewReno>()
,NS-3系统可以通过这个构造函数创建TcpNewReno
类的实例。
构造函数和析构函数:
TcpNewReno::TcpNewReno (void) : TcpCongestionOps ()
{//这是TcpNewReno类的默认构造函数。它调用基类TcpCongestionOps的默认构造函数,NS_LOG_FUNCTION (this);
} //记录日志,记录构造函数的调用。TcpNewReno::TcpNewReno (const TcpNewReno& sock): TcpCongestionOps (sock)
{NS_LOG_FUNCTION (this);
}TcpNewReno::~TcpNewReno (void)
{//TcpNewReno类的析构函数。
}
//如果类中有动态分配的资源或其他需要清理的资源,它们将在这里被释放。
TcpNewReno::TcpNewReno (const TcpNewReno& sock): TcpCongestionOps (sock):
TcpNewReno类的复制构造函数。它接受一个TcpNewReno
对象作为参数,并调用基类TcpCongestionOps的复制构造函数来复制基类部分的状态。同样,它也记录了日志。
以上代码展示了如何在NS-3中注册一个类,并定义其构造函数和析构函数。
5. TcpNewReno慢启动算法
uint32_t
TcpNewReno::SlowStart (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{NS_LOG_FUNCTION (this << tcb << segmentsAcked);if (segmentsAcked >= 1){tcb->m_cWnd += tcb->m_segmentSize;NS_LOG_INFO ("In SlowStart, updated to cwnd " << tcb->m_cWnd << " ssthresh " << tcb->m_ssThresh);return segmentsAcked - 1;}return 0;
}
- 函数体:如果ack确认数 >=1,表示至少有一个段被确认,那么拥塞窗口的值增加一个段大小(m_segmentSize);
- 参数:
Ptr<TcpSocketState> tcb
,指向TCP套接字状态的智能指针;uint32_t segmentsAcked
,表示收到的ACK确认的段数。 - 同时在日志中更新拥塞窗口和慢开始门限的值;
- 返回
segmentsAcked - 1:
表示已经处理了一个段的确认,剩余的segmentsAcked - 1
个段的确认将不会被用于增加cwnd。 - 返回0:如果
segmentsAcked
小于1,表示没有段被确认,因此不增加cwnd,函数返回0。
6. TcpNewReno拥塞避免算法
void
TcpNewReno::CongestionAvoidance (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{NS_LOG_FUNCTION (this << tcb << segmentsAcked);if (segmentsAcked > 0){double adder = static_cast<double> (tcb->m_segmentSize * tcb->m_segmentSize) / tcb->m_cWnd.Get ();adder = std::max (1.0, adder);tcb->m_cWnd += static_cast<uint32_t> (adder);NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd <<" ssthresh " << tcb->m_ssThresh);}
}
- 函数名:CongestionAvoidance,TcpNewReno类的成员函数;
- 参数:
Ptr<TcpSocketState> tcb
,指向TCP套接字状态的智能指针;uint32_t segmentsAcked
,表示收到的ACK确认的段数。 - 使用NS-3的日志系统记录函数的调用,包括
this
指针、tcb
和segmentsAcked
的值。
拥塞避免逻辑:
if (segmentsAcked > 0){double adder = static_cast<double> (tcb->m_segmentSize * tcb->m_segmentSize) / tcb->m_cWnd.Get ();adder = std::max (1.0, adder);tcb->m_cWnd += static_cast<uint32_t> (adder);NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd <<" ssthresh " << tcb->m_ssThresh);}
- 如果
segmentsAcked
大于0,表示至少有一个段被确认,那么进入拥塞避免阶段的逻辑。 - 计算增加量
adder
,这是基于当前的段大小(m_segmentSize
)和拥塞窗口(m_cWnd
)来计算的。公式为:adder = (m_segmentSize * m_segmentSize) / m_cWnd
。这个公式的目的是逐渐增加cwnd,而不是像慢启动阶段那样快速增加。 - 使用
std::max(1.0, adder)
确保adder
至少为1.0,这意味着即使计算出的增加量小于1,也会至少增加1个MSS。 - 更新拥塞窗口
m_cWnd
,增加计算出的adder
值。 - 记录日志信息,显示更新后的cwnd和ssthresh值。
7.IncreaseWindow
函数的实现
void
TcpNewReno::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{NS_LOG_FUNCTION (this << tcb << segmentsAcked);if (tcb->m_cWnd < tcb->m_ssThresh){segmentsAcked = SlowStart (tcb, segmentsAcked);}if (tcb->m_cWnd >= tcb->m_ssThresh){CongestionAvoidance (tcb, segmentsAcked);}
函数逻辑:
if (tcb->m_cWnd < tcb->m_ssThresh)
{segmentsAcked = SlowStart (tcb, segmentsAcked);
}
如果当前的拥塞窗口m_cWnd
小于慢启动阈值m_ssThresh
,则调用SlowStart
函数来处理窗口增加。在慢启动阶段,每当收到一个ACK,cwnd会增加一个MSS。
if (tcb->m_cWnd >= tcb->m_ssThresh)
{CongestionAvoidance (tcb, segmentsAcked);
}
如果当前的拥塞窗口m_cWnd
大于或等于慢启动阈值m_ssThresh
,则调用CongestionAvoidance
函数来处理窗口增加。在拥塞避免阶段,cwnd的增加速率会减慢,通常是每收到一个ACK增加MSS的1/cwnd。
8.其他成员函数的实现
8.1 GetName函数
std::string
TcpNewReno::GetName () const
{return "TcpNewReno";
}
返回拥塞控制算法的名称,即"TcpNewReno"。这通常用于日志记录、调试或者在模拟器配置中标识使用的具体拥塞控制算法。
8.2 GetSsThresh函数
uint32_t
TcpNewReno::GetSsThresh (Ptr<const TcpSocketState> state,uint32_t bytesInFlight)
{NS_LOG_FUNCTION (this << state << bytesInFlight);return std::max (2 * state->m_segmentSize, bytesInFlight / 2);
}
- 函数:计算并返回慢启动阈值(ssthresh)
- 参数:state,指向TCP连接状态的智能指针;
bytesInFlight
,表示当前在网络中未被确认的数据量。 - 返回值:是
2 * state->m_segmentSize
和bytesInFlight / 2
中的较大值。这意味着ssthresh至少是两个段的大小,但也可以根据当前飞行中的字节量调整。
8.3 Fork函数
Ptr<TcpCongestionOps>
TcpNewReno::Fork ()
{return CopyObject<TcpNewReno> (this);
}} // namespace ns3
- 用于创建
TcpNewReno
对象的副本。在NS-3中,Fork
方法通常被用来复制拥塞控制算法的状态,以便在创建新的TCP连接时使用。 CopyObject<TcpNewReno>(this)
调用了NS-3的复制构造函数来创建当前对象的一个副本,并返回这个副本的智能指针。