NS3学习笔记20230712
Tracing系统
在有大量数据产生、收集和分析的脚本中Logging系统会有些笨重繁琐,因此ns-3提供了一个解决此问题的工具——Tracing系统。Tracing系统包含3个基本概念:Tracing Sources、Tracing Sink以及讲前面二者连接在一起的统一机制。
ASCII Tracing
Tracing模块中也提供了Helper类:AsciiTraceHelper
。
ASCII Tracing的含义是一种以ASCII格式的信息输出。在Simulator::Run()
代码前添加如下代码,可以使用AsciiTraceHelper
生成ASCII格式文档。
AsciiTraceHelper ascii;
pointToPoint.EnableAsciiAll(ascii.CreateFileStraeam("myfirst.tr"));
第二行中函数CreateFileStream
创建一个名为参数名(这里为"myfist.tr"
)的流文件并返回该文件作为外面函数EnableAsciiAll
的参数。
而EnableAsciiAll
的作用是通知helper将所有的关于point-to-point设备的仿真信息都打印成ASCII Tracing格式。
运行此脚本后,会在tarballs/ns-allinone-3.36.1/ns-3.36.1
目录下生成文件,文件中包含收集的信息。
PCAP Tracing
还可以生成以.pcap
为后缀的格式文件,该文件可用Wireshark工具打开进行分析。
只需要在Simulator::Run()
前添加如下代码:
pointToPoint.EnablePcapAll("myfirst");
官方examples文件-second.cc
下图为second.cc的网络拓扑结构, n 1 n_1 n1~ n 4 n_4 n4是个有线局域网络, n 0 n_0 n0 经由 n 1 n_1 n1和 n 4 n_4 n4通信。
下面为second.cc
的代码:
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
int main (int argc, char *argv[])
{
// 定义变量,用于决定是否开启2个UdpApplicaition的Logging组件;默认true开启
bool verbose = true;
uint32_t nCsma = 3; // LAN中另有3个node
CommandLine cmd (__FILE__);
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
// 命令行是否开启logging
cmd.Parse (argc,argv);
if (verbose) {
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma = nCsma == 0 ? 1 : nCsma;
/**********网络拓扑部分************/
// 创建使用P2P链路连接的2个node
NodeContainer p2pNodes;
p2pNodes.Create (2);
// 创建另一个NodeContainer类对象,用于总线(CSMA)网络
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
// 将之前P2P的NodeContainer的第二个节点(索引1)添加到CSMA的NodeContainer,以获得CSMA device;这个node将会有2gedevice
csmaNodes.Create (nCsma); // 再创建Bus network上另外的node
// 设置传送速率和信道延迟,同first.cc
PointToPointHelper pointToPoint; // 注意使用Helper的固定格式:
// 1/helper 对象声明及属性设置
// 2/devices 对象声明及接受helper对象安装方法的返回列表,安装方法的参数为节点对象
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
// 安装P2P网卡设备到P2P网络节点,同first.cc
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
// 类似于P2PHelper,CsmaHelper帮助创建和连接CSMA设备及信道
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
// 数据率由Channel属性指定,而非Device属性
// 因为CSMA不允许同一信道上有多个不同数据率的设备
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
// 安装网络协议
InternetStackHelper stack;
stack.Install (p2pNodes.Get (0)); // P2P链路中的第一个节点
stack.Install (csmaNodes);
// P2P链路中的第二个节点包含在csmaNodes中
Ipv4AddressHelper address; // 2个网段的IP地址类对象
address.SetBase ("10.1.1.0", "255.255.255.0"); // 安排P2P网段的地址
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0"); // 安排CSMA网段地址
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
/************网络拓扑部分结束******************/
/************应用程序部分******************/
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
// 将Server服务安装在CSMA网段的最后一个节点上,nCsma是可变的,所以不能用3
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
/**************应用程序部分结束****************/
/**************调用全局路由Helper帮助建立网络路由****************/
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
// 全局路由管理器根据节点产生的链路通告为每个节点建立路由表
/**************开启pcap跟踪****************/
pointToPoint.EnablePcapAll ("second");
// 开启P2PHelper类对象的pcap;"second"为保存文件的前缀名
// 前缀后的节点号是“全局节点号”,不用担心名称相同
csma.EnablePcap ("second", csmaDevices.Get (1), true);
// 开启csmaHelper类对象的pcap
// 使用CSMA网段索引为1的设备(第二个)进行sniff,True开启Promiscuous mode
// NodeContainer类对象的Get方法用于获得容器中给定索引下的节点,返回指向请求节点的指针
// Node类对象的GetId返回节点的全局ID(即节点列表中的索引号)
// 注意之前使用的Get是NetDevice类的方法,以下使用的是Node类的方法
// NetDevice不用取得ID,可以直接使用;但Node需要进一步查找ID
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
运行脚本后会在tarballs/ns-allinone-3.36.1/ns-3.36.1
目录下生成跟踪文件,如图所示
文件的命名格式是相同的,例如,second-0-0.pcap意味着是来自点对点网络设备上的节点0、设备0的跟踪文件。
可以使用wireshark工具分析或者执行下面的命令查看文件内容
tcpdump -nn -tt -r second-0-0.pcap
tcpdump -nn -tt -r second-1-0.pcap
tcpdump -nn -tt -r second-2-0.pcap
执行后可看到以下输出:
首先查看最左端点到点节点(节点0),如上图所示。从输出可以看到链路类型是PPP(点到点)回显数据分组离开节点0,途径P地址为10.1.1.1的关联设备,奔向IP地址为10.1.2.4的最右边CSMA节点。这个数据分组移到点至点链
路,被节点1上点到点的网络设备接收。
另一个跟踪文件second-1-0.pcap,在这里链路类型也是PPP,来自IP地址10.1.1.1的数据分组(在2.000000s被发送到P地址10.1.2.4)出现在该接口上。在这个节点上,数据分组会被转发到CSMA接口,然后去往最终的目的地。
节点2作为CSMA网络混杂嗅探节点的情况如图所示。现在的链路类型为“以太网”,总线网络需要ARP地址解析协议。节点1知道它需要发送数据分组到P地址10.1.2.4,但它不知道相应节点的MAC地址。于是在CSMA网络(FF:FF:FF:FF:FF:FF)上广播寻找IP地址为10124的设备在这种情况下,最右边的节点回答说其MAC地址是 00:00:00:00:00:06。请注意,节点2不直接参与这种交流,但嗅探网络并且报告所有流量。
节点1、设备1发送回显数据分组给IP地址为10.1.2.4的UDP回显服务器服务器接收到回显请求后试图将数据分组发回给源头,服务器知道其地址在另一个网络(IP地址为10.1.2.1)上,这是因为初始化了全局路由。但是回显服务器节点不知道第一个CSMA节点的MAC地址,所以如同第一个CSMA节点所做的,它发送了ARP。
使用NetAnim仿真可看到如下结果,图为P2P节点的第二个节点,即CSMA网络中的第一个节点在向其他节点广播寻址。