A Discrete-Event Network Simulator
API
wifi-example-sim.cc
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation;
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 *
15 * Authors: Joe Kopena <tjkopena@cs.drexel.edu>
16 *
17 * This program conducts a simple experiment: It places two nodes at a
18 * parameterized distance apart. One node generates packets and the
19 * other node receives. The stat framework collects data on packet
20 * loss. Outside of this program, a control script uses that data to
21 * produce graphs presenting performance at the varying distances.
22 * This isn't a typical simulation but is a common "experiment"
23 * performed in real life and serves as an accessible exemplar for the
24 * stat framework. It also gives some intuition on the behavior and
25 * basic reasonability of the NS-3 WiFi models.
26 *
27 * Applications used by this program are in test02-apps.h and
28 * test02-apps.cc, which should be in the same place as this file.
29 *
30 */
31
32#include "wifi-example-apps.h"
33
34#include "ns3/core-module.h"
35#include "ns3/internet-module.h"
36#include "ns3/mobility-module.h"
37#include "ns3/network-module.h"
38#include "ns3/stats-module.h"
39#include "ns3/yans-wifi-helper.h"
40
41#include <ctime>
42#include <sstream>
43
44using namespace ns3;
45
46NS_LOG_COMPONENT_DEFINE("WiFiDistanceExperiment");
47
55void
57{
58 NS_LOG_INFO("Sent frame counted in " << datac->GetKey());
59 datac->Update();
60 // end TxCallback
61}
62
63//----------------------------------------------------------------------
64//-- main
65//----------------------------------------------
66int
67main(int argc, char* argv[])
68{
69 double distance = 50.0;
70 std::string format("omnet");
71
72 std::string experiment("wifi-distance-test");
73 std::string strategy("wifi-default");
74 std::string input;
75 std::string runID;
76
77 {
78 std::stringstream sstr;
79 sstr << "run-" << time(nullptr);
80 runID = sstr.str();
81 }
82
83 // Set up command line parameters used to control the experiment.
84 CommandLine cmd(__FILE__);
85 cmd.AddValue("distance", "Distance apart to place nodes (in meters).", distance);
86 cmd.AddValue("format", "Format to use for data output.", format);
87 cmd.AddValue("experiment", "Identifier for experiment.", experiment);
88 cmd.AddValue("strategy", "Identifier for strategy.", strategy);
89 cmd.AddValue("run", "Identifier for run.", runID);
90 cmd.Parse(argc, argv);
91
92 if (format != "omnet" && format != "db")
93 {
94 NS_LOG_ERROR("Unknown output format '" << format << "'");
95 return -1;
96 }
97
98#ifndef HAVE_SQLITE3
99 if (format == "db")
100 {
101 NS_LOG_ERROR("sqlite support not compiled in.");
102 return -1;
103 }
104#endif
105
106 {
107 std::stringstream sstr("");
108 sstr << distance;
109 input = sstr.str();
110 }
111
112 //------------------------------------------------------------
113 //-- Create nodes and network stacks
114 //--------------------------------------------
115 NS_LOG_INFO("Creating nodes.");
117 nodes.Create(2);
118
119 NS_LOG_INFO("Installing WiFi and Internet stack.");
121 WifiMacHelper wifiMac;
122 wifiMac.SetType("ns3::AdhocWifiMac");
123 YansWifiPhyHelper wifiPhy;
124 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default();
125 wifiPhy.SetChannel(wifiChannel.Create());
126 NetDeviceContainer nodeDevices = wifi.Install(wifiPhy, wifiMac, nodes);
127
128 InternetStackHelper internet;
129 internet.Install(nodes);
130 Ipv4AddressHelper ipAddrs;
131 ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
132 ipAddrs.Assign(nodeDevices);
133
134 //------------------------------------------------------------
135 //-- Setup physical layout
136 //--------------------------------------------
137 NS_LOG_INFO("Installing static mobility; distance " << distance << " .");
139 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
140 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
141 positionAlloc->Add(Vector(0.0, distance, 0.0));
142 mobility.SetPositionAllocator(positionAlloc);
143 mobility.Install(nodes);
144
145 //------------------------------------------------------------
146 //-- Create a custom traffic source and sink
147 //--------------------------------------------
148 NS_LOG_INFO("Create traffic source & sink.");
149 Ptr<Node> appSource = NodeList::GetNode(0);
150 Ptr<Sender> sender = CreateObject<Sender>();
151 appSource->AddApplication(sender);
152 sender->SetStartTime(Seconds(1));
153
154 Ptr<Node> appSink = NodeList::GetNode(1);
155 Ptr<Receiver> receiver = CreateObject<Receiver>();
156 appSink->AddApplication(receiver);
157 receiver->SetStartTime(Seconds(0));
158
159 Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
160 Ipv4AddressValue("192.168.0.2"));
161
162 //------------------------------------------------------------
163 //-- Setup stats and data collection
164 //--------------------------------------------
165
166 // Create a DataCollector object to hold information about this run.
168 data.DescribeRun(experiment, strategy, input, runID);
169
170 // Add any information we wish to record about this run.
171 data.AddMetadata("author", "tjkopena");
172
173 // Create a counter to track how many frames are generated. Updates
174 // are triggered by the trace signal generated by the WiFi MAC model
175 // object. Here we connect the counter to the signal via the simple
176 // TxCallback() glue function defined above.
177 Ptr<CounterCalculator<uint32_t>> totalTx = CreateObject<CounterCalculator<uint32_t>>();
178 totalTx->SetKey("wifi-tx-frames");
179 totalTx->SetContext("node[0]");
180 Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
181 MakeBoundCallback(&TxCallback, totalTx));
182 data.AddDataCalculator(totalTx);
183
184 // This is similar, but creates a counter to track how many frames
185 // are received. Instead of our own glue function, this uses a
186 // method of an adapter class to connect a counter directly to the
187 // trace signal generated by the WiFi MAC.
188 Ptr<PacketCounterCalculator> totalRx = CreateObject<PacketCounterCalculator>();
189 totalRx->SetKey("wifi-rx-frames");
190 totalRx->SetContext("node[1]");
191 Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
192 MakeCallback(&PacketCounterCalculator::PacketUpdate, totalRx));
193 data.AddDataCalculator(totalRx);
194
195 // This counter tracks how many packets---as opposed to frames---are
196 // generated. This is connected directly to a trace signal provided
197 // by our Sender class.
198 Ptr<PacketCounterCalculator> appTx = CreateObject<PacketCounterCalculator>();
199 appTx->SetKey("sender-tx-packets");
200 appTx->SetContext("node[0]");
201 Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
202 MakeCallback(&PacketCounterCalculator::PacketUpdate, appTx));
203 data.AddDataCalculator(appTx);
204
205 // Here a counter for received packets is directly manipulated by
206 // one of the custom objects in our simulation, the Receiver
207 // Application. The Receiver object is given a pointer to the
208 // counter and calls its Update() method whenever a packet arrives.
209 Ptr<CounterCalculator<>> appRx = CreateObject<CounterCalculator<>>();
210 appRx->SetKey("receiver-rx-packets");
211 appRx->SetContext("node[1]");
212 receiver->SetCounter(appRx);
213 data.AddDataCalculator(appRx);
214
228 // This DataCalculator connects directly to the transmit trace
229 // provided by our Sender Application. It records some basic
230 // statistics about the sizes of the packets received (min, max,
231 // avg, total # bytes), although in this scenaro they're fixed.
233 CreateObject<PacketSizeMinMaxAvgTotalCalculator>();
234 appTxPkts->SetKey("tx-pkt-size");
235 appTxPkts->SetContext("node[0]");
236 Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
237 MakeCallback(&PacketSizeMinMaxAvgTotalCalculator::PacketUpdate, appTxPkts));
238 data.AddDataCalculator(appTxPkts);
239
240 // Here we directly manipulate another DataCollector tracking min,
241 // max, total, and average propagation delays. Check out the Sender
242 // and Receiver classes to see how packets are tagged with
243 // timestamps to do this.
244 Ptr<TimeMinMaxAvgTotalCalculator> delayStat = CreateObject<TimeMinMaxAvgTotalCalculator>();
245 delayStat->SetKey("delay");
246 delayStat->SetContext(".");
247 receiver->SetDelayTracker(delayStat);
248 data.AddDataCalculator(delayStat);
249
250 //------------------------------------------------------------
251 //-- Run the simulation
252 //--------------------------------------------
253 NS_LOG_INFO("Run Simulation.");
254 Simulator::Run();
255
256 //------------------------------------------------------------
257 //-- Generate statistics output.
258 //--------------------------------------------
259
260 // Pick an output writer based in the requested format.
261 Ptr<DataOutputInterface> output = nullptr;
262 if (format == "omnet")
263 {
264 NS_LOG_INFO("Creating omnet formatted data output.");
265 output = CreateObject<OmnetDataOutput>();
266 }
267 else if (format == "db")
268 {
269#ifdef HAVE_SQLITE3
270 NS_LOG_INFO("Creating sqlite formatted data output.");
271 output = CreateObject<SqliteDataOutput>();
272#endif
273 }
274 else
275 {
276 NS_LOG_ERROR("Unknown output format " << format);
277 }
278
279 // Finally, have that writer interrogate the DataCollector and save
280 // the results.
281 if (output)
282 {
283 output->Output(data);
284 }
285
286 // Free any memory here at the end of this example.
287 Simulator::Destroy();
288
289 // end main
290 return 0;
291}
Parse command-line arguments.
Definition: command-line.h:232
Introspection did not find any typical Config paths.
void SetContext(const std::string context)
Sets the DataCalculator context to the provided context.
void SetKey(const std::string key)
Sets the DataCalculator key to the provided key.
Collects data.
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
AttributeValue implementation for Ipv4Address.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:169
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Vector3D Vector
Vector alias typedef for compatibility with mobility models.
Definition: vector.h:324
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
create MAC layers for a ns3::WifiNetDevice.
void SetType(std::string type, Args &&... args)
manage and create wifi channel objects for the YANS model.
Ptr< YansWifiChannel > Create() const
Make it easy to create and manage PHY objects for the YANS model.
void SetChannel(Ptr< YansWifiChannel > channel)
void experiment(std::string queue_disc_type)
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:877
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:752
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:691
cmd
Definition: second.py:33
wifi
Definition: third.py:88
mobility
Definition: third.py:96
uint8_t data[writeSize]
void TxCallback(Ptr< CounterCalculator< uint32_t > > datac, std::string path, Ptr< const Packet > packet)
Function called when a packet is transmitted.