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  * \file uan-rc-example.cc
23  * \ingroup UAN
24  * This example uses UanMacRc and UanMacRcGw which combined form a system
25  * using what is referred to as RC-MAC.  Details of RC-MAC will be published
26  * soon.  In brief terms, RC-MAC is a dual channel protocol wherein the
27  * available bandwidth is dynamically divided into two channels,
28  * a reservation channel and a data channel.  The network is assumed
29  * to consist of a single gateway node which services several
30  * non-gateway nodes.
31  *
32  * Time is divided into cycles.  The non-gateway nodes transmit RTS packets
33  * on the reservation channel in parallel to scheduled data transmissions
34  * (scheduled in the previous cycle), and the gateway stores these requests
35  * for the duration of the cycle.  At the start of the next cycle
36  * the gateway node transmits a CTS which contains packet transmission times
37  * for reserved packets as well as bandwidth allocation information
38  *
39  * This script deploys a single gateway node (current UanMacRc only supports
40  * a single gateway) in the center of a region and then distributes
41  * non-gateway nodes around the gateway with a uniformly distributed range
42  * between each node and the gateway.
43  *
44  * The script supports two simulation types.  By default the gateway
45  * dynamically determines the optimal parameter settings and
46  * simulations are run with varying number of nodes (SimMin to SimMax as
47  * set by the command line).  If DoNode=0 is given as a command line option
48  * then the mac parameter "a" (approximate expected number of successful
49  * RTS arrivals per cycle) is varied as the simulation parameter.
50  *
51  * For questions about this MAC protocol email "lentracy@gmail.com"
52  */
53 
54 #include "uan-rc-example.h"
55 #include "ns3/core-module.h"
56 #include "ns3/network-module.h"
57 #include "ns3/applications-module.h"
58 #include "ns3/mobility-module.h"
59 #include "ns3/log.h"
60 #include "ns3/config.h"
61 #include "ns3/callback.h"
62 #include "ns3/stats-module.h"
63 
64 #include <fstream>
65 
66 using namespace ns3;
67 
68 NS_LOG_COMPONENT_DEFINE ("UanRcExample");
69 
Experiment()70 Experiment::Experiment ()
71   : m_simMin (1),
72     m_simMax (1),
73     m_simStep (1),
74     m_numRates (1023),
75     m_totalRate (4096),
76     m_maxRange (3000),
77     m_numNodes (15),
78     m_pktSize (1000),
79     m_doNode (true),
80     m_sifs (Seconds (0.05)),
81     m_simTime (Seconds (5000)),
82     m_gnuplotfile ("uan-rc-example.gpl"),
83     m_bytesTotal (0)
84 {
85 }
86 
87 void
ReceivePacket(Ptr<Socket> socket)88 Experiment::ReceivePacket (Ptr<Socket> socket)
89 {
90   Ptr<Packet> packet;
91   while ((packet = socket->Recv ()))
92     {
93       m_bytesTotal += packet->GetSize ();
94     }
95 }
96 
97 UanTxMode
CreateMode(uint32_t kass,uint32_t fc,bool upperblock,std::string name)98 Experiment::CreateMode (uint32_t kass,
99                         uint32_t fc,
100                         bool upperblock,
101                         std::string name)
102 {
103 
104   std::ostringstream buf;
105   buf << name << " " << kass;
106 
107   uint32_t rate = m_totalRate/(m_numRates+1)* (kass);
108   uint32_t bw = kass * m_totalRate / (m_numRates+1);
109   uint32_t fcmode;
110   if(upperblock)
111     fcmode = (m_totalRate - bw)/2 + fc;
112   else
113     fcmode = (uint32_t)((-((double) m_totalRate ) + (double) bw)/2.0 + (double) fc);
114 
115 
116   uint32_t phyrate = m_totalRate;
117 
118   UanTxMode mode;
119   mode = UanTxModeFactory::CreateMode (UanTxMode::OTHER,
120                                        rate,
121                                        phyrate,
122                                        fcmode,
123                                        bw,
124                                        2,
125                                        buf.str ());
126   return mode;
127 }
128 
129 //Creates m_numRates different modes each dividing m_totalRate Hz (assumes 1 bit per hz)
130 //centered at frequency fc
131 void
CreateDualModes(uint32_t fc)132 Experiment::CreateDualModes (uint32_t fc)
133 {
134 
135 
136   for (uint32_t i=1; i < m_numRates+1; i++)
137     {
138       m_controlModes.AppendMode (CreateMode (i, fc, false, "control "));
139     }
140   for (uint32_t i=m_numRates; i > 0; i--)
141     {
142       m_dataModes.AppendMode (CreateMode (i, fc, true, "data "));
143     }
144 }
145 
146 uint32_t
Run(uint32_t param)147 Experiment::Run (uint32_t param)
148 {
149 
150   UanHelper uan;
151 
152   m_bytesTotal=0;
153 
154   uint32_t nNodes;
155   uint32_t a;
156   if(m_doNode)
157     {
158       a=0;
159       nNodes = param;
160     }
161   else
162     {
163       nNodes = m_numNodes;
164       a = param;
165     }
166   Time pDelay = Seconds ((double) m_maxRange / 1500.0);
167 
168   uan.SetPhy ("ns3::UanPhyDual",
169               "SupportedModesPhy1", UanModesListValue (m_dataModes),
170               "SupportedModesPhy2", UanModesListValue (m_controlModes));
171 
172   uan.SetMac ("ns3::UanMacRcGw",
173               "NumberOfRates", UintegerValue (m_numRates),
174               "NumberOfNodes", UintegerValue (nNodes),
175               "MaxReservations", UintegerValue (a),
176               "SIFS", TimeValue (m_sifs),
177               "MaxPropDelay", TimeValue (pDelay),
178               "FrameSize", UintegerValue (m_pktSize));
179   Ptr<UanChannel> chan = CreateObject<UanChannel>();
180 
181   NodeContainer sink;
182   sink.Create (1);
183   NetDeviceContainer sinkDev = uan.Install (sink, chan);
184 
185   uan.SetMac ("ns3::UanMacRc",
186               "NumberOfRates", UintegerValue (m_numRates),
187               "MaxPropDelay", TimeValue (pDelay));
188   NodeContainer nodes;
189   nodes.Create (nNodes);
190   NetDeviceContainer devices = uan.Install (nodes, chan);
191 
192   MobilityHelper mobility;
193   uint32_t depth = 70;
194   Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();
195 
196   Ptr<UniformRandomVariable> urv = CreateObject<UniformRandomVariable> ();
197   Ptr<UniformRandomVariable> utheta = CreateObject<UniformRandomVariable> ();
198   pos->Add (Vector (m_maxRange, m_maxRange, depth));
199 
200   for (uint32_t i=0; i<nNodes; i++)
201     {
202       double theta = utheta->GetValue (0, 2.0*M_PI);
203       double r = urv->GetValue (0,m_maxRange);
204 
205       double x = m_maxRange + r*std::cos (theta);
206       double y = m_maxRange + r*std::sin (theta);
207 
208       pos->Add (Vector (x, y, depth));
209 
210     }
211 
212   mobility.SetPositionAllocator (pos);
213   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
214   mobility.Install (sink);
215   mobility.Install (nodes);
216 
217   PacketSocketHelper pktskth;
218   pktskth.Install (nodes);
219   pktskth.Install (sink);
220 
221   PacketSocketAddress socket;
222   socket.SetSingleDevice (sinkDev.Get (0)->GetIfIndex ());
223   socket.SetPhysicalAddress (sinkDev.Get (0)->GetAddress ());
224   socket.SetProtocol (0);
225 
226   OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
227   app.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
228   app.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
229   app.SetAttribute ("DataRate", DataRateValue (m_totalRate));
230   app.SetAttribute ("PacketSize", UintegerValue (m_pktSize));
231 
232   ApplicationContainer apps = app.Install (nodes);
233 
234   apps.Start (Seconds (0.5));
235   apps.Stop (m_simTime + Seconds (0.5));
236 
237   Ptr<Node> sinkNode = sink.Get (0);
238   TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
239 
240   Ptr<Socket> sinkSocket = Socket::CreateSocket (sinkNode, psfid);
241   sinkSocket->Bind (socket);
242   sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
243 
244   Simulator::Stop (m_simTime + Seconds (0.6));
245   Simulator::Run ();
246   Simulator::Destroy ();
247 
248   return m_bytesTotal;
249 }
250 int
main(int argc,char * argv[])251 main (int argc, char *argv[])
252 {
253 
254   Experiment exp;
255   bool quiet = false;
256 
257   CommandLine cmd (__FILE__);
258   cmd.AddValue ("TotalRate", "Total channel capacity", exp.m_totalRate);
259   cmd.AddValue ("NumberRates", "Number of divided rates ( (NumberRates+1)%TotalRate should be 0)", exp.m_numRates);
260   cmd.AddValue ("MaxRange", "Maximum range between gateway and acoustic node", exp.m_maxRange);
261   cmd.AddValue ("SimMin", "Minimum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMin);
262   cmd.AddValue ("SimMax", "Maximum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMax);
263   cmd.AddValue ("SimStep", "Amount to increment param per trial", exp.m_simStep);
264   cmd.AddValue ("DataFile", "Filename for GnuPlot", exp.m_gnuplotfile);
265   cmd.AddValue ("NumberNodes", "Number of nodes (invalid for doNode=1)", exp.m_numNodes);
266   cmd.AddValue ("SIFS", "SIFS time duration", exp.m_sifs);
267   cmd.AddValue ("PktSize", "Packet size in bytes", exp.m_pktSize);
268   cmd.AddValue ("SimTime", "Simulation time per trial", exp.m_simTime);
269   cmd.AddValue ("DoNode", "1 for do max nodes simulation (invalidates AMin and AMax values)", exp.m_doNode);
270   cmd.AddValue ("Quiet", "Run in quiet mode (disable logging)", quiet);
271   cmd.Parse (argc, argv);
272 
273   if (!quiet)
274     {
275       LogComponentEnable ("UanRcExample", LOG_LEVEL_ALL);
276     }
277 
278   exp.CreateDualModes (12000);
279 
280   ;
281 
282   Gnuplot2dDataset ds;
283   for (uint32_t param=exp.m_simMin; param<=exp.m_simMax; param += exp.m_simStep)
284     {
285       uint32_t bytesRx = exp.Run (param);
286       NS_LOG_DEBUG ("param=" << param << ":  Received " << bytesRx << " bytes at sink");
287 
288       double util = bytesRx*8.0/(exp.m_simTime.GetSeconds ()*exp.m_totalRate);
289 
290       ds.Add (param, util);
291 
292       SeedManager::SetRun (SeedManager::GetRun () + 1);
293     }
294 
295   Gnuplot gp;
296   gp.AddDataset (ds);
297   std::ofstream of (exp.m_gnuplotfile.c_str ());
298   if (!of.is_open ())
299     {
300       NS_FATAL_ERROR ("Can not open GNU Plot outfile: " << exp.m_gnuplotfile);
301     }
302   gp.GenerateOutput (of);
303 
304 }
305