ns3

NS3笔记

Posted by KunLiu on November 11, 2016

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的绑定。

参考文章:

creat new module 1

creat new module 2 博主有回复问题

creat new module 3

ns3官网新建model,注意是model

6.First NS3 test script

依据ns3 Tutorial给与的second.cc文件,参考Doxygen API文档,写出第一个以CSMA框架上的数据发送与接收,目的是了解整个测试文件的整体结构以及如何根据文档来使用ns3提供API接口。

ns3文档的技巧: 搜索很有用, 关键词查找, 看到有help首先点, 类中的说明很重要。

总体组成部分

  1. Node(NodeContainer):简单产生节点的个数

  2. CSMA(CsmaHelper):包括Channel和NetDevice(NetDeviceContainer)的设置,先设置CSMA Channel的参数,之后将参数安装给对应的节点,并返回产生NetDevice对象以为分配IP地址使用。

  3. Internet: 包括Stack和IP address两个部分。首先,配置使用的Stack(InternetStackHelper),并安装给对应的节点(Node)。在已有stack的基础上,在设置IP address(这里使用Ipv4AddressHelper),并将地址分配给各个NetDevice,返回一个Ipv4InterfaceContainer对象供之后client需要获取地址使用。

  4. Application:包括Server和Client两个部分。均需要设置参数和端口(port),然后安装返回一个 ApplicationContainer 对象,通过ApplicationContainer 对象来启动和关闭application。

  5. Routing:设定所使用的路由策略,这里使用Ipv4GlobalRoutingHelper。

  6. 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”就可以了。

说明:

  1. 使用”ns3/” 是因为不在同一个目录下就需要使用”n3/”来引人别的module这在新建module需要注意,不过增加“n3/”肯定是对的。

  2. core-module包含Object、Callback、Attribute和Simulator的类,因而一般肯定引入。

  3. 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。

  1. 首先需要看Stack,这里使用InternetStack。同理,Doxygen的右上方搜索InternetStack,找有没有helper ns3后缀的,点击InternetStackHelper

如何给节点分配对应的协议栈,向下又找到输入参数是NodeContainer的install方法,两步搞定分配协议栈。

InternetStackHelper internetStackHelper;
internetStackHelper.Install(nodes);
  1. 再看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分配地址。

  1. 返回的是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的StartStop两个方法控制着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来观察位置


知识共享许可协议
本文采用 CC A-NC-SA 4.0国际许可协议进行许可。