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/wifi-module.h"
40 
41 #include <ctime>
42 #include <sstream>
43 
44 using namespace ns3;
45 
46 NS_LOG_COMPONENT_DEFINE("WiFiDistanceExperiment");
47 
55 void
57 {
58  NS_LOG_INFO("Sent frame counted in " << datac->GetKey());
59  datac->Update();
60 }
61 
62 int
63 main(int argc, char* argv[])
64 {
65  double distance = 50.0;
66  std::string format("omnet");
67 
68  std::string experiment("wifi-distance-test");
69  std::string strategy("wifi-default");
70  std::string input;
71  std::string runID;
72 
73  {
74  std::stringstream sstr;
75  sstr << "run-" << time(nullptr);
76  runID = sstr.str();
77  }
78 
79  // Set up command line parameters used to control the experiment.
80  CommandLine cmd(__FILE__);
81  cmd.AddValue("distance", "Distance apart to place nodes (in meters).", distance);
82  cmd.AddValue("format", "Format to use for data output.", format);
83  cmd.AddValue("experiment", "Identifier for experiment.", experiment);
84  cmd.AddValue("strategy", "Identifier for strategy.", strategy);
85  cmd.AddValue("run", "Identifier for run.", runID);
86  cmd.Parse(argc, argv);
87 
88  if (format != "omnet" && format != "db")
89  {
90  NS_LOG_ERROR("Unknown output format '" << format << "'");
91  return -1;
92  }
93 
94 #ifndef HAVE_SQLITE3
95  if (format == "db")
96  {
97  NS_LOG_ERROR("sqlite support not compiled in.");
98  return -1;
99  }
100 #endif
101 
102  {
103  std::stringstream sstr("");
104  sstr << distance;
105  input = sstr.str();
106  }
107 
108  //--------------------------------------------
109  //-- Create nodes and network stacks
110  //--------------------------------------------
111  NS_LOG_INFO("Creating nodes.");
113  nodes.Create(2);
114 
115  NS_LOG_INFO("Installing WiFi and Internet stack.");
117  WifiMacHelper wifiMac;
118  wifiMac.SetType("ns3::AdhocWifiMac");
119  YansWifiPhyHelper wifiPhy;
121  wifiPhy.SetChannel(wifiChannel.Create());
122  NetDeviceContainer nodeDevices = wifi.Install(wifiPhy, wifiMac, nodes);
123 
124  InternetStackHelper internet;
125  internet.Install(nodes);
126  Ipv4AddressHelper ipAddrs;
127  ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
128  ipAddrs.Assign(nodeDevices);
129 
130  //--------------------------------------------
131  //-- Setup physical layout
132  //--------------------------------------------
133  NS_LOG_INFO("Installing static mobility; distance " << distance << " .");
135  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
136  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
137  positionAlloc->Add(Vector(0.0, distance, 0.0));
138  mobility.SetPositionAllocator(positionAlloc);
139  mobility.Install(nodes);
140 
141  //--------------------------------------------
142  //-- Create a custom traffic source and sink
143  //--------------------------------------------
144  NS_LOG_INFO("Create traffic source & sink.");
145  Ptr<Node> appSource = NodeList::GetNode(0);
146  Ptr<Sender> sender = CreateObject<Sender>();
147  appSource->AddApplication(sender);
148  sender->SetStartTime(Seconds(1));
149 
150  Ptr<Node> appSink = NodeList::GetNode(1);
151  Ptr<Receiver> receiver = CreateObject<Receiver>();
152  appSink->AddApplication(receiver);
153  receiver->SetStartTime(Seconds(0));
154 
155  Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
156  Ipv4AddressValue("192.168.0.2"));
157 
158  //--------------------------------------------
159  //-- Setup stats and data collection
160  //--------------------------------------------
161 
162  // Create a DataCollector object to hold information about this run.
164  data.DescribeRun(experiment, strategy, input, runID);
165 
166  // Add any information we wish to record about this run.
167  data.AddMetadata("author", "tjkopena");
168 
169  // Create a counter to track how many frames are generated. Updates
170  // are triggered by the trace signal generated by the WiFi MAC model
171  // object. Here we connect the counter to the signal via the simple
172  // TxCallback() glue function defined above.
173  Ptr<CounterCalculator<uint32_t>> totalTx = CreateObject<CounterCalculator<uint32_t>>();
174  totalTx->SetKey("wifi-tx-frames");
175  totalTx->SetContext("node[0]");
176  Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
177  MakeBoundCallback(&TxCallback, totalTx));
178  data.AddDataCalculator(totalTx);
179 
180  // This is similar, but creates a counter to track how many frames
181  // are received. Instead of our own glue function, this uses a
182  // method of an adapter class to connect a counter directly to the
183  // trace signal generated by the WiFi MAC.
184  Ptr<PacketCounterCalculator> totalRx = CreateObject<PacketCounterCalculator>();
185  totalRx->SetKey("wifi-rx-frames");
186  totalRx->SetContext("node[1]");
187  Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
189  data.AddDataCalculator(totalRx);
190 
191  // This counter tracks how many packets---as opposed to frames---are
192  // generated. This is connected directly to a trace signal provided
193  // by our Sender class.
194  Ptr<PacketCounterCalculator> appTx = CreateObject<PacketCounterCalculator>();
195  appTx->SetKey("sender-tx-packets");
196  appTx->SetContext("node[0]");
197  Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
199  data.AddDataCalculator(appTx);
200 
201  // Here a counter for received packets is directly manipulated by
202  // one of the custom objects in our simulation, the Receiver
203  // Application. The Receiver object is given a pointer to the
204  // counter and calls its Update() method whenever a packet arrives.
205  Ptr<CounterCalculator<>> appRx = CreateObject<CounterCalculator<>>();
206  appRx->SetKey("receiver-rx-packets");
207  appRx->SetContext("node[1]");
208  receiver->SetCounter(appRx);
209  data.AddDataCalculator(appRx);
210 
211  // Just to show this is here...
212 
213  /*
214  Ptr<MinMaxAvgTotalCalculator<uint32_t>> test =
215  CreateObject<MinMaxAvgTotalCalculator<uint32_t>>();
216  test->SetKey("test-dc");
217  data.AddDataCalculator(test);
218 
219  test->Update(4);
220  test->Update(8);
221  test->Update(24);
222  test->Update(12);
223  */
224 
225  // This DataCalculator connects directly to the transmit trace
226  // provided by our Sender Application. It records some basic
227  // statistics about the sizes of the packets received (min, max,
228  // avg, total # bytes), although in this scenario they're fixed.
230  CreateObject<PacketSizeMinMaxAvgTotalCalculator>();
231  appTxPkts->SetKey("tx-pkt-size");
232  appTxPkts->SetContext("node[0]");
233  Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
235  data.AddDataCalculator(appTxPkts);
236 
237  // Here we directly manipulate another DataCollector tracking min,
238  // max, total, and average propagation delays. Check out the Sender
239  // and Receiver classes to see how packets are tagged with
240  // timestamps to do this.
241  Ptr<TimeMinMaxAvgTotalCalculator> delayStat = CreateObject<TimeMinMaxAvgTotalCalculator>();
242  delayStat->SetKey("delay");
243  delayStat->SetContext(".");
244  receiver->SetDelayTracker(delayStat);
245  data.AddDataCalculator(delayStat);
246 
247  //--------------------------------------------
248  //-- Run the simulation
249  //--------------------------------------------
250  NS_LOG_INFO("Run Simulation.");
251  Simulator::Run();
252 
253  //--------------------------------------------
254  //-- Generate statistics output.
255  //--------------------------------------------
256 
257  // Pick an output writer based in the requested format.
258  Ptr<DataOutputInterface> output = nullptr;
259  if (format == "omnet")
260  {
261  NS_LOG_INFO("Creating omnet formatted data output.");
262  output = CreateObject<OmnetDataOutput>();
263  }
264  else if (format == "db")
265  {
266 #ifdef HAVE_SQLITE3
267  NS_LOG_INFO("Creating sqlite formatted data output.");
268  output = CreateObject<SqliteDataOutput>();
269 #endif
270  }
271  else
272  {
273  NS_LOG_ERROR("Unknown output format " << format);
274  }
275 
276  // Finally, have that writer interrogate the DataCollector and save
277  // the results.
278  if (output)
279  {
280  output->Output(data);
281  }
282 
283  // Free any memory here at the end of this example.
285 
286  return 0;
287 }
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
static Ptr< Node > GetNode(uint32_t n)
Definition: node-list.cc:251
void PacketUpdate(std::string path, Ptr< const Packet > packet)
Increments the packet counter by one.
void PacketUpdate(std::string path, Ptr< const Packet > packet)
Increments the packet stats by the size of the packet.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static void Run()
Run the simulation.
Definition: simulator.cc:176
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.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
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:768
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
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:707
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.