1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Leonard Tracy <lentracy@gmail.com>
19  */
20 
21 
22 /**
23  * \file uan-cw-example.cc
24  * \ingroup uan
25  *
26  * This example showcases the "CW-MAC" described in System Design Considerations
27  * for Undersea Networks article in the IEEE Journal on Selected Areas of
28  * Communications 2008 by Nathan Parrish, Leonard Tracy and Sumit Roy.
29  * The MAC protocol is implemented in the class UanMacCw.  CW-MAC is similar
30  * in nature to the IEEE 802.11 DCF with a constant backoff window.
31  * It requires two parameters to be set, the slot time and
32  * the contention window size.  The contention window size is
33  * the backoff window size in slots, and the slot time is
34  * the duration of each slot.  These parameters should be set
35  * according to the overall network size, internode spacing and
36  * the number of nodes in the network.
37  *
38  * This example deploys nodes randomly (according to RNG seed of course)
39  * in a finite square region with the X and Y coordinates of the nodes
40  * distributed uniformly.  The CW parameter is varied throughout
41  * the simulation in order to show the variation in throughput
42  * with respect to changes in CW.
43  */
44 
45 #include "uan-cw-example.h"
46 #include "ns3/core-module.h"
47 #include "ns3/network-module.h"
48 #include "ns3/mobility-module.h"
49 #include "ns3/stats-module.h"
50 #include "ns3/applications-module.h"
51 
52 #include <fstream>
53 
54 using namespace ns3;
55 
56 NS_LOG_COMPONENT_DEFINE ("UanCwExample");
57 
Experiment()58 Experiment::Experiment ()
59   : m_numNodes (15),
60     m_dataRate (80),
61     m_depth (70),
62     m_boundary (500),
63     m_packetSize (32),
64     m_bytesTotal (0),
65     m_cwMin (10),
66     m_cwMax (400),
67     m_cwStep (10),
68     m_avgs (3),
69     m_slotTime (Seconds (0.2)),
70     m_simTime (Seconds (1000)),
71     m_gnudatfile ("uan-cw-example.gpl"),
72     m_asciitracefile ("uan-cw-example.asc"),
73     m_bhCfgFile ("uan-apps/dat/default.cfg")
74 {
75 }
76 
77 void
ResetData()78 Experiment::ResetData ()
79 {
80   NS_LOG_DEBUG (Now ().As (Time::S) << "  Resetting data");
81   m_throughputs.push_back (m_bytesTotal * 8.0 / m_simTime.GetSeconds ());
82   m_bytesTotal = 0;
83 }
84 
85 void
IncrementCw(uint32_t cw)86 Experiment::IncrementCw (uint32_t cw)
87 {
88   NS_ASSERT (m_throughputs.size () == m_avgs);
89 
90   double avgThroughput = 0.0;
91   for (uint32_t i=0; i<m_avgs; i++)
92     {
93       avgThroughput += m_throughputs[i];
94     }
95   avgThroughput /= m_avgs;
96   m_data.Add (cw, avgThroughput);
97   m_throughputs.clear ();
98 
99   Config::Set ("/NodeList/*/DeviceList/*/Mac/CW", UintegerValue (cw + m_cwStep));
100 
101   SeedManager::SetRun (SeedManager::GetRun () + 1);
102 
103   NS_LOG_DEBUG ("Average for cw=" << cw << " over " << m_avgs << " runs: " << avgThroughput);
104 }
105 void
UpdatePositions(NodeContainer & nodes)106 Experiment::UpdatePositions (NodeContainer &nodes)
107 {
108 
109   NS_LOG_DEBUG (Now ().As (Time::S) << " Updating positions");
110   NodeContainer::Iterator it = nodes.Begin ();
111   Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable> ();
112   for (; it != nodes.End (); it++)
113     {
114       Ptr<MobilityModel> mp = (*it)->GetObject<MobilityModel> ();
115       mp->SetPosition (Vector (uv->GetValue (0, m_boundary), uv->GetValue (0, m_boundary), 70.0));
116     }
117 }
118 
119 void
ReceivePacket(Ptr<Socket> socket)120 Experiment::ReceivePacket (Ptr<Socket> socket)
121 {
122   Ptr<Packet> packet;
123 
124   while ((packet = socket->Recv ()))
125     {
126       m_bytesTotal += packet->GetSize ();
127     }
128   packet = 0;
129 }
130 
131 Gnuplot2dDataset
Run(UanHelper & uan)132 Experiment::Run (UanHelper &uan)
133 {
134   uan.SetMac ("ns3::UanMacCw", "CW", UintegerValue (m_cwMin), "SlotTime", TimeValue (m_slotTime));
135   NodeContainer nc = NodeContainer ();
136   NodeContainer sink = NodeContainer ();
137   nc.Create (m_numNodes);
138   sink.Create (1);
139 
140   PacketSocketHelper socketHelper;
141   socketHelper.Install (nc);
142   socketHelper.Install (sink);
143 
144 #ifdef UAN_PROP_BH_INSTALLED
145   Ptr<UanPropModelBh> prop = CreateObjectWithAttributes<UanPropModelBh> ("ConfigFile", StringValue ("exbhconfig.cfg"));
146 #else
147   Ptr<UanPropModelIdeal> prop = CreateObjectWithAttributes<UanPropModelIdeal> ();
148 #endif //UAN_PROP_BH_INSTALLED
149   Ptr<UanChannel> channel = CreateObjectWithAttributes<UanChannel> ("PropagationModel", PointerValue (prop));
150 
151   //Create net device and nodes with UanHelper
152   NetDeviceContainer devices = uan.Install (nc, channel);
153   NetDeviceContainer sinkdev = uan.Install (sink, channel);
154 
155   MobilityHelper mobility;
156   Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();
157 
158   {
159     Ptr<UniformRandomVariable> urv = CreateObject<UniformRandomVariable> ();
160     pos->Add (Vector (m_boundary / 2.0, m_boundary / 2.0, m_depth));
161     double rsum = 0;
162 
163     double minr = 2 * m_boundary;
164     for (uint32_t i = 0; i < m_numNodes; i++)
165       {
166         double x = urv->GetValue (0, m_boundary);
167         double y = urv->GetValue (0, m_boundary);
168         double newr = std::sqrt ((x - m_boundary / 2.0) * (x - m_boundary / 2.0)
169                             + (y - m_boundary / 2.0) * (y - m_boundary / 2.0));
170         rsum += newr;
171         minr = std::min (minr, newr);
172         pos->Add (Vector (x, y, m_depth));
173 
174       }
175     NS_LOG_DEBUG ("Mean range from gateway: " << rsum / m_numNodes
176                                               << "    min. range " << minr);
177 
178     mobility.SetPositionAllocator (pos);
179     mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
180     mobility.Install (sink);
181 
182     NS_LOG_DEBUG ("Position of sink: "
183                   << sink.Get (0)->GetObject<MobilityModel> ()->GetPosition ());
184     mobility.Install (nc);
185 
186     PacketSocketAddress socket;
187     socket.SetSingleDevice (sinkdev.Get (0)->GetIfIndex ());
188     socket.SetPhysicalAddress (sinkdev.Get (0)->GetAddress ());
189     socket.SetProtocol (0);
190 
191     OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
192     app.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
193     app.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
194     app.SetAttribute ("DataRate", DataRateValue (m_dataRate));
195     app.SetAttribute ("PacketSize", UintegerValue (m_packetSize));
196 
197     ApplicationContainer apps = app.Install (nc);
198     apps.Start (Seconds (0.5));
199     Time nextEvent = Seconds (0.5);
200 
201 
202     for (uint32_t cw = m_cwMin; cw <= m_cwMax; cw += m_cwStep)
203       {
204 
205         for (uint32_t an = 0; an < m_avgs; an++)
206           {
207             nextEvent += m_simTime;
208             Simulator::Schedule (nextEvent, &Experiment::ResetData, this);
209             Simulator::Schedule (nextEvent, &Experiment::UpdatePositions, this, nc);
210           }
211         Simulator::Schedule (nextEvent, &Experiment::IncrementCw, this, cw);
212       }
213     apps.Stop (nextEvent + m_simTime);
214 
215     Ptr<Node> sinkNode = sink.Get (0);
216     TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
217     if (sinkNode->GetObject<SocketFactory> (psfid) == 0)
218       {
219         Ptr<PacketSocketFactory> psf = CreateObject<PacketSocketFactory> ();
220         sinkNode->AggregateObject (psf);
221       }
222     Ptr<Socket> sinkSocket = Socket::CreateSocket (sinkNode, psfid);
223     sinkSocket->Bind (socket);
224     sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
225 
226     m_bytesTotal = 0;
227 
228     std::ofstream ascii (m_asciitracefile.c_str ());
229     if (!ascii.is_open ())
230       {
231         NS_FATAL_ERROR ("Could not open ascii trace file: "
232                         << m_asciitracefile);
233       }
234     uan.EnableAsciiAll (ascii);
235 
236     Simulator::Run ();
237     sinkNode = 0;
238     sinkSocket = 0;
239     pos = 0;
240     channel = 0;
241     prop = 0;
242     for (uint32_t i=0; i < nc.GetN (); i++)
243       {
244         nc.Get (i) = 0;
245       }
246     for (uint32_t i=0; i < sink.GetN (); i++)
247       {
248         sink.Get (i) = 0;
249       }
250 
251     for (uint32_t i=0; i < devices.GetN (); i++)
252       {
253         devices.Get (i) = 0;
254       }
255     for (uint32_t i=0; i < sinkdev.GetN (); i++)
256       {
257         sinkdev.Get (i) = 0;
258       }
259 
260     Simulator::Destroy ();
261     return m_data;
262   }
263 }
264 
265 int
main(int argc,char ** argv)266 main (int argc, char **argv)
267 {
268 
269   Experiment exp;
270   bool quiet = false;
271 
272   std::string gnudatfile ("cwexpgnuout.dat");
273   std::string perModel = "ns3::UanPhyPerGenDefault";
274   std::string sinrModel = "ns3::UanPhyCalcSinrDefault";
275 
276   CommandLine cmd (__FILE__);
277   cmd.AddValue ("NumNodes", "Number of transmitting nodes", exp.m_numNodes);
278   cmd.AddValue ("Depth", "Depth of transmitting and sink nodes", exp.m_depth);
279   cmd.AddValue ("RegionSize", "Size of boundary in meters", exp.m_boundary);
280   cmd.AddValue ("PacketSize", "Generated packet size in bytes", exp.m_packetSize);
281   cmd.AddValue ("DataRate", "DataRate in bps", exp.m_dataRate);
282   cmd.AddValue ("CwMin", "Min CW to simulate", exp.m_cwMin);
283   cmd.AddValue ("CwMax", "Max CW to simulate", exp.m_cwMax);
284   cmd.AddValue ("SlotTime", "Slot time duration", exp.m_slotTime);
285   cmd.AddValue ("Averages", "Number of topologies to test for each cw point", exp.m_avgs);
286   cmd.AddValue ("GnuFile", "Name for GNU Plot output", exp.m_gnudatfile);
287   cmd.AddValue ("PerModel", "PER model name", perModel);
288   cmd.AddValue ("SinrModel", "SINR model name", sinrModel);
289   cmd.AddValue ("Quiet", "Run in quiet mode (disable logging)", quiet);
290   cmd.Parse (argc, argv);
291 
292   if (!quiet)
293     {
294       LogComponentEnable ("UanCwExample", LOG_LEVEL_ALL);
295     }
296 
297   ObjectFactory obf;
298   obf.SetTypeId (perModel);
299   Ptr<UanPhyPer> per = obf.Create<UanPhyPer> ();
300   obf.SetTypeId (sinrModel);
301   Ptr<UanPhyCalcSinr> sinr = obf.Create<UanPhyCalcSinr> ();
302 
303   UanHelper uan;
304   UanTxMode mode;
305   mode = UanTxModeFactory::CreateMode (UanTxMode::FSK, exp.m_dataRate,
306                                        exp.m_dataRate, 12000,
307                                        exp.m_dataRate, 2,
308                                        "Default mode");
309   UanModesList myModes;
310   myModes.AppendMode (mode);
311 
312   uan.SetPhy ("ns3::UanPhyGen",
313               "PerModel", PointerValue (per),
314               "SinrModel", PointerValue (sinr),
315               "SupportedModes", UanModesListValue (myModes));
316 
317   Gnuplot gp;
318   Gnuplot2dDataset ds;
319   ds = exp.Run (uan);
320 
321   gp.AddDataset (ds);
322 
323   std::ofstream of (exp.m_gnudatfile.c_str ());
324   if (!of.is_open ())
325     {
326       NS_FATAL_ERROR ("Can not open GNU Plot outfile: " << exp.m_gnudatfile);
327     }
328   gp.GenerateOutput (of);
329 
330   per = 0;
331   sinr = 0;
332 
333 }
334 
335