我是靠谱客的博主 清脆乌龟,这篇文章主要介绍以wifi-example-sim.cc为例说明NS3统计数据模型,现在分享给大家,希望可以做个参考。

利用NS3已有的Trace系统或者Log机制收集记录和统计数据,例如MAC层收发帧数目,网络层以上收发包数目的跟踪与统计,这里选取example/stats/wifi-example-sim.cc为例来很好说明问题:

这个仿真程序是一个简单的实验,包括两个节点,基于AdhocMAC信道模型,包含NS3仿真所需常见模型如节点/网络设备/协议栈和应用进程,这里的应用进程Sender   和Receiver,基于UDP的不可靠连接。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <ctime> #include <sstream> #include "ns3/core-module.h" #include "ns3/network-module.h" #include "ns3/mobility-module.h" #include "ns3/wifi-module.h" #include "ns3/internet-module.h" #include "ns3/stats-module.h" #include "wifi-example-apps.h" using namespace ns3; using namespace std; NS_LOG_COMPONENT_DEFINE ("WiFiDistanceExperiment"); void TxCallback (Ptr<CounterCalculator<uint32_t> > datac, std::string path, Ptr<const Packet> packet) { NS_LOG_INFO ("Sent frame counted in " << datac->GetKey ()); datac->Update (); // end TxCallback } //---------------------------------------------------------------------- //-- main //---------------------------------------------- int main (int argc, char *argv[]) { double distance = 50.0; string format ("omnet"); string experiment ("wifi-distance-test"); string strategy ("wifi-default"); string input; string runID; { stringstream sstr; sstr << "run-" << time (NULL); runID = sstr.str (); } // Set up command line parameters used to control the experiment. CommandLine cmd; cmd.AddValue ("distance", "Distance apart to place nodes (in meters).", distance); cmd.AddValue ("format", "Format to use for data output.", format); cmd.AddValue ("experiment", "Identifier for experiment.", experiment); cmd.AddValue ("strategy", "Identifier for strategy.", strategy); cmd.AddValue ("run", "Identifier for run.", runID); cmd.Parse (argc, argv); if (format != "omnet" && format != "db") { NS_LOG_ERROR ("Unknown output format '" << format << "'"); return -1; } #ifndef STATS_HAS_SQLITE3 if (format == "db") { NS_LOG_ERROR ("sqlite support not compiled in."); return -1; } #endif { stringstream sstr (""); sstr << distance; input = sstr.str (); } //------------------------------------------------------------ //-- Create nodes and network stacks //-------------------------------------------- NS_LOG_INFO ("Creating nodes."); NodeContainer nodes; nodes.Create (2); NS_LOG_INFO ("Installing WiFi and Internet stack."); WifiHelper wifi; WifiMacHelper wifiMac; wifiMac.SetType ("ns3::AdhocWifiMac"); YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); wifiPhy.SetChannel (wifiChannel.Create ()); NetDeviceContainer nodeDevices = wifi.Install (wifiPhy, wifiMac, nodes); InternetStackHelper internet; internet.Install (nodes); Ipv4AddressHelper ipAddrs; ipAddrs.SetBase ("192.168.0.0", "255.255.255.0"); ipAddrs.Assign (nodeDevices); //------------------------------------------------------------ //-- Setup physical layout //-------------------------------------------- NS_LOG_INFO ("Installing static mobility; distance " << distance << " ."); MobilityHelper mobility; Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>(); positionAlloc->Add (Vector (0.0, 0.0, 0.0)); positionAlloc->Add (Vector (0.0, distance, 0.0)); mobility.SetPositionAllocator (positionAlloc); mobility.Install (nodes); //------------------------------------------------------------ //-- Create a custom traffic source and sink //-------------------------------------------- NS_LOG_INFO ("Create traffic source & sink."); Ptr<Node> appSource = NodeList::GetNode (0); Ptr<Sender> sender = CreateObject<Sender>(); appSource->AddApplication (sender); sender->SetStartTime (Seconds (1)); Ptr<Node> appSink = NodeList::GetNode (1); Ptr<Receiver> receiver = CreateObject<Receiver>(); appSink->AddApplication (receiver); receiver->SetStartTime (Seconds (0)); Config::Set ("/NodeList/*/ApplicationList/*/$Sender/Destination", Ipv4AddressValue ("192.168.0.2")); //------------------------------------------------------------ //-- Setup stats and data collection //-------------------------------------------- // Create a DataCollector object to hold information about this run. DataCollector data; data.DescribeRun (experiment,//experiment 是对象 strategy,//strategy 是被检查的代码或者参数 input,//2个节点距离 runID); // Add any information we wish to record about this run. data.AddMetadata ("author", "tjkopena"); // Create a counter to track how many frames are generated. Updates // are triggered by the trace signal generated by the WiFi MAC model // object. Here we connect the counter to the signal via the simple // TxCallback() glue function defined above. Ptr<CounterCalculator<uint32_t> > totalTx = CreateObject<CounterCalculator<uint32_t> >(); totalTx->SetKey ("wifi-tx-frames"); totalTx->SetContext ("node[0]"); Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx", MakeBoundCallback (&TxCallback, totalTx)); data.AddDataCalculator (totalTx); // This is similar, but creates a counter to track how many frames // are received. Instead of our own glue function, this uses a // method of an adapter class to connect a counter directly to the // trace signal generated by the WiFi MAC. Ptr<PacketCounterCalculator> totalRx = CreateObject<PacketCounterCalculator>(); totalRx->SetKey ("wifi-rx-frames"); totalRx->SetContext ("node[1]"); Config::Connect ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx", MakeCallback (&PacketCounterCalculator::PacketUpdate, totalRx)); data.AddDataCalculator (totalRx); // This counter tracks how many packets---as opposed to frames---are // generated. This is connected directly to a trace signal provided // by our Sender class. Ptr<PacketCounterCalculator> appTx = CreateObject<PacketCounterCalculator>(); appTx->SetKey ("sender-tx-packets"); appTx->SetContext ("node[0]"); Config::Connect ("/NodeList/0/ApplicationList/*/$Sender/Tx", MakeCallback (&PacketCounterCalculator::PacketUpdate, appTx)); data.AddDataCalculator (appTx); // Here a counter for received packets is directly manipulated by // one of the custom objects in our simulation, the Receiver // Application. The Receiver object is given a pointer to the // counter and calls its Update() method whenever a packet arrives. Ptr<CounterCalculator<> > appRx = CreateObject<CounterCalculator<> >(); appRx->SetKey ("receiver-rx-packets"); appRx->SetContext ("node[1]"); receiver->SetCounter (appRx); data.AddDataCalculator (appRx); /** * Just to show this is here... Ptr<MinMaxAvgTotalCalculator<uint32_t> > test = CreateObject<MinMaxAvgTotalCalculator<uint32_t> >(); test->SetKey("test-dc"); data.AddDataCalculator(test); test->Update(4); test->Update(8); test->Update(24); test->Update(12); **/ // This DataCalculator connects directly to the transmit trace // provided by our Sender Application. It records some basic // statistics about the sizes of the packets received (min, max, // avg, total # bytes), although in this scenaro they're fixed. Ptr<PacketSizeMinMaxAvgTotalCalculator> appTxPkts = CreateObject<PacketSizeMinMaxAvgTotalCalculator>(); appTxPkts->SetKey ("tx-pkt-size"); appTxPkts->SetContext ("node[0]"); Config::Connect ("/NodeList/0/ApplicationList/*/$Sender/Tx", MakeCallback (&PacketSizeMinMaxAvgTotalCalculator::PacketUpdate, appTxPkts)); data.AddDataCalculator (appTxPkts); // Here we directly manipulate another DataCollector tracking min, // max, total, and average propagation delays. Check out the Sender // and Receiver classes to see how packets are tagged with // timestamps to do this. Ptr<TimeMinMaxAvgTotalCalculator> delayStat = CreateObject<TimeMinMaxAvgTotalCalculator>(); delayStat->SetKey ("delay"); delayStat->SetContext ("."); receiver->SetDelayTracker (delayStat); data.AddDataCalculator (delayStat); //------------------------------------------------------------ //-- Run the simulation //-------------------------------------------- NS_LOG_INFO ("Run Simulation."); Simulator::Run (); //------------------------------------------------------------ //-- Generate statistics output. //-------------------------------------------- // Pick an output writer based in the requested format. Ptr<DataOutputInterface> output = 0; if (format == "omnet") { NS_LOG_INFO ("Creating omnet formatted data output."); output = CreateObject<OmnetDataOutput>(); } else if (format == "db") { #ifdef STATS_HAS_SQLITE3 NS_LOG_INFO ("Creating sqlite formatted data output."); output = CreateObject<SqliteDataOutput>(); #endif } else { NS_LOG_ERROR ("Unknown output format " << format); } // Finally, have that writer interrogate the DataCollector and save // the results. if (output != 0) output->Output (data); // Free any memory here at the end of this example. Simulator::Destroy (); // end main }
一 给定本次仿真参数distance,format,experiment,strategy,runID在初始化的同时也可以通过命令行改变,这些参数用于从多次实验中快速区分和组合数据。

二 创建节点和网络模型

三 安装协议栈,并分配IP

四 设置移动模型,这里为静止,并给定初始位置

五 安装应用,这里安装Sender / Receiver,自定义的见examples/stats/wifi-example-apps.h|cc

数据统计与收集,这是本文重点,下面具体分析。

这里创建DataCollector对象来存储运行信息,并通过Trace机制记录收发端帧和分组传输情况。

1 记录发端帧传输(基WIFI MAC对界)

通过CounterCalculator(src/stats/model/basic-data-calculators.h )类实现计数,利用Trace机制,当节点0上wifiNetDevice/Mac/MacTx变化(source),通过Config::Connect关联,定义的TxCallback作为sink函数调用,导致CounterCalculator::update调用即m_count++从而起到计数功能;

2 记录收端帧传输(基WIFI MAC对界)

类似情况1,虽然这里的sink函数是PacketConterCalculator::PacketUpdate(src/network/utils/packet-data-calculators.cc),但是该函数仍然是通过CounterCalculator::update实现计数,即利用Trace机制,当节点1上wifiNetDevice/Mac/MacRx变化(source),通过Config::Connect关联;

3 记录发端分组传输

 也是通过PacketConterCalculator::PacketUpdate实现计数,利用Trace机制,当节点0上/Application/*/$Sender/Tx变化(source),通过通过Config::Connect关联,定义的PacketConterCalculator::PacketUpdate作为sink函数调用;

4 记录收端分组接收

由于收端应用Receiver没有定义traced source,故这里没有采用Trace机制,而是直接利用Receiver:;SetCounter直接操作,通过SetCounter显示类型转换,j将appRx赋值给Receiver内部计数器,从而实现计数

以上均是通过PacketConterCalculator(src/network/utils/packet-data-calculators.cc)或者CounterCalculator(src/stats/model/basic-data-calculators.h )实现传输单元的计数,下一个将通过引入PacketSizeMinMaxAvgTotalCalculator (src/network/utils/packet-data-calculators.h|cc)和MinMaxAvgTotalCalculator(src/stats/model/basic-data-calculators.h)实现单元内大小的记录。

5 记录发端分组大小

这里采用Trace机制,节点0上/Application/*/$Sender/Tx变化(source),通过通过Config::Connect关联,定义的PacketSizeMinMaxAvgTotalCalculator::PacketUpdate作为sink函数调用,从而MinMaxAvgTotalCalculator::Update实现大小的记录。

6 记录端到端产生分组时的延迟

类似情况4,不采用Trace机制,直接利用Receiver:;SetDelayTracker记录传世时延最值/平均值等

七 运行程序命令

八 统计结果输出

对于输出要么OMNet++(纯文本输出格式)要么SQLite(数据库格式输出),这取决于程序头部定义的参数format,并最终DataCollector对象进行存储。

九 控制脚本实现最后运行

通过 一个简单的控制脚本实现该仿真程序在不同距离下大量重复(作为输入)实验后运行画图。可参考example/stats/wifi-example-db.sh(以后自己写多个不同输入下重复仿真项目时可参考这个)。该运行脚本每次都是基于一个不同的距离作为输入,收集每次仿真结果到SQLite数据库,其中对于每个距离输入,进行5次重复实验以减小波动。全部仿真完成只需几十秒,在完成存储到数据库后,可通过SQLite命令行进行SQL查询。并调用 wifi-example.gnuplot画图

进入该目录

复制代码
1
2
3
cd /NS3/ns-allinone-3.25/ns-3.25/examples/stats ./wifi-example-db.sh

产生data.db数据库,wifi-default.data和wifi-default.eps图

图是对应距离下的丢包率以表征WiFi模型性能。

最后

以上就是清脆乌龟最近收集整理的关于以wifi-example-sim.cc为例说明NS3统计数据模型的全部内容,更多相关以wifi-example-sim内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部