ns3使用-1
ns-3基本使用:
1 | ./waf --run hello-simulator |
选项名 | 含义 |
---|---|
--enable-examples |
编译时包括ns/src/<模块>/examples ,ns/examples 下面所有目录下的examples脚本 |
--enable-tests |
编译时包括ns/src/<模块>/test 目录下的examples脚本 |
--build-profile |
修改编译模式:debug 或者optimized |
源代码的目录结构:
子目录名 | 含义 |
---|---|
bindings | python绑定 |
doc | 各个模块的文档 |
examples | 示例脚本 |
helper | 助手类源代码 |
model | 模块源代码 |
test | 测试用例源代码 |
用户若运行ns-3自带的示例脚本,需要配置添加--enable-examples
选项,这样在./waf
编译时会在build目录下生成一个同名可执行文件,这时就不用指定脚本源文件路径了。
用户添加新脚本,应该放在ns3/scratch
目录下。
ns-3入门:first.cc脚本解析
参考:NS3入门:第一个程序first.cc_一只揪°的博客-CSDN博客
1 |
|
Wifi-无线网络:third脚本
(2条消息) NS-3实例分析——third.cc_xxyxiaxinyan的博客-CSDN博客_ns3实例
1 | //该脚本的第一行是 emacs 模式行。这告诉 emacs 我们在源代码中使用的格式约定(编码风格) |
输出结果:
这里tracing会生成四个文件:third-0-0
;third-0-1
;third-1-0
;third-1-1
分别表示0结点的p2p接口,WiFi接口;1结点的p2p接口,CSMA接口
Python脚本
得益于Pybindgen,也可以用python语言编写ns-3脚本,其可以调用C++中的API,实现与C++脚本基本相同的功能。
运行python脚本:
1 | ./waf --pyrun examples/tutorial/first.py |
再探ns-3中的脚本:
ns-3中的每一个模块都有自己的助手类。源代码在src/<模块名>/helper目录
。
一些主要的ns-3助手如下:
协议层 | 助手类 | 操作对象 | 模块 |
---|---|---|---|
应用层 | BulkSendHelper | TCP分组产生器 | application |
应用层 | PacketSinkHelper | 分组接收器 | application |
应用层 | UdpEchoClientHelper | UDP分组产生器 | application |
传输层,网络层 | InternetStackHelper | TCP/IP协议栈 | internet |
传输层,网络层 | Ipv4AddressHelper | IPV4地址分配 | internet |
传输层,网络层 | Ipv4RouteHelper | IPV4路由分配 | internet |
链路层,物理层 | PointToPointHelper | 点对点网络设备 | point-to-point |
链路层,物理层 | WifiHelper | Wi-Fi网络设备 | wifi |
链路层,物理层 | MobilityHelper | 移动模型 | mobility |
1. 参数输入:属性变量
输入仿真的参数本质上属性就是C++类中的一个变量,比如下面的声明传输速率和传播延时分别是PointToPointNetDevice和PointToPointChannel类的私有成员变量。
1 | pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); |
通过编写脚本配置属性变量的参数,就可以把内部的私有成员变成外部可配置的参数。进而可以仿真不同的网络场景。
2. 配置属性
第一类:助手类,命令行和Config::SetDefault()
可以一次性的给多个对象中的一个属性进行配置。例如first.cc
这个例子,但是必须先使用这三种方法声明属性,再创建网络设备。
1 | //先声明属性 |
第二类:ObjectBase::SetAttribute()函数
更精准的属性配置,一次只能配置一个设备的一个属性,ObjectBase是绝大部分网络元素的基类,如Node,Application,NetDevice,Channel。
1 | //获取结点0中PPP网络设备对象 |
Ptr是ns3中的智能指针,Ptr<NetDevice> dev0
可以理解为NetDevice* dev0
.
第三类:Config::Set函数
更精准的属性配置,一次只能配置多个设备的一个属性,可以看作是前面两个的综合体。这个函数的参数有两个,属性命名空间路径和属性值。
1 | //修改0结点的第0个网络设备 |
这段代码与第二类中的例子作用完全相同,如果想要一次性表示多个对象,将0换成*即可。
绝大多数对象的配置路径都在/NodeList/或/ChannelList/。
对于一个结点,访问Application对象需要从/Nodelist/<结点序号>/ApplicationList/开始。访问其NetDevice对象需要从/Nodelist/<结点序号>/DeviceList/开始。
3. 读取属性
使用ObjectBase::GetAttribute()函数
1 | //获取结点0中PPP网络设备对象 |
4. 查找属性
查找模块属性的使用方法最简单的方式就是查看模块的示例代码
此外,还可以在ns-3 documentation中查看。
在文档中搜索想要的模块,然后点击more即可得到一下信息。
数据输出:trace变量
trace变量本质上是一个函数指针,在使用时,用户需要先定义一个回调函数callback,然后通过trace系统将其与某个C++内部的函数指针相关联。当有特定的网络事件发生时,ns-3就调用相应的trace变量函数指针,进而触发脚本中的回调函数,这样一些重要的模拟数据就会传回给脚本。
trace变量配置方法主要可以分为以下两类:
助手类和Config::Connect(),一次能配置多个trace,通过命名空间路径来获取对象
ObjectBase::TraceConnect,一次只能配置一个trace,直接从代码中获取对象
只能在已经创建的对象上配置trace变量,因为ns-3没有给trace赋予默认值。trace本质是指针,若对象未创建,未分配内存无法配置。
trace一般位于网络拓扑和应用建立以后,Simulator::Run()
之前。但也有例外,比如套接字对象。Socket对象是在应用程序启动之后才被创建,因此直接在脚本中为Socket对象的trace变量设置回调函数会引起程序崩溃。一个比较通用的做法是使用Schedule()函数使配置trace的时间点在应用程序启动之后。
具体例子可以参考:
NS3初识——trace回调与first例子的修改_Aomiz_lm的博客-CSDN博客_ns3中trace
此外,也可以通过助手类进行trace配置,本质上就是对上面的函数进行了封装。
查找trace也可以在ns-3: ns-3 文档 (nsnam.org)中找。
通过命令行也可以定义变量值:
1 | ./waf --run "third --nWifi=18" |
计划事件:Schedule函数
Schedule有三个参数:计划时间延时,事件回调函数指针,事件回调函数参数。
ns-3的log系统:
NS3初识——first.cc与Log系统_Aomiz_lm的博客-CSDN博客
ns-3中的数据跟踪与采集——Logging系统_寻同学的博客-CSDN博客
如果Log系统输出较多可以用下面的命令把Log信息定向输出到一个文本文件中。
1 | ./waf --run first 2>log.log |
网络是怎样模拟的
物理世界中网络的运行是随时间变化的连续过程,ns-3把这些连续变化的网络过程按照时间顺序分割成一系列的离散事件,并按照时间顺序执行这些离散事件。