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 
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
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.
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...
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:77
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
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:974
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:876
#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:765
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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:704
cmd
Definition: second.py:40
wifi
Definition: third.py:95
mobility
Definition: third.py:105
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.