关于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相关推荐

  1. tcp抓包返回fin_TCP/IP学习二TCP链接建立与断开

    今天详细学习下TCP链接的三次握手四次挥手,因为开发web服务还是会经常遇到一些网络问题的.其实这方面的资料很多,可能我们看过很多次但也忘了无数次[捂脸],这次我主要通过抓包例子来展示这个过程. TC ...

  2. 嵌入式学习之TCP和UDP基础理解

    鸡汤:若有一个柠檬,那就做成柠檬水. 学习梳理目录: 1. 传输层的作用2. 端口的理解3. UDP学习4. TCP学习5. UDP首部学习6. TCP首部学习 传输层的作用 首先应说明的是TCP/I ...

  3. C#多线程学习(二) 如何操纵一个线程

    C#多线程学习(二) 如何操纵一个线程 原文链接:http://kb.cnblogs.com/page/42529/ [1] C#多线程学习(二) 如何操纵一个线程 [2] C#多线程学习(二) 如何 ...

  4. spring security 学习二

    spring security 学习二 doc:https://docs.spring.io/spring-security/site/docs/ 基于表单的认证(个性化认证流程): 一.自定义登录页 ...

  5. STL源码剖析学习二:空间配置器(allocator)

    STL源码剖析学习二:空间配置器(allocator) 标准接口: vlaue_type pointer const_pointer reference const_reference size_ty ...

  6. mysql用创建的用户登陆并修改表格_MySQL 基础学习二:创建一个用户表,并增删改查...

    MySQL 基础学习二:创建一个用户表,并 增删改查 提示:MySQL 命令建议都用大写,因为小写运行时,还是翻译成大写的. 第一步,创建一个用户表 1,打开控制台,进入数据库 C:\Users\Ad ...

  7. OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()

    OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...

  8. OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()

    OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...

  9. OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats()

    OpenCV学习(二十一) :计算图像连通分量:connectedComponents(),connectedComponentsWithStats() 1.connectedComponents() ...

最新文章

  1. python opencv cv2 API
  2. Leetcode 116. 填充每个节点的下一个右侧节点指针 解题思路及C++实现
  3. 工厂方法 coding
  4. OC学习篇之---类的初始化方法和点语法的使用
  5. LinkedIn会成为下一个诺基亚吗?
  6. 71. Simplify Path
  7. curl有时获取不到数据 什么原因导致_缓存击穿导致 golang 组件死锁的问题分享...
  8. 山东大学计算机专业毕业后,儿子被山东大学数学系录取,毕业之后的前景将会如何...
  9. java read bytes 阻塞_InputStream中read()与read(byte[] b)java InputStream读取数据问题 | 学步园...
  10. 阀体端面钻6孔组合机床设计及夹具设计
  11. Python QGIS 3自动化教程
  12. 传感器i2c与arduino连接_ARDUINO的I2C通信详解 - arduino读取I2C总线上连接设备的地址...
  13. 孙子兵法——02 作战第二
  14. 三问中国电子云,此时入局的深意是什么?
  15. 信息学奥赛一本通1182 合影效果
  16. 如何分析线程Dump和堆Dump
  17. linux看视频插件,Linux系统下安装Adobe Flash Player插件观播放视频
  18. autoscraper网络刮板模块总结
  19. LIN总线协议详解3(帧的类型)
  20. php运行python爬虫_群晖系统中运行python爬虫程序

热门文章

  1. 如何免费申请阿里云SSL证书
  2. 写给即将工作和刚刚工作的人们
  3. 【OOP】DOTA世界中的对象建模
  4. linux epel7安装,在CentOS6.x或CentOS7.x上安装EPEL Repo,Extra Packages for Enterprise Linux (EPEL)...
  5. Linux网络相关命令
  6. HTML标签汇总(基础表单部分)
  7. 华为OD机试题,用 Java 解【5 键键盘的输出 | 五键键盘】问题 | 含解题思路
  8. 快速删除txt文本数据中的某一列
  9. 基于Camera2和MediaRecorder实现视频录制
  10. C++移动拷贝构造函数