ns3学习(二)——tcp-NewReno
关于NewReno的理论部分学习可以参考拥塞控制算法(二)——Tahoe、Reno、NewReno、Vegas
一、ns3源码
在文件tcp-congestion-ops.cc文件中是TCP-NewReno的源码
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/** Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation;** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**/
#include "tcp-congestion-ops.h"
#include "tcp-socket-base.h"
#include "ns3/log.h"namespace ns3 {NS_LOG_COMPONENT_DEFINE ("TcpCongestionOps");NS_OBJECT_ENSURE_REGISTERED (TcpCongestionOps);TypeId
TcpCongestionOps::GetTypeId (void)
{static TypeId tid = TypeId ("ns3::TcpCongestionOps").SetParent<Object> ().SetGroupName ("Internet");return tid;
}TcpCongestionOps::TcpCongestionOps () : Object ()
{}TcpCongestionOps::TcpCongestionOps (const TcpCongestionOps &other) : Object (other)
{}TcpCongestionOps::~TcpCongestionOps ()
{}// RENONS_OBJECT_ENSURE_REGISTERED (TcpNewReno);TypeId
TcpNewReno::GetTypeId (void)
{static TypeId tid = TypeId ("ns3::TcpNewReno").SetParent<TcpCongestionOps> ().SetGroupName ("Internet").AddConstructor<TcpNewReno> ();return tid;
}TcpNewReno::TcpNewReno (void) : TcpCongestionOps ()
{NS_LOG_FUNCTION (this);
}TcpNewReno::TcpNewReno (const TcpNewReno& sock): TcpCongestionOps (sock)
{NS_LOG_FUNCTION (this);
}TcpNewReno::~TcpNewReno (void)
{}/*** \brief Tcp NewReno slow start algorithm** Defined in RFC 5681 as** > During slow start, a TCP increments cwnd by at most SMSS bytes for* > each ACK received that cumulatively acknowledges new data. Slow* > start ends when cwnd exceeds ssthresh (or, optionally, when it* > reaches it, as noted above) or when congestion is observed. While* > traditionally TCP implementations have increased cwnd by precisely* > SMSS bytes upon receipt of an ACK covering new data, we RECOMMEND* > that TCP implementations increase cwnd, per:* >* > cwnd += min (N, SMSS) (2)* >* > where N is the number of previously unacknowledged bytes acknowledged* > in the incoming ACK.** The ns-3 implementation respect the RFC definition. Linux does something* different:* \verbatim
u32 tcp_slow_start(struct tcp_sock *tp, u32 acked){u32 cwnd = tp->snd_cwnd + acked;if (cwnd > tp->snd_ssthresh)cwnd = tp->snd_ssthresh + 1;acked -= cwnd - tp->snd_cwnd;tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp);return acked;}\endverbatim** As stated, we want to avoid the case when a cumulative ACK increases cWnd more* than a segment size, but we keep count of how many segments we have ignored,* and return them.** \param tcb internal congestion state* \param segmentsAcked count of segments acked* \return the number of segments not considered for increasing the cWnd*/
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;
}/*** \brief NewReno congestion avoidance** During congestion avoidance, cwnd is incremented by roughly 1 full-sized* segment per round-trip time (RTT).** \param tcb internal congestion state* \param segmentsAcked count of segments acked*/
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);}
}/*** \brief Try to increase the cWnd following the NewReno specification** \see SlowStart* \see CongestionAvoidance** \param tcb internal congestion state* \param segmentsAcked count of segments acked*/
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);}/* At this point, we could have segmentsAcked != 0. This because RFC says* that in slow start, we should increase cWnd by min (N, SMSS); if in* slow start we receive a cumulative ACK, it counts only for 1 SMSS of* increase, wasting the others.** // Incorrect assert, I am sorry* NS_ASSERT (segmentsAcked == 0);*/
}std::string
TcpNewReno::GetName () const
{return "TcpNewReno";
}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);
}Ptr<TcpCongestionOps>
TcpNewReno::Fork ()
{return CopyObject<TcpNewReno> (this);
}} // namespace ns3
二、学习内容
1、在命名空间中写,方便其他部分进行引用
namespace ns3 {
2、定义日志
NS_LOG_COMPONENT_DEFINE ("TcpCongestionOps");
3、定义一个TypeId类——TcpCongestionOps
关于这部分的c++语言结构看不懂可以参考:C++类构造函数学习
定义一个名为TcpCongestionOps的TypeId类,并定义其GetTyped函数。
在GetTyped函数内部,定义全局属性TypeId为"ns3::TcpCongestionOps"。set其父类为Object,所属分组为Internet(应该是上层文件夹名)。无其他属性Attribute。
NS_OBJECT_ENSURE_REGISTERED (TcpCongestionOps);TypeId
TcpCongestionOps::GetTypeId (void)
{static TypeId tid = TypeId ("ns3::TcpCongestionOps").SetParent<Object> ().SetGroupName ("Internet");return tid;
}
设置TcpCongestionOps类的构造方法TcpCongestionOps(void)。并赋值Object为空。
TcpCongestionOps::TcpCongestionOps () : Object ()
{}
设置TcpCongestionOps类的构造方法TcpCongestionOps(const TcpCongestionOps &other)。并传入名为other的输入的索引(对other值更改则调用函数时传入的变量也更改。参考链接:C++学习——&)。
TcpCongestionOps::TcpCongestionOps (const TcpCongestionOps &other) : Object (other)
{}
设置TcpCongestionOps类的析构函数TcpCongestionOps()。相当于把该对象分解掉,释放内内存
TcpCongestionOps::~TcpCongestionOps ()
{}
4、定义一个TypeId类——TcpNewReno
类似第三部分定义TcpCongestionOps类的同样操作,定义TcpNewReno。
// RENONS_OBJECT_ENSURE_REGISTERED (TcpNewReno);TypeId
TcpNewReno::GetTypeId (void)
{static TypeId tid = TypeId ("ns3::TcpNewReno").SetParent<TcpCongestionOps> ().SetGroupName ("Internet").AddConstructor<TcpNewReno> ();return tid;
}TcpNewReno::TcpNewReno (void) : TcpCongestionOps ()
{NS_LOG_FUNCTION (this);
}TcpNewReno::TcpNewReno (const TcpNewReno& sock): TcpCongestionOps (sock)
{NS_LOG_FUNCTION (this);
}TcpNewReno::~TcpNewReno (void)
{}
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;
}
5.1、Ptr<TcpSocketState> tcb
声明一个TcpSocketState类型的变量的指针,该指针名叫tcb。
Ptr是一个声明指针的模板类,C++中为固定用法。Ptr模板类定义如下:
template <typename T> class Ptr
T为传入值,类型为typename,可见是一个类型名称。Ptr类为template <typename T>class,即T类型的模板类。
5.2、tcb->m_cWnd
tcb是TcpSocketState类型的变量的指针,TcpSocketState类型中有m_cWnd属性。tcb->m_cWnd是指通过tcb来索引该属性。
5.2、SlowStart算法
Log部分不再阐述,this << tcb << segmentsAcked的意思与cout相似。
算法的关键部分是:
if (segmentsAcked >= 1){tcb->m_cWnd += tcb->m_segmentSize;return segmentsAcked - 1;}
当ack大于1时,将拥塞窗口的大小进行调整,增加值为段大小。
由此可见,就是对拥塞窗口增加一个段的大小。可见NewReno在慢启动阶段是线性增长。
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);}
}
static_cast<double>的含义与double类似,但是运行时间比double更快。
忽略Log部分,算法的关键部分是:
adder是拥塞避免阶段加在cwnd上的增量。该增量是max(1.0,段大小的平方除以cwnd)。
7、TcpNewReno增窗
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);}
TcpNewReno使用IncreaseWindow把SlowStart和CongestionAvidance封装起来。
拥塞窗口在ssThresh之下时,为慢启动阶段,窗口大于ssTresh时,为拥塞避免阶段。
8、ssThresh设置
GetName和Fork函数不再赘述,下面来看ssTresh的设置。
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);
}
ssTresh为max (2, 拥塞时的cwnd/2)
ns3学习(二)——tcp-NewReno相关推荐
- tcp抓包返回fin_TCP/IP学习二TCP链接建立与断开
今天详细学习下TCP链接的三次握手四次挥手,因为开发web服务还是会经常遇到一些网络问题的.其实这方面的资料很多,可能我们看过很多次但也忘了无数次[捂脸],这次我主要通过抓包例子来展示这个过程. TC ...
- 嵌入式学习之TCP和UDP基础理解
鸡汤:若有一个柠檬,那就做成柠檬水. 学习梳理目录: 1. 传输层的作用2. 端口的理解3. UDP学习4. TCP学习5. UDP首部学习6. TCP首部学习 传输层的作用 首先应说明的是TCP/I ...
- C#多线程学习(二) 如何操纵一个线程
C#多线程学习(二) 如何操纵一个线程 原文链接:http://kb.cnblogs.com/page/42529/ [1] C#多线程学习(二) 如何操纵一个线程 [2] C#多线程学习(二) 如何 ...
- spring security 学习二
spring security 学习二 doc:https://docs.spring.io/spring-security/site/docs/ 基于表单的认证(个性化认证流程): 一.自定义登录页 ...
- STL源码剖析学习二:空间配置器(allocator)
STL源码剖析学习二:空间配置器(allocator) 标准接口: vlaue_type pointer const_pointer reference const_reference size_ty ...
- mysql用创建的用户登陆并修改表格_MySQL 基础学习二:创建一个用户表,并增删改查...
MySQL 基础学习二:创建一个用户表,并 增删改查 提示:MySQL 命令建议都用大写,因为小写运行时,还是翻译成大写的. 第一步,创建一个用户表 1,打开控制台,进入数据库 C:\Users\Ad ...
- OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...
- OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...
- OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats()
OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats() 1.connectedComponents() ...
最新文章
- python opencv cv2 API
- Leetcode 116. 填充每个节点的下一个右侧节点指针 解题思路及C++实现
- 工厂方法 coding
- OC学习篇之---类的初始化方法和点语法的使用
- LinkedIn会成为下一个诺基亚吗?
- 71. Simplify Path
- curl有时获取不到数据 什么原因导致_缓存击穿导致 golang 组件死锁的问题分享...
- 山东大学计算机专业毕业后,儿子被山东大学数学系录取,毕业之后的前景将会如何...
- java read bytes 阻塞_InputStream中read()与read(byte[] b)java InputStream读取数据问题 | 学步园...
- 阀体端面钻6孔组合机床设计及夹具设计
- Python QGIS 3自动化教程
- 传感器i2c与arduino连接_ARDUINO的I2C通信详解 - arduino读取I2C总线上连接设备的地址...
- 孙子兵法——02 作战第二
- 三问中国电子云,此时入局的深意是什么?
- 信息学奥赛一本通1182 合影效果
- 如何分析线程Dump和堆Dump
- linux看视频插件,Linux系统下安装Adobe Flash Player插件观播放视频
- autoscraper网络刮板模块总结
- LIN总线协议详解3(帧的类型)
- php运行python爬虫_群晖系统中运行python爬虫程序
热门文章
- 如何免费申请阿里云SSL证书
- 写给即将工作和刚刚工作的人们
- 【OOP】DOTA世界中的对象建模
- linux epel7安装,在CentOS6.x或CentOS7.x上安装EPEL Repo,Extra Packages for Enterprise Linux (EPEL)...
- Linux网络相关命令
- HTML标签汇总(基础表单部分)
- 华为OD机试题,用 Java 解【5 键键盘的输出 | 五键键盘】问题 | 含解题思路
- 快速删除txt文本数据中的某一列
- 基于Camera2和MediaRecorder实现视频录制
- C++移动拷贝构造函数