NS3
1.安装NS3
安装参考https://www.nsnam.org/docs/tutorial/html/getting-started.html
相关的依赖安装:https://www.nsnam.org/wiki/Installation
遇到问题与解决:
1.测试生成module出错,重新clean再build一下(时间较长,需要之后修改方法)
2.virtualize安装相关依赖仍然disable:需要选择对应的pyhon2.7版本,参考http://stackoverflow.com/questions/19256127/two-versions-of-python-on-linux-how-to-make-2-7-the-default
2.使用ns3图形界面
参考https://www.nsnam.org/wiki/Installation 安装相关依赖。
其中使用pythonvis不需要Python API scanning support这个模块(设置太复杂)。
使用语句有,前面加sudo:
apt-get install gcc g++ python
apt-get install gcc g++ python python-dev
apt-get install mercurial python-setuptools git
apt-get install qt4-dev-tools libqt4-dev
apt-get install cmake libc6-dev libc6-dev-i386 g++-multilib
apt-get install python-pygraphviz python-kiwi python-pygoocanvas libgoocanvas-dev ipython
使用AODV example
cd Desktop/workspace/ns-allinone-3.26/ns-3.26/
./waf --run aodv --vis
出现missing gnome desktop的问题没有关系,只是没有图标而已.pyVis参考:https://www.nsnam.org/wiki/PyViz
此外,还须给代码增加cmdLine,即增加以下代码
int main(int argc, char *argv[]) {
CommandLine cmd;
cmd.Parse (argc, argv);
}
注意其中的main函数中参数定义
3.使用PCAP tracing
参考文档,pointToPoint实现了虚类PcapHelperForDevice,所以可以使用PcapHelperForDevice类的成员函数EnablePcapAll();
pointToPoint.EnablePcapAll ("myfirst");
所以这句需要放在devices生成之后,否则没有devices,那么就没有pcap文件生成。 再使用
tcpdump -nn -tt -r myfirst-0-0.pcap
就够测试pcap文件了。
4.gpsr下载的文件使用
文件来源:http://www.mehic.info/2016/04/greedy-perimeter-stateless-routing-gpsr-in-ns3-25/
打开/src/gpsr/model/gpsr.cc文件,根据终端运行时错误提示, 通过find找到GetypeId方法,去掉PerimeterMode后的空格
TypeId
RoutingProtocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::gpsr::RoutingProtocol")
.SetParent<Ipv4RoutingProtocol> ()
.AddConstructor<RoutingProtocol> ()
.AddAttribute ("HelloInterval", "HELLO messages emission interval.",
TimeValue (Seconds (1)),
MakeTimeAccessor (&RoutingProtocol::HelloInterval),
MakeTimeChecker ())
.AddAttribute ("LocationServiceName", "Indicates wich Location Service is enabled",
EnumValue (GPSR_LS_GOD),
MakeEnumAccessor (&RoutingProtocol::LocationServiceName),
MakeEnumChecker (GPSR_LS_GOD, "GOD",
GPSR_LS_RLS, "RLS"))
.AddAttribute ("PerimeterMode", "Indicates if PerimeterMode is enabled",
BooleanValue (false),
MakeBooleanAccessor (&RoutingProtocol::PerimeterMode),
MakeBooleanChecker ())
;
return tid;
}
其中源文件Attribute”PerimeterMode”末尾有空格.
不能一起把包含test的example文件放入scratch目录下,把7个test文件分别都拷贝在scratch文件目录下。
./waf
./waf --run scratch/gpsr-test1 #不需要.cc后缀名
5.建立新的module
首先进入根目录下的src文件夹中,利用create-module.py 新建你自己的module。
$./create-module.py new-module-name#可以取任何不重复之前module的名字
就会在src目录下产生module模板:
src/
module-name/
bindings/
doc/
examples/
wscript
helper/
model/
test/
examples-to-run.py
wscript
之后需要增加修改自己定义的文件,并在wscipt中增加的文件和需要已有module的绑定。
参考文章:
6.First NS3 test script
依据ns3 Tutorial给与的second.cc文件,参考Doxygen API文档,写出第一个以CSMA框架上的数据发送与接收,目的是了解整个测试文件的整体结构以及如何根据文档来使用ns3提供API接口。
ns3文档的技巧: 搜索很有用, 关键词查找, 看到有help首先点, 类中的说明很重要。
总体组成部分
-
Node(NodeContainer):简单产生节点的个数
-
CSMA(CsmaHelper):包括Channel和NetDevice(NetDeviceContainer)的设置,先设置CSMA Channel的参数,之后将参数安装给对应的节点,并返回产生NetDevice对象以为分配IP地址使用。
-
Internet: 包括Stack和IP address两个部分。首先,配置使用的Stack(InternetStackHelper),并安装给对应的节点(Node)。在已有stack的基础上,在设置IP address(这里使用Ipv4AddressHelper),并将地址分配给各个NetDevice,返回一个Ipv4InterfaceContainer对象供之后client需要获取地址使用。
-
Application:包括Server和Client两个部分。均需要设置参数和端口(port),然后安装返回一个 ApplicationContainer 对象,通过ApplicationContainer 对象来启动和关闭application。
-
Routing:设定所使用的路由策略,这里使用Ipv4GlobalRoutingHelper。
-
others:包括头文件,LOG,cmd,PCAP和 simultator几个部分。
头文件
#include "ns3/core-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
写所需头文件的方法:在Doxygen文档中找到 (右上方搜索关键词) 需要使用类所在的module模块总名称,在头文件中添加#include “ns3/模块名称-module.h”就可以了。
说明:
-
使用”ns3/” 是因为不在同一个目录下就需要使用”n3/”来引人别的module这在新建module需要注意,不过增加“n3/”肯定是对的。
-
core-module包含Object、Callback、Attribute和Simulator的类,因而一般肯定引入。
-
csma,internet,network和application正是几个关键部分的module,可在写文档时,需要时候就增加在头文件中。
命名空间
using namespace ns3;
命名空间使用ns3,类似std,之后文档就不需要使用”ns3::”,个别module中会可能引入新的命名空间。
主函数
int
main (int argc, char *argv[])
{
}
Node
参看Doxygen文档的NodeContainer
NodeContainer nodes;
nodes.Create(2);
先新建NodeContainer类的对象,再使用Create (uint32_t n) 方法建立节点。这样建立的节点对象没有任何配置,需要在后面为之配置。
Channel and Devices(CSMA)
既然要基于CSMA的框架上传送数据,那么在Doxygen上搜索Csma,一般先看有没有helper,helper一般是为了建立对象而准备的。搜索到csmahelper ns3点击,参看CsmaHelper,它是结果就是产生节点的NetDeviceContainer (写的是a set of CsmaNetDevice,但是install返回是NetDeviceContainer,因而NetDeviceContainer包含一系列的CsmaNetDevice)。
CsmaHelper csmaNode;
这样建立了一个csmaNode对象,但是这个helper对象没有任何配置。
那么怎么配置对象产生NetDeviceContainer:继续向下有没有返回NetDeiceContainer的方法,找到有多个Install方法就是通过输入节点就能够返回一个NetDeviceContainer的对象。点击输入参数只有节点的Install方法,可以知道该方法通过设置CsmaChannel的属性后,输入所需配置Node节点,就能为节点配置channel的参数,并返回该节点对应的一个NetDeviceContainer。
那么CsmaChannel有哪些属性:点击CsmaChannel,看到Detailed Description一栏中的Attribute有DataRate和Delay两个属性。
这样就可以根据CsmaHelper::SetChannelAttribute方法来通过csmaNode对象来设置Channel的属性值。
csmaNode.SetChannelAttribute("DataRate",StringValue("100Mbps"));
csmaNode.SetChannelAttribute("Delay",StringValue("6560ns"));
设置好属性值后,就可以为节点安装(install)配置了,再返回一个NetDeviceContainer对象。
NetDeviceContainer csmaNetDevice;
csmaNetDevice=csmaNode.Install(nodes);
这里NetDeviceContainer对象csmaNetDevice为后面分配addres作链接 整个使用连接线:Node->NetDevice(前提配置channel)->AddressInteface(前提配置stack和addres)->ClientHelp。
Internet
Internet包括三个部分:Stack、Address和 Interface。
- 首先需要看Stack,这里使用InternetStack。同理,Doxygen的右上方搜索InternetStack,找有没有helper ns3后缀的,点击InternetStackHelper 。
如何给节点分配对应的协议栈,向下又找到输入参数是NodeContainer的install方法,两步搞定分配协议栈。
InternetStackHelper internetStackHelper;
internetStackHelper.Install(nodes);
- 再看Address,这里使用ipv4地址。搜索ipv4address,找到Ipv4AddressHelper
采用类似获取Devices中方法,倒着寻找,先找输出方法再找配置的方法,写的时候先配置后输出方法。
输出方法我们需要的是返回Ipv4InterfaceContainer对象的方法,即Ipv4AddressHelper::Assign方法。查看文档还需要Ipv4AddressHelper::SetBase来设置基本的Addres。
Ipv4AddressHelper ipv4AddressHelper;
ipv4AddressHelper.SetBase("10.1.1.0","255.255.255.0");
之后Ipv4AddressHelper可调用Assign方法来安顺序为NetDeviceCotainer分配地址。
- 返回的是Ipv4InterfaceContainer对象,所以新建对象接收返回值。
Ipv4InterfaceContainer ipv4InterfaceContainer;
ipv4InterfaceContainer=ipv4AddressHelper.Assign(csmaNetDevice);
Application
Application主要包括server和client两个部分。先设置Application 使用的协议(Udp/TCP等),这里使用Udp
先为Application设置对应的输出log日志,对应不同Application有不同LogComponent,需要在All LogComponents中对应寻找。
LogComponentEnable("UdpClient",LOG_LEVEL_INFO);
LogComponentEnable("UdpServer",LOG_LEVEL_INFO);
这里使用Udp作为传输协议,Udp也有两种,一种是正常的一发一收 Udp,一种是接收并回复 的UdpEcho,两种的设置完全相同,只需在写法上增加或取消”Echo”就可以实现两种变换(LogComponent还需要增加”Application”)。
Server
UdpServerHelp在初始化上首先需要端口号,否则报错non-class type ‘ns3::UdpServerHelper()’。建立之后通过install就可以将对应节点配置为UdpServer,并返回ApplicationContainer对象。
UdpServerHelper server (9);
ApplicationContainer serverApps = server.Install (nodes.Get (1));
ApplicationContainer的Start和Stop两个方法控制着Apllication的运行时间。
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
Client
UdpClientHelp相比Server需要更多的配置。UdpClientHelp的初始化还需要通过Interface来获取的Server地址与端口号。
此外,因为是client发送(TOEXPLAIN: 为什么是Client发送?),所以需要UdpClientHelper::SetAttribute 配置包的相关属性。(server当然也有属性的设置,但是这里设置client,server使用默认值)具体属性在UdpClient中的Detailed Description中可以查看。
UdpClientHelper client (ipv4InterfaceContainer.GetAddress (1), 9);
client.SetAttribute ("MaxPackets", UintegerValue (2));
client.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
client.SetAttribute ("PacketSize", UintegerValue (1024));
同样,返回一个ApplicationContainer对象,设置Start与Stop。
ApplicationContainer clientApps = client.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Routing
使用ipv4协议栈的简单路由策略Ipv4GlobalRoutingHelper。
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Ipv4GlobalRoutingHelper这里没有新建对象,所以直接用”::”访问方法函数PopulateRoutingTables ()产生一个routing database并初始化路由表。
Simulator
通过Simulator开始与结束仿真。
Simulator::Run ();
Simulator::Destroy ();
Simulator是core module中的类,这里没有新建对象,所以直接用”::”访问方法函数。
运行
拷贝文件到scratch 目录下,进入ns根目录,终端输入
$ ./waf
$ ./waf --run scratch/文件名 #不需要.cc后缀名
Ta da.. . 就可以显示结果了,接下来通过修改参数查看结果有何变化。
6. Mobility的运用
使用Moblity先从简单的设定开始,主要使用MobilityHelper来帮助建立移动模型。包含设定初始位置(SetPositionAllocator)、设置运动模型(SetMobilityModel)和安装给node(Install)这三个步骤。 简单范例如下:
#include <ns3/core-module.h>
#include <ns3/mobility-module.h>
using namespace ns3;
int main(int argc, char const *argv[]) {
NodeContainer nodes;
nodes.Create(3);
MobilityHelper mobility;
mobility.SetPositionAllocator("ns3::GridPositionAllocator",
"MinX",DoubleValue(0.0),
"MinY",DoubleValue(0.0),
"DeltaX",DoubleValue(5.0),
"DeltaY",DoubleValue(10.0),
"LayoutType",StringValue ("RowFirst"));
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
mobility.Install(nodes);
return 0;
}
但是观察位置变动,mobilityHelper在install时候会产生mobiltityModel的对象,观看mobility中可以看到有config的状态。可以在坐标位置改变的时候调动CourseChange的方法,反映3位坐标的状态改变。
static void
CourseChange ( std::string foo, Ptr<const MobilityModel> mobility)
{
Vector pos = mobility->GetPosition (); // Get position
Vector vel = mobility->GetVelocity (); // Get velocity
// Prints position and velocities
std::cout << Simulator::Now () << " POS: x=" << pos.x << ", y=" << pos.y
<< ", z=" << pos.z << "; VEL:" << vel.x << ", y=" << vel.y
<< ", z=" << vel.z << std::endl;
}
//main function code
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
MakeCallback (&CourseChange));
其中的/NodeList//$ns3::MobilityModel/CourseChange中间的号就是mobility资源的标号,可以通过0,1,2等访问对应node的mobility来观察位置