1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation;
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 * Author: Duy Nguyen <duy@soe.ucsc.edu>
17 */
18
19 /**
20 * Scenarios: 100 nodes, multiple simultaneous flows, multi-hop ad hoc, routing,
21 * and mobility
22 *
23 * QUICK INSTRUCTIONS:
24 *
25 * To optimize build:
26 * ./waf -d optimized configure
27 * ./waf
28 *
29 * To compile:
30 * ./waf --run wifi-multirate
31 *
32 * To compile with command line(useful for varying parameters):
33 * ./waf --run "wifi-multirate --totalTime=0.3s --rateManager=ns3::MinstrelWifiManager"
34 *
35 * To turn on NS_LOG:
36 * export NS_LOG=multirate=level_all
37 * (can only view log if built with ./waf -d debug configure)
38 *
39 * To debug:
40 * ./waf --shell
41 * gdb ./build/debug/examples/wireless/wifi-multirate
42 *
43 * To view pcap files:
44 * tcpdump -nn -tt -r filename.pcap
45 *
46 * To monitor the files:
47 * tail -f filename.pcap
48 *
49 */
50
51 #include "ns3/gnuplot.h"
52 #include "ns3/command-line.h"
53 #include "ns3/config.h"
54 #include "ns3/uinteger.h"
55 #include "ns3/boolean.h"
56 #include "ns3/double.h"
57 #include "ns3/string.h"
58 #include "ns3/log.h"
59 #include "ns3/yans-wifi-helper.h"
60 #include "ns3/mobility-helper.h"
61 #include "ns3/internet-stack-helper.h"
62 #include "ns3/ipv4-address-helper.h"
63 #include "ns3/on-off-helper.h"
64 #include "ns3/yans-wifi-channel.h"
65 #include "ns3/mobility-model.h"
66 #include "ns3/olsr-helper.h"
67 #include "ns3/ipv4-static-routing-helper.h"
68 #include "ns3/ipv4-list-routing-helper.h"
69 #include "ns3/rectangle.h"
70 #include "ns3/flow-monitor-helper.h"
71
72 using namespace ns3;
73
74 NS_LOG_COMPONENT_DEFINE ("multirate");
75
76 class Experiment
77 {
78 public:
79 Experiment ();
80 Experiment (std::string name);
81 Gnuplot2dDataset Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
82 const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility);
83
84 bool CommandSetup (int argc, char **argv);
IsRouting()85 bool IsRouting ()
86 {
87 return (enableRouting == 1) ? 1 : 0;
88 }
IsMobility()89 bool IsMobility ()
90 {
91 return (enableMobility == 1) ? 1 : 0;
92 }
93
GetScenario()94 uint32_t GetScenario ()
95 {
96 return scenario;
97 }
98
GetRtsThreshold()99 std::string GetRtsThreshold ()
100 {
101 return rtsThreshold;
102 }
GetOutputFileName()103 std::string GetOutputFileName ()
104 {
105 return outputFileName;
106 }
GetRateManager()107 std::string GetRateManager ()
108 {
109 return rateManager;
110 }
111
112 private:
113 Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
114 NodeContainer GenerateNeighbors (NodeContainer c, uint32_t senderId);
115
116 void ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop);
117 void AssignNeighbors (NodeContainer c);
118 void SelectSrcDest (NodeContainer c);
119 void ReceivePacket (Ptr<Socket> socket);
120 void CheckThroughput ();
121 void SendMultiDestinations (Ptr<Node> sender, NodeContainer c);
122
123 Gnuplot2dDataset m_output;
124
125 double totalTime;
126 double expMean;
127 double samplingPeriod;
128
129 uint32_t bytesTotal;
130 uint32_t packetSize;
131 uint32_t gridSize;
132 uint32_t nodeDistance;
133 uint32_t port;
134 uint32_t scenario;
135
136 bool enablePcap;
137 bool enableTracing;
138 bool enableFlowMon;
139 bool enableRouting;
140 bool enableMobility;
141
142 NodeContainer containerA, containerB, containerC, containerD;
143 std::string rtsThreshold, rateManager, outputFileName;
144 };
145
Experiment()146 Experiment::Experiment ()
147 {
148 }
149
Experiment(std::string name)150 Experiment::Experiment (std::string name)
151 : m_output (name),
152 totalTime (0.3),
153 expMean (0.1),
154 //flows being exponentially distributed
155 samplingPeriod (0.1),
156 bytesTotal (0),
157 packetSize (2000),
158 gridSize (10),
159 //10x10 grid for a total of 100 nodes
160 nodeDistance (30),
161 port (5000),
162 scenario (4),
163 enablePcap (false),
164 enableTracing (true),
165 enableFlowMon (false),
166 enableRouting (false),
167 enableMobility (false),
168 rtsThreshold ("2200"),
169 //0 for enabling rts/cts
170 rateManager ("ns3::MinstrelWifiManager"),
171 outputFileName ("minstrel")
172 {
173 m_output.SetStyle (Gnuplot2dDataset::LINES);
174 }
175
176 Ptr<Socket>
SetupPacketReceive(Ptr<Node> node)177 Experiment::SetupPacketReceive (Ptr<Node> node)
178 {
179 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
180 Ptr<Socket> sink = Socket::CreateSocket (node, tid);
181 InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), port);
182 sink->Bind (local);
183 sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
184
185 return sink;
186 }
187
188 void
ReceivePacket(Ptr<Socket> socket)189 Experiment::ReceivePacket (Ptr<Socket> socket)
190 {
191 Ptr<Packet> packet;
192 while ((packet = socket->Recv ()))
193 {
194 bytesTotal += packet->GetSize ();
195 }
196 }
197
198 void
CheckThroughput()199 Experiment::CheckThroughput ()
200 {
201 double mbs = ((bytesTotal * 8.0) / 1000000 / samplingPeriod);
202 bytesTotal = 0;
203 m_output.Add ((Simulator::Now ()).GetSeconds (), mbs);
204
205 //check throughput every samplingPeriod second
206 Simulator::Schedule (Seconds (samplingPeriod), &Experiment::CheckThroughput, this);
207 }
208
209 /**
210 *
211 * Take the grid map, divide it into 4 quadrants
212 * Assign all nodes from each quadrant to a specific container
213 *
214 */
215 void
AssignNeighbors(NodeContainer c)216 Experiment::AssignNeighbors (NodeContainer c)
217 {
218 uint32_t totalNodes = c.GetN ();
219 for (uint32_t i = 0; i < totalNodes; i++)
220 {
221 if ( (i % gridSize) <= (gridSize / 2 - 1))
222 {
223 //lower left quadrant
224 if ( i < totalNodes / 2 )
225 {
226 containerA.Add (c.Get (i));
227 }
228
229 //upper left quadrant
230 if ( i >= (uint32_t)(4 * totalNodes) / 10 )
231 {
232 containerC.Add (c.Get (i));
233 }
234 }
235 if ( (i % gridSize) >= (gridSize / 2 - 1))
236 {
237 //lower right quadrant
238 if ( i < totalNodes / 2 )
239 {
240 containerB.Add (c.Get (i));
241 }
242
243 //upper right quadrant
244 if ( i >= (uint32_t)(4 * totalNodes) / 10 )
245 {
246 containerD.Add (c.Get (i));
247 }
248 }
249 }
250 }
251
252 /**
253 * Generate 1-hop and 2-hop neighbors of a node in grid topology
254 *
255 */
256 NodeContainer
GenerateNeighbors(NodeContainer c,uint32_t senderId)257 Experiment::GenerateNeighbors (NodeContainer c, uint32_t senderId)
258 {
259 NodeContainer nc;
260 uint32_t limit = senderId + 2;
261 for (uint32_t i = senderId - 2; i <= limit; i++)
262 {
263 //must ensure the boundaries for other topologies
264 nc.Add (c.Get (i));
265 nc.Add (c.Get (i + 10));
266 nc.Add (c.Get (i + 20));
267 nc.Add (c.Get (i - 10));
268 nc.Add (c.Get (i - 20));
269 }
270 return nc;
271 }
272
273 /**
274 * Sources and destinations are randomly selected such that a node
275 * may be the source for multiple destinations and a node maybe a destination
276 * for multiple sources.
277 */
278 void
SelectSrcDest(NodeContainer c)279 Experiment::SelectSrcDest (NodeContainer c)
280 {
281 uint32_t totalNodes = c.GetN ();
282 Ptr<UniformRandomVariable> uvSrc = CreateObject<UniformRandomVariable> ();
283 uvSrc->SetAttribute ("Min", DoubleValue (0));
284 uvSrc->SetAttribute ("Max", DoubleValue (totalNodes / 2 - 1));
285 Ptr<UniformRandomVariable> uvDest = CreateObject<UniformRandomVariable> ();
286 uvDest->SetAttribute ("Min", DoubleValue (totalNodes / 2));
287 uvDest->SetAttribute ("Max", DoubleValue (totalNodes));
288
289 for (uint32_t i = 0; i < totalNodes / 3; i++)
290 {
291 ApplicationSetup (c.Get (uvSrc->GetInteger ()), c.Get (uvDest->GetInteger ()), 0, totalTime);
292 }
293 }
294
295 /**
296 *
297 * A sender node will set up a flow to each of the its neighbors
298 * in its quadrant randomly. All the flows are exponentially distributed
299 *
300 */
301 void
SendMultiDestinations(Ptr<Node> sender,NodeContainer c)302 Experiment::SendMultiDestinations (Ptr<Node> sender, NodeContainer c)
303 {
304
305 // UniformRandomVariable params: (Xrange, Yrange)
306 Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable> ();
307 uv->SetAttribute ("Min", DoubleValue (0));
308 uv->SetAttribute ("Max", DoubleValue (c.GetN ()));
309
310 // ExponentialRandomVariable params: (mean, upperbound)
311 Ptr<ExponentialRandomVariable> ev = CreateObject<ExponentialRandomVariable> ();
312 ev->SetAttribute ("Mean", DoubleValue (expMean));
313 ev->SetAttribute ("Bound", DoubleValue (totalTime));
314
315 double start = 0.0, stop;
316 uint32_t destIndex;
317
318 for (uint32_t i = 0; i < c.GetN (); i++)
319 {
320 stop = start + ev->GetValue ();
321 NS_LOG_DEBUG ("Start=" << start << " Stop=" << stop);
322
323 do
324 {
325 destIndex = (uint32_t) uv->GetValue ();
326 }
327 while ( (c.Get (destIndex))->GetId () == sender->GetId ());
328
329 ApplicationSetup (sender, c.Get (destIndex), start, stop);
330
331 start = stop;
332
333 if (start > totalTime)
334 {
335 break;
336 }
337 }
338 }
339
340 static inline Vector
GetPosition(Ptr<Node> node)341 GetPosition (Ptr<Node> node)
342 {
343 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
344 return mobility->GetPosition ();
345 }
346
347 static inline std::string
PrintPosition(Ptr<Node> client,Ptr<Node> server)348 PrintPosition (Ptr<Node> client, Ptr<Node> server)
349 {
350 Vector serverPos = GetPosition (server);
351 Vector clientPos = GetPosition (client);
352
353 Ptr<Ipv4> ipv4Server = server->GetObject<Ipv4> ();
354 Ptr<Ipv4> ipv4Client = client->GetObject<Ipv4> ();
355
356 Ipv4InterfaceAddress iaddrServer = ipv4Server->GetAddress (1,0);
357 Ipv4InterfaceAddress iaddrClient = ipv4Client->GetAddress (1,0);
358
359 Ipv4Address ipv4AddrServer = iaddrServer.GetLocal ();
360 Ipv4Address ipv4AddrClient = iaddrClient.GetLocal ();
361
362 std::ostringstream oss;
363 oss << "Set up Server Device " << (server->GetDevice (0))->GetAddress ()
364 << " with ip " << ipv4AddrServer
365 << " position (" << serverPos.x << "," << serverPos.y << "," << serverPos.z << ")";
366
367 oss << "Set up Client Device " << (client->GetDevice (0))->GetAddress ()
368 << " with ip " << ipv4AddrClient
369 << " position (" << clientPos.x << "," << clientPos.y << "," << clientPos.z << ")"
370 << "\n";
371 return oss.str ();
372 }
373
374 void
ApplicationSetup(Ptr<Node> client,Ptr<Node> server,double start,double stop)375 Experiment::ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop)
376 {
377 Ptr<Ipv4> ipv4Server = server->GetObject<Ipv4> ();
378
379 Ipv4InterfaceAddress iaddrServer = ipv4Server->GetAddress (1,0);
380 Ipv4Address ipv4AddrServer = iaddrServer.GetLocal ();
381
382 NS_LOG_DEBUG (PrintPosition (client, server));
383
384 // Equipping the source node with OnOff Application used for sending
385 OnOffHelper onoff ("ns3::UdpSocketFactory", Address (InetSocketAddress (Ipv4Address ("10.0.0.1"), port)));
386 onoff.SetConstantRate (DataRate (60000000));
387 onoff.SetAttribute ("PacketSize", UintegerValue (packetSize));
388 onoff.SetAttribute ("Remote", AddressValue (InetSocketAddress (ipv4AddrServer, port)));
389
390 ApplicationContainer apps = onoff.Install (client);
391 apps.Start (Seconds (start));
392 apps.Stop (Seconds (stop));
393
394 Ptr<Socket> sink = SetupPacketReceive (server);
395
396 }
397
398 Gnuplot2dDataset
Run(const WifiHelper & wifi,const YansWifiPhyHelper & wifiPhy,const WifiMacHelper & wifiMac,const YansWifiChannelHelper & wifiChannel,const MobilityHelper & mobility)399 Experiment::Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
400 const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility)
401 {
402
403
404 uint32_t nodeSize = gridSize * gridSize;
405 NodeContainer c;
406 c.Create (nodeSize);
407
408 YansWifiPhyHelper phy = wifiPhy;
409 phy.SetChannel (wifiChannel.Create ());
410
411 WifiMacHelper mac = wifiMac;
412 NetDeviceContainer devices = wifi.Install (phy, mac, c);
413
414
415 OlsrHelper olsr;
416 Ipv4StaticRoutingHelper staticRouting;
417
418 Ipv4ListRoutingHelper list;
419
420 if (enableRouting)
421 {
422 list.Add (staticRouting, 0);
423 list.Add (olsr, 10);
424 }
425
426 InternetStackHelper internet;
427
428 if (enableRouting)
429 {
430 internet.SetRoutingHelper (list); // has effect on the next Install ()
431 }
432 internet.Install (c);
433
434
435 Ipv4AddressHelper address;
436 address.SetBase ("10.0.0.0", "255.255.255.0");
437
438 Ipv4InterfaceContainer ipInterfaces;
439 ipInterfaces = address.Assign (devices);
440
441 MobilityHelper mobil = mobility;
442 mobil.SetPositionAllocator ("ns3::GridPositionAllocator",
443 "MinX", DoubleValue (0.0),
444 "MinY", DoubleValue (0.0),
445 "DeltaX", DoubleValue (nodeDistance),
446 "DeltaY", DoubleValue (nodeDistance),
447 "GridWidth", UintegerValue (gridSize),
448 "LayoutType", StringValue ("RowFirst"));
449
450 mobil.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
451
452 if (enableMobility && enableRouting)
453 {
454 //Rectangle (xMin, xMax, yMin, yMax)
455 mobil.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
456 "Bounds", RectangleValue (Rectangle (0, 500, 0, 500)),
457 "Speed", StringValue ("ns3::ConstantRandomVariable[Constant=10]"),
458 "Pause", StringValue ("ns3::ConstantRandomVariable[Constant=0.2]"));
459 }
460 mobil.Install (c);
461
462 if ( scenario == 1 && enableRouting)
463 {
464 SelectSrcDest (c);
465 }
466 else if ( scenario == 2)
467 {
468 //All flows begin at the same time
469 for (uint32_t i = 0; i < nodeSize - 1; i = i + 2)
470 {
471 ApplicationSetup (c.Get (i), c.Get (i + 1), 0, totalTime);
472 }
473 }
474 else if ( scenario == 3)
475 {
476 AssignNeighbors (c);
477 //Note: these senders are hand-picked in order to ensure good coverage
478 //for 10x10 grid, basically one sender for each quadrant
479 //you might have to change these values for other grids
480 NS_LOG_DEBUG (">>>>>>>>>region A<<<<<<<<<");
481 SendMultiDestinations (c.Get (22), containerA);
482
483 NS_LOG_DEBUG (">>>>>>>>>region B<<<<<<<<<");
484 SendMultiDestinations (c.Get (26), containerB);
485
486 NS_LOG_DEBUG (">>>>>>>>>region C<<<<<<<<<");
487 SendMultiDestinations (c.Get (72), containerC);
488
489 NS_LOG_DEBUG (">>>>>>>>>region D<<<<<<<<<");
490 SendMultiDestinations (c.Get (76), containerD);
491 }
492 else if ( scenario == 4)
493 {
494 //GenerateNeighbors(NodeContainer, uint32_t sender)
495 //Note: these senders are hand-picked in order to ensure good coverage
496 //you might have to change these values for other grids
497 NodeContainer c1, c2, c3, c4, c5, c6, c7, c8, c9;
498
499 c1 = GenerateNeighbors (c, 22);
500 c2 = GenerateNeighbors (c, 24);
501 c3 = GenerateNeighbors (c, 26);
502 c4 = GenerateNeighbors (c, 42);
503 c5 = GenerateNeighbors (c, 44);
504 c6 = GenerateNeighbors (c, 46);
505 c7 = GenerateNeighbors (c, 62);
506 c8 = GenerateNeighbors (c, 64);
507 c9 = GenerateNeighbors (c, 66);
508
509 SendMultiDestinations (c.Get (22), c1);
510 SendMultiDestinations (c.Get (24), c2);
511 SendMultiDestinations (c.Get (26), c3);
512 SendMultiDestinations (c.Get (42), c4);
513 SendMultiDestinations (c.Get (44), c5);
514 SendMultiDestinations (c.Get (46), c6);
515 SendMultiDestinations (c.Get (62), c7);
516 SendMultiDestinations (c.Get (64), c8);
517 SendMultiDestinations (c.Get (66), c9);
518 }
519
520 CheckThroughput ();
521
522 if (enablePcap)
523 {
524 phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
525 phy.EnablePcapAll (GetOutputFileName ());
526 }
527
528 if (enableTracing)
529 {
530 AsciiTraceHelper ascii;
531 phy.EnableAsciiAll (ascii.CreateFileStream (GetOutputFileName () + ".tr"));
532 }
533
534 FlowMonitorHelper flowmonHelper;
535
536 if (enableFlowMon)
537 {
538 flowmonHelper.InstallAll ();
539 }
540
541 Simulator::Stop (Seconds (totalTime));
542 Simulator::Run ();
543
544 if (enableFlowMon)
545 {
546 flowmonHelper.SerializeToXmlFile ((GetOutputFileName () + ".flomon"), false, false);
547 }
548
549 Simulator::Destroy ();
550
551 return m_output;
552 }
553
554 bool
CommandSetup(int argc,char ** argv)555 Experiment::CommandSetup (int argc, char **argv)
556 {
557 // for commandline input
558 CommandLine cmd (__FILE__);
559 cmd.AddValue ("packetSize", "packet size", packetSize);
560 cmd.AddValue ("totalTime", "simulation time", totalTime);
561 // according to totalTime, select an appropriate samplingPeriod automatically.
562 if (totalTime < 1.0)
563 {
564 samplingPeriod = 0.1;
565 }
566 else
567 {
568 samplingPeriod = 1.0;
569 }
570 // or user selects a samplingPeriod.
571 cmd.AddValue ("samplingPeriod", "sampling period", samplingPeriod);
572 cmd.AddValue ("rtsThreshold", "rts threshold", rtsThreshold);
573 cmd.AddValue ("rateManager", "type of rate", rateManager);
574 cmd.AddValue ("outputFileName", "output filename", outputFileName);
575 cmd.AddValue ("enableRouting", "enable Routing", enableRouting);
576 cmd.AddValue ("enableMobility", "enable Mobility", enableMobility);
577 cmd.AddValue ("scenario", "scenario ", scenario);
578
579 cmd.Parse (argc, argv);
580 return true;
581 }
582
main(int argc,char * argv[])583 int main (int argc, char *argv[])
584 {
585
586 Experiment experiment;
587 experiment = Experiment ("multirate");
588
589 //for commandline input
590 experiment.CommandSetup (argc, argv);
591
592 std::ofstream outfile ((experiment.GetOutputFileName () + ".plt").c_str ());
593
594 MobilityHelper mobility;
595 Gnuplot gnuplot;
596 Gnuplot2dDataset dataset;
597
598 WifiHelper wifi;
599 WifiMacHelper wifiMac;
600 YansWifiPhyHelper wifiPhy;
601 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
602
603 wifiMac.SetType ("ns3::AdhocWifiMac",
604 "Ssid", StringValue ("Testbed"));
605 wifi.SetStandard (WIFI_STANDARD_80211a);
606 wifi.SetRemoteStationManager (experiment.GetRateManager ());
607
608 NS_LOG_INFO ("Scenario: " << experiment.GetScenario ());
609 NS_LOG_INFO ("Rts Threshold: " << experiment.GetRtsThreshold ());
610 NS_LOG_INFO ("Name: " << experiment.GetOutputFileName ());
611 NS_LOG_INFO ("Rate: " << experiment.GetRateManager ());
612 NS_LOG_INFO ("Routing: " << experiment.IsRouting ());
613 NS_LOG_INFO ("Mobility: " << experiment.IsMobility ());
614
615 dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
616
617 gnuplot.AddDataset (dataset);
618 gnuplot.GenerateOutput (outfile);
619
620 return 0;
621 }
622