A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
uan-cw-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Leonard Tracy <lentracy@gmail.com>
7 */
8
9/**
10 * @file uan-cw-example.cc
11 * @ingroup uan
12 *
13 * This example showcases the "CW-MAC" described in System Design Considerations
14 * for Undersea Networks article in the IEEE Journal on Selected Areas of
15 * Communications 2008 by Nathan Parrish, Leonard Tracy and Sumit Roy.
16 * The MAC protocol is implemented in the class UanMacCw. CW-MAC is similar
17 * in nature to the IEEE 802.11 DCF with a constant backoff window.
18 * It requires two parameters to be set, the slot time and
19 * the contention window size. The contention window size is
20 * the backoff window size in slots, and the slot time is
21 * the duration of each slot. These parameters should be set
22 * according to the overall network size, internode spacing and
23 * the number of nodes in the network.
24 *
25 * This example deploys nodes randomly (according to RNG seed of course)
26 * in a finite square region with the X and Y coordinates of the nodes
27 * distributed uniformly. The CW parameter is varied throughout
28 * the simulation in order to show the variation in throughput
29 * with respect to changes in CW.
30 */
31
32#include "ns3/applications-module.h"
33#include "ns3/core-module.h"
34#include "ns3/mobility-module.h"
35#include "ns3/network-module.h"
36#include "ns3/stats-module.h"
37#include "ns3/uan-module.h"
38
39#include <fstream>
40
41using namespace ns3;
42
43NS_LOG_COMPONENT_DEFINE("UanCwExample");
44
45/** Unnamed namespace, to disambiguate class Experiment. */
46namespace
47{
48
49/**
50 * @ingroup uan
51 * @brief Helper class for UAN CW MAC example.
52 *
53 * An experiment measures the average throughput for a series of CW values.
54 *
55 * @see uan-cw-example.cc
56 */
58{
59 public:
60 /**
61 * Run an experiment across a range of congestion window values.
62 *
63 * @param uan The Uan stack helper to configure nodes in the model.
64 * @return The data set of CW values and measured throughput
65 */
67 /**
68 * Receive all available packets from a socket.
69 *
70 * @param socket The receive socket.
71 */
72 void ReceivePacket(Ptr<Socket> socket);
73 /**
74 * Assign new random positions to a set of nodes. New positions
75 * are randomly assigned within the bounding box.
76 *
77 * @param nodes The nodes to reposition.
78 */
80 /** Save the throughput from a single run. */
81 void ResetData();
82 /**
83 * Compute average throughput for a set of runs, then increment CW.
84 *
85 * @param cw CW value for completed runs.
86 */
87 void IncrementCw(uint32_t cw);
88
89 uint32_t m_numNodes; //!< Number of transmitting nodes.
90 uint32_t m_dataRate; //!< DataRate in bps.
91 double m_depth; //!< Depth of transmitting and sink nodes.
92 double m_boundary; //!< Size of boundary in meters.
93 uint32_t m_packetSize; //!< Generated packet size in bytes.
94 uint32_t m_bytesTotal; //!< Total bytes received.
95 uint32_t m_cwMin; //!< Min CW to simulate.
96 uint32_t m_cwMax; //!< Max CW to simulate.
97 uint32_t m_cwStep; //!< CW step size, default 10.
98 uint32_t m_avgs; //!< Number of topologies to test for each cw point.
99
100 Time m_slotTime; //!< Slot time duration.
101 Time m_simTime; //!< Simulation run time, default 1000 s.
102
103 std::string m_gnudatfile; //!< Name for GNU Plot output, default uan-cw-example.gpl.
104 std::string m_asciitracefile; //!< Name for ascii trace file, default uan-cw-example.asc.
105 std::string m_bhCfgFile; //!< (Unused)
106
107 Gnuplot2dDataset m_data; //!< Container for the simulation data.
108 std::vector<double> m_throughputs; //!< Throughput for each run.
109
110 /** Default constructor. */
111 Experiment();
112};
113
115 : m_numNodes(15),
116 m_dataRate(80),
117 m_depth(70),
118 m_boundary(500),
119 m_packetSize(32),
120 m_bytesTotal(0),
121 m_cwMin(10),
122 m_cwMax(400),
123 m_cwStep(10),
124 m_avgs(3),
125 m_slotTime(Seconds(0.2)),
126 m_simTime(Seconds(1000)),
127 m_gnudatfile("uan-cw-example.gpl"),
128 m_asciitracefile("uan-cw-example.asc"),
129 m_bhCfgFile("uan-apps/dat/default.cfg")
130{
131}
132
133void
135{
136 NS_LOG_DEBUG(Now().As(Time::S) << " Resetting data");
137 m_throughputs.push_back(m_bytesTotal * 8.0 / m_simTime.GetSeconds());
138 m_bytesTotal = 0;
139}
140
141void
143{
144 NS_ASSERT(m_throughputs.size() == m_avgs);
145
146 double avgThroughput = 0.0;
147 for (uint32_t i = 0; i < m_avgs; i++)
148 {
149 avgThroughput += m_throughputs[i];
150 }
151 avgThroughput /= m_avgs;
152 m_data.Add(cw, avgThroughput);
153 m_throughputs.clear();
154
155 Config::Set("/NodeList/*/DeviceList/*/Mac/CW", UintegerValue(cw + m_cwStep));
156
158
159 NS_LOG_DEBUG("Average for cw=" << cw << " over " << m_avgs << " runs: " << avgThroughput);
160}
161
162void
164{
165 NS_LOG_DEBUG(Now().As(Time::S) << " Updating positions");
166 auto it = nodes.Begin();
168 for (; it != nodes.End(); it++)
169 {
170 Ptr<MobilityModel> mp = (*it)->GetObject<MobilityModel>();
171 mp->SetPosition(Vector(uv->GetValue(0, m_boundary), uv->GetValue(0, m_boundary), 70.0));
172 }
173}
174
175void
177{
178 Ptr<Packet> packet;
179
180 while ((packet = socket->Recv()))
181 {
182 m_bytesTotal += packet->GetSize();
183 }
184 packet = nullptr;
185}
186
189{
190 uan.SetMac("ns3::UanMacCw", "CW", UintegerValue(m_cwMin), "SlotTime", TimeValue(m_slotTime));
193 nc.Create(m_numNodes);
194 sink.Create(1);
195
196 PacketSocketHelper socketHelper;
197 socketHelper.Install(nc);
198 socketHelper.Install(sink);
199
200#ifdef UAN_PROP_BH_INSTALLED
202 CreateObjectWithAttributes<UanPropModelBh>("ConfigFile", StringValue("exbhconfig.cfg"));
203#else
205#endif // UAN_PROP_BH_INSTALLED
206 Ptr<UanChannel> channel =
207 CreateObjectWithAttributes<UanChannel>("PropagationModel", PointerValue(prop));
208
209 // Create net device and nodes with UanHelper
210 NetDeviceContainer devices = uan.Install(nc, channel);
211 NetDeviceContainer sinkdev = uan.Install(sink, channel);
212
213 MobilityHelper mobility;
215
216 {
218 pos->Add(Vector(m_boundary / 2.0, m_boundary / 2.0, m_depth));
219 double rsum = 0;
220
221 double minr = 2 * m_boundary;
222 for (uint32_t i = 0; i < m_numNodes; i++)
223 {
224 double x = urv->GetValue(0, m_boundary);
225 double y = urv->GetValue(0, m_boundary);
226 double newr = std::sqrt((x - m_boundary / 2.0) * (x - m_boundary / 2.0) +
227 (y - m_boundary / 2.0) * (y - m_boundary / 2.0));
228 rsum += newr;
229 minr = std::min(minr, newr);
230 pos->Add(Vector(x, y, m_depth));
231 }
232 NS_LOG_DEBUG("Mean range from gateway: " << rsum / m_numNodes << " min. range " << minr);
233
234 mobility.SetPositionAllocator(pos);
235 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
236 mobility.Install(sink);
237
239 "Position of sink: " << sink.Get(0)->GetObject<MobilityModel>()->GetPosition());
240 mobility.Install(nc);
241
242 PacketSocketAddress socket;
243 socket.SetSingleDevice(sinkdev.Get(0)->GetIfIndex());
244 socket.SetPhysicalAddress(sinkdev.Get(0)->GetAddress());
245 socket.SetProtocol(0);
246
247 OnOffHelper app("ns3::PacketSocketFactory", Address(socket));
248 app.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
249 app.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
250 app.SetAttribute("DataRate", DataRateValue(m_dataRate));
251 app.SetAttribute("PacketSize", UintegerValue(m_packetSize));
252
253 ApplicationContainer apps = app.Install(nc);
254 apps.Start(Seconds(0.5));
255 Time nextEvent = Seconds(0.5);
256
257 for (uint32_t cw = m_cwMin; cw <= m_cwMax; cw += m_cwStep)
258 {
259 for (uint32_t an = 0; an < m_avgs; an++)
260 {
261 nextEvent += m_simTime;
264 }
265 Simulator::Schedule(nextEvent, &Experiment::IncrementCw, this, cw);
266 }
267 apps.Stop(nextEvent + m_simTime);
268
269 Ptr<Node> sinkNode = sink.Get(0);
270 TypeId psfid = TypeId::LookupByName("ns3::PacketSocketFactory");
271 if (!sinkNode->GetObject<SocketFactory>(psfid))
272 {
274 sinkNode->AggregateObject(psf);
275 }
276 Ptr<Socket> sinkSocket = Socket::CreateSocket(sinkNode, psfid);
277 sinkSocket->Bind(socket);
278 sinkSocket->SetRecvCallback(MakeCallback(&Experiment::ReceivePacket, this));
279
280 m_bytesTotal = 0;
281
282 std::ofstream ascii(m_asciitracefile);
283 if (!ascii.is_open())
284 {
285 NS_FATAL_ERROR("Could not open ascii trace file: " << m_asciitracefile);
286 }
288
290 sinkNode = nullptr;
291 sinkSocket = nullptr;
292 pos = nullptr;
293 channel = nullptr;
294 prop = nullptr;
295 for (uint32_t i = 0; i < nc.GetN(); i++)
296 {
297 nc.Get(i) = nullptr;
298 }
299 for (uint32_t i = 0; i < sink.GetN(); i++)
300 {
301 sink.Get(i) = nullptr;
302 }
303
304 for (uint32_t i = 0; i < devices.GetN(); i++)
305 {
306 devices.Get(i) = nullptr;
307 }
308 for (uint32_t i = 0; i < sinkdev.GetN(); i++)
309 {
310 sinkdev.Get(i) = nullptr;
311 }
312
314 return m_data;
315 }
316}
317
318} // unnamed namespace
319
320int
321main(int argc, char** argv)
322{
323 Experiment exp;
324 bool quiet = false;
325
326 std::string gnudatfile("cwexpgnuout.dat");
327 std::string perModel = "ns3::UanPhyPerGenDefault";
328 std::string sinrModel = "ns3::UanPhyCalcSinrDefault";
329
330 CommandLine cmd(__FILE__);
331 cmd.AddValue("NumNodes", "Number of transmitting nodes", exp.m_numNodes);
332 cmd.AddValue("Depth", "Depth of transmitting and sink nodes", exp.m_depth);
333 cmd.AddValue("RegionSize", "Size of boundary in meters", exp.m_boundary);
334 cmd.AddValue("PacketSize", "Generated packet size in bytes", exp.m_packetSize);
335 cmd.AddValue("DataRate", "DataRate in bps", exp.m_dataRate);
336 cmd.AddValue("CwMin", "Min CW to simulate", exp.m_cwMin);
337 cmd.AddValue("CwMax", "Max CW to simulate", exp.m_cwMax);
338 cmd.AddValue("SlotTime", "Slot time duration", exp.m_slotTime);
339 cmd.AddValue("Averages", "Number of topologies to test for each cw point", exp.m_avgs);
340 cmd.AddValue("GnuFile", "Name for GNU Plot output", exp.m_gnudatfile);
341 cmd.AddValue("PerModel", "PER model name", perModel);
342 cmd.AddValue("SinrModel", "SINR model name", sinrModel);
343 cmd.AddValue("Quiet", "Run in quiet mode (disable logging)", quiet);
344 cmd.Parse(argc, argv);
345
346 if (!quiet)
347 {
348 LogComponentEnable("UanCwExample", LOG_LEVEL_ALL);
349 }
350
351 ObjectFactory obf;
352 obf.SetTypeId(perModel);
353 Ptr<UanPhyPer> per = obf.Create<UanPhyPer>();
354 obf.SetTypeId(sinrModel);
355 Ptr<UanPhyCalcSinr> sinr = obf.Create<UanPhyCalcSinr>();
356
357 UanHelper uan;
358 UanTxMode mode;
360 exp.m_dataRate,
361 exp.m_dataRate,
362 12000,
363 exp.m_dataRate,
364 2,
365 "Default mode");
366 UanModesList myModes;
367 myModes.AppendMode(mode);
368
369 uan.SetPhy("ns3::UanPhyGen",
370 "PerModel",
371 PointerValue(per),
372 "SinrModel",
373 PointerValue(sinr),
374 "SupportedModes",
375 UanModesListValue(myModes));
376
377 Gnuplot gp;
378 Gnuplot2dDataset ds;
379 ds = exp.Run(uan);
380
381 gp.AddDataset(ds);
382
383 std::ofstream of(exp.m_gnudatfile);
384 if (!of.is_open())
385 {
386 NS_FATAL_ERROR("Can not open GNU Plot outfile: " << exp.m_gnudatfile);
387 }
388 gp.GenerateOutput(of);
389
390 per = nullptr;
391 sinr = nullptr;
392
393 return 0;
394}
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
uint32_t m_avgs
Number of topologies to test for each cw point.
void UpdatePositions(NodeContainer &nodes) const
Assign new random positions to a set of nodes.
void ReceivePacket(Ptr< Socket > socket)
Receive all available packets from a socket.
std::string m_gnudatfile
Name for GNU Plot output, default uan-cw-example.gpl.
uint32_t m_packetSize
Generated packet size in bytes.
void IncrementCw(uint32_t cw)
Compute average throughput for a set of runs, then increment CW.
void ResetData()
Save the throughput from a single run.
Time m_simTime
Simulation run time, default 1000 s.
double m_depth
Depth of transmitting and sink nodes.
std::vector< double > m_throughputs
Throughput for each run.
Gnuplot2dDataset m_data
Container for the simulation data.
uint32_t m_numNodes
Number of transmitting nodes.
std::string m_asciitracefile
Name for ascii trace file, default uan-cw-example.asc.
double m_boundary
Size of boundary in meters.
Gnuplot2dDataset Run(UanHelper &uan)
Run an experiment across a range of congestion window values.
a polymophic address class
Definition address.h:114
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
Parse command-line arguments.
AttributeValue implementation for DataRate.
Definition data-rate.h:285
Class to represent a 2D points plot.
Definition gnuplot.h:105
void AddDataset(const GnuplotDataset &dataset)
Definition gnuplot.cc:785
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition gnuplot.cc:791
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
Vector GetPosition() const
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static void SetRun(uint64_t run)
Set the run number of simulation.
static uint64_t GetRun()
Get the current run number.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
Object to create transport layer instances that provide a socket API to applications.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition socket.cc:61
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
@ S
second
Definition nstime.h:107
AttributeValue implementation for Time.
Definition nstime.h:1483
a unique identifier for an interface.
Definition type-id.h:49
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
UAN configuration helper.
Definition uan-helper.h:31
void SetMac(std::string type, Ts &&... args)
Set MAC attributes.
Definition uan-helper.h:186
NetDeviceContainer Install(NodeContainer c) const
This method creates a simple ns3::UanChannel (with a default ns3::UanNoiseModelDefault and ns3::UanPr...
static void EnableAsciiAll(std::ostream &os)
Enable ascii output on each device which is of the ns3::UanNetDevice type and dump that to the specif...
void AppendMode(UanTxMode mode)
Add mode to this list.
static UanTxMode CreateMode(UanTxMode::ModulationType type, uint32_t dataRateBps, uint32_t phyRateSps, uint32_t cfHz, uint32_t bwHz, uint32_t constSize, std::string name)
@ FSK
Frequency shift keying.
Definition uan-tx-mode.h:44
Hold an unsigned integer type.
Definition uinteger.h:34
void ReceivePacket(Ptr< Socket > socket)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
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:690
void Set(std::string path, const AttributeValue &value)
Definition config.cc:872
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:294
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition log.cc:284
@ LOG_LEVEL_ALL
Print everything.
Definition log.h:108
Ptr< PacketSink > sink
Pointer to the packet sink application.
Definition wifi-tcp.cc:44