ns3

ns3第二个例子构建总线网络拓扑

ns3例子

Posted by MZ on September 23, 2022

一、代码解读

头文件如下:

#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"

拓扑图:

// Default Network Topology
//
//       10.1.1.0
// n0 -------------- n1   n2   n3   n4
//    point-to-point  |    |    |    |
//                    ================
//                      LAN 10.1.2.0

命令行参数与日志开启

//是否开启日志的标志
bool verbose = true;
//总线上的节点数= nCsma+1
uint32_t nCsma = 3;
//命令行输入 上面两个变量的值
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);

cmd.Parse (argc, argv);

if (verbose)
  {
    LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
  }

nCsma = nCsma == 0 ? 1 : nCsma;

创建节点

NodeContainer p2pNodes;
p2pNodes.Create (2);
//与第一个例子不同的地方在于除了创建点对点节点外,还要创建csma节点,也就是总线上的节点
//因为p2p节点之一也在总线上,所以将其Add到csmaNodes中
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma);

设置网络设备和信道

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
//和点对点拓扑几乎一模一样的设置方式
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);

网络协议栈

InternetStackHelper stack;
stack.Install (p2pNodes.Get (0));
stack.Install (csmaNodes);

注意不要加多了,一共五个。不可以如下操作:

InternetStackHelper stack;
stack.Install (p2pNodes);
stack.Install (csmaNodes);

这样有一个既是p2p又是csma的节点被添加了两次协议

分配IP地址

Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);

address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);

应用程序设置与第一个例子类似

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
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));

该实例是让p2p的第一个节点与总线上最后一个进行通信

由于我们实际上已经在这里构建了一个互联网络,因此我们需要某种形式的互联网络路由。ns-3提供了全局路由且无需配置即可使用。事实上,发生的事情是每个节点的行为都像是OSPF路由器一样,可以立即神奇地与幕后的所有其他路由器进行通信。

Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

接下来,我们启用 pcap 跟踪。

pointToPoint.EnablePcapAll ("second");
csma.EnablePcap ("second", csmaDevices.Get (1), true);

CSMA 网络是多点对点网络。这意味着共享介质上可以(在本例中为)多个终结点。这些端点中的每一个都有一个与之关联的网络设备。从此类网络收集跟踪信息有两种基本替代方法。一种方法是为每个网络设备创建一个跟踪文件,并仅存储该网络设备发出或使用的数据包。另一种方法是选择其中一个设备并将其置于混杂模式。然后,该单个设备会“嗅探”网络中的所有数据包,并将它们存储在单个 pcap 文件中。例如,这就是工作原理。最后一个参数告诉 CSMA 帮助程序是否安排在混杂模式下捕获数据包。

代码的最后一部分只是运行并清理模拟,就像示例一样。

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

二、踪迹解析

运行完第二个实例后,会生成三个文件:

second-0-0.pcap  second-1-0.pcap  second-2-0.pcap

第一个:

$ tcpdump -nn -tt -r second-0-0.pcap

reading from file second-0-0.pcap, link-type PPP (PPP)
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.017607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

点对点节点0的追踪结果,可以看到PPP就是点对点链路,追踪到两个数据包,一个发送一个接收。

第二个:

$ tcpdump -nn -tt -r second-1-0.pcap

reading from file second-1-0.pcap, link-type PPP (PPP)
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

点对点节点1的追踪结果,和上一个类似

第三个:

$ tcpdump -nn -tt -r second-2-0.pcap

reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
2.007698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50
2.007710 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50
2.007803 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.013815 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50
2.013828 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

可以看到链路类型变成EN10MB ,以太网类型,而且它需要地址解析协议。节点1知道IP地址,但不知道MAC地址,所以发起请求问谁是10.1.2.4,然后10.1.2.4将MAC地址回应给10.1.2.1,然后数据就能发送到10.1.2.4了。后面也是同理。

如果想从单个设备获取跟踪,可以设置为非混杂模式

pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);

最后一个参数设为false,再来看看输出如何

$ tcpdump -nn -tt -r second-3-0.pcap

reading from file second-3-0.pcap, link-type EN10MB (Ethernet)
2.007698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50
2.013815 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50

非混杂模式旁观者,只能接收到广播到整个csma网络的ARP请求

$ tcpdump -nn -tt -r second-4-0.pcap

reading from file second-4-0.pcap, link-type EN10MB (Ethernet)
2.007698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50
2.007698 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50
2.007803 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.013803 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50
2.013828 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50
2.013828 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

而作为回声交换的实际参与者,混杂与非混杂输出结果是一样的。