examples/multirate.cc
changeset 5256 7bd503be20c9
child 5266 dd5b22749a78
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/multirate.cc	Fri Sep 25 14:38:12 2009 -0700
@@ -0,0 +1,523 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Duy Nguyen <duy@soe.ucsc.edu>
+ */
+
+/**
+ * Objective: Test multi-rate algorithms in varios scenarios and settings
+ *
+ * INSTRUCTIONS:
+ *
+ * To compile:
+ * ./waf --run multirate
+ *
+ * To compile with command input:
+ * ./waf --run "scratch/multirate.cc --packetSize=2000 --totalTime=50"
+ *
+ * To turn on NS_LOG:
+ * export NS_LOG=multirate=level_all
+ *
+ * To debug:
+ * /waf --shell
+ * gdb ./build/debug/scratch/multirate
+ *
+ * To view pcap files:
+ * tcpdump -nn -tt -r filename.pcap
+ *
+ * Sidenote: Simulation might take sometime
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/contrib-module.h"
+#include "ns3/random-variable.h"
+#include "ns3/wifi-module.h"
+
+#include <iostream>
+#include <fstream>
+
+NS_LOG_COMPONENT_DEFINE ("multirate");
+
+using namespace ns3;
+
+class Experiment
+{
+
+public:
+
+  Experiment ();
+  Experiment (std::string name);
+  Gnuplot2dDataset Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                        const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility);
+  bool CommandSetup (int argc, char **argv);
+
+private:
+
+  Vector GetPosition (Ptr<Node> node);
+  Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
+
+  void ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop);
+  void AssignNeighbors (NodeContainer c);
+  void SelectSrcDest (NodeContainer c);
+  void ReceivePacket (Ptr<Socket> socket);
+  void CheckThroughput ();
+  void SendMultiDestinations(Ptr<Node> sender, NodeContainer c);
+
+  Gnuplot2dDataset m_output;
+
+  uint32_t m_bytesTotal;
+  uint32_t packetSize;
+  uint32_t gridSize; 
+  uint32_t nodeDistance;
+  uint32_t port;
+  uint32_t expMean;
+
+  double totalTime; 
+
+  bool enablePcap;
+  bool enableTracing;
+  bool enableFlowMon;
+  bool enableRouting;
+  bool enableMobility;
+
+  NodeContainer containerA, containerB, containerC, containerD; 
+};
+
+Experiment::Experiment ()
+{}
+
+Experiment::Experiment (std::string name) : 
+  m_output (name),
+  m_bytesTotal(0),
+  packetSize (2000),
+  gridSize (10), //10x10 grid  for a total of 100 nodes
+  nodeDistance (40),
+  port (5000),
+  expMean (4), //flows being exponentially distributed
+  totalTime (50),
+  enablePcap(false), // will flood the directory with *.pcap files
+  enableTracing(false),
+  enableFlowMon(true),
+  enableRouting(false),
+  enableMobility(false)
+{
+  m_output.SetStyle (Gnuplot2dDataset::LINES);
+}
+
+Ptr<Socket>
+Experiment::SetupPacketReceive (Ptr<Node> node)
+{
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> sink = Socket::CreateSocket (node, tid);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), port);
+  sink->Bind (local);
+  sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
+
+  return sink;
+}
+
+void
+Experiment::ReceivePacket (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+  {
+    m_bytesTotal += packet->GetSize();
+  }
+}
+
+void
+Experiment::CheckThroughput()
+{
+  double mbs = ((m_bytesTotal * 8.0) /1000000);
+  m_bytesTotal = 0;
+  m_output.Add ((Simulator::Now ()).GetSeconds (), mbs);
+
+  Simulator::Schedule (Seconds (1.0), &Experiment::CheckThroughput, this);
+}
+
+Vector
+Experiment::GetPosition (Ptr<Node> node)
+{
+  Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+  return mobility->GetPosition ();
+}
+
+/**
+ *
+ * Take the grid map, divide it into 4 quadrants
+ * Assign all nodes from each quadrant to a specific container 
+ * 
+ */
+void
+Experiment::AssignNeighbors (NodeContainer c)
+{
+  uint32_t totalNodes = c.GetN ();
+  for (uint32_t i=0; i< totalNodes; i++)
+    {
+      if ( (i % gridSize) <= (gridSize/2 - 1))
+        {
+          //lower left quadrant
+	  if ( i < totalNodes/2 )
+	    {
+	      containerA.Add(c.Get(i));
+            }
+      
+          //upper left quadrant
+          if ( i >= (uint32_t)(4*totalNodes)/10 )
+	    {
+	      containerC.Add(c.Get(i));  
+            }
+	}
+      if ( (i % gridSize) >= (gridSize/2 - 1))
+        {
+          //lower right quadrant
+	  if ( i < totalNodes/2 )
+	    {
+	      containerB.Add(c.Get(i));  
+            }
+
+          //upper right quadrant
+          if ( i >= (uint32_t)(4*totalNodes)/10  )
+	    {
+	      containerD.Add(c.Get(i));  
+            }
+	}
+    }
+}
+
+/**
+ * Sources and destinations are randomly selected such that a node 
+ * may be the source for multiple destinations and a node maybe a destination 
+ * for multiple sources. 
+ */
+void
+Experiment::SelectSrcDest (NodeContainer c)
+{
+  uint32_t totalNodes = c.GetN();
+  UniformVariable uvSrc (0, totalNodes/2 -1);
+  UniformVariable uvDest (totalNodes/2, totalNodes);
+
+  for (uint32_t i=0; i < totalNodes/3; i++)
+    {
+      ApplicationSetup (c.Get(uvSrc.GetValue()), c.Get(uvDest.GetValue()) ,  1, totalTime);
+    }
+}
+
+/**
+ *
+ * A sender node will  set up a flow to each of the its neighbors
+ * in its quadrant randomly.  All the flows are exponentially distributed
+ *
+ */
+void
+Experiment::SendMultiDestinations(Ptr<Node> sender, NodeContainer c)
+{
+
+  // UniformVariable params: (Xrange, Yrange)
+  UniformVariable uv(0, c.GetN ());
+
+  // ExponentialVariable params: (mean, upperbound)
+  ExponentialVariable ev(expMean, totalTime);
+
+  double start=1, stop=totalTime;
+  uint32_t destIndex; 
+
+  for (uint32_t i=0; i < c.GetN (); i++)
+    {
+      stop = start + ev.GetValue();
+      NS_LOG_DEBUG("Start=" << start << " Stop=" << stop);
+
+      do {
+          destIndex = (uint32_t) uv.GetValue();
+      } while ( (c.Get(destIndex))->GetId () == sender->GetId ());
+      
+      ApplicationSetup (sender, c.Get(destIndex) ,  start, stop);
+
+      start = stop;
+
+      if(start > totalTime) 
+        {
+          break;
+        }
+    }
+}
+
+void
+Experiment::ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop)
+{
+
+  Vector serverPos = GetPosition (server);
+  Vector clientPos = GetPosition (client);
+
+  Ptr<Ipv4> ipv4Server = server->GetObject<Ipv4>();
+  Ptr<Ipv4> ipv4Client = client->GetObject<Ipv4>();
+
+  Ipv4InterfaceAddress iaddrServer = ipv4Server->GetAddress(1,0);
+  Ipv4InterfaceAddress iaddrClient = ipv4Client->GetAddress(1,0);
+
+  Ipv4Address ipv4AddrServer = iaddrServer.GetLocal ();
+  Ipv4Address ipv4AddrClient = iaddrClient.GetLocal ();
+
+  NS_LOG_DEBUG("Set up Server Device " <<  (server->GetDevice(0))->GetAddress () 
+            << " with ip " << ipv4AddrServer 
+            << " position (" << serverPos.x << "," << serverPos.y << "," << serverPos.z << ")");
+
+  NS_LOG_DEBUG("Set up Client Device " <<  (client->GetDevice(0))->GetAddress () 
+            << " with ip " << ipv4AddrClient 
+            << " position (" << clientPos.x << "," << clientPos.y << "," << clientPos.z << ")"
+            << "\n");
+
+   
+  // Equipping the source  node with OnOff Application used for sending 
+  OnOffHelper onoff ("ns3::UdpSocketFactory", Address(InetSocketAddress(Ipv4Address("10.0.0.1"), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (60000000)));
+  onoff.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  onoff.SetAttribute ("Remote", AddressValue(InetSocketAddress (ipv4AddrServer, port)));
+
+  ApplicationContainer apps = onoff.Install (client);
+  apps.Start (Seconds (start));
+  apps.Stop (Seconds (stop));
+
+
+
+/*
+  // Select either Sink Method 1 or 2 for setting up sink
+  // one using a helper vs one without
+  // Sink: Method 1
+  Address sinkAddr(InetSocketAddress (Ipv4Address::GetAny (), port));
+  PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkAddr);
+  ApplicationContainer sinkApp = sinkHelper.Install (server);
+  sinkApp.Start (Seconds (start));
+  sinkApp.Stop (Seconds (stop));
+*/
+
+  // Sink: Method 2
+  Ptr<Socket> sink = SetupPacketReceive (server);
+
+}
+
+Gnuplot2dDataset
+Experiment::Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                 const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility)
+{
+
+
+  uint32_t nodeSize = gridSize*gridSize;
+  NodeContainer c;
+  c.Create (nodeSize);
+
+  YansWifiPhyHelper phy = wifiPhy;
+  phy.SetChannel (wifiChannel.Create ());
+
+  NqosWifiMacHelper mac = wifiMac;
+  NetDeviceContainer devices = wifi.Install (phy, mac, c);
+
+
+  OlsrHelper olsr;
+  Ipv4StaticRoutingHelper staticRouting;
+
+  Ipv4ListRoutingHelper list;
+  
+  if (enableRouting)
+    {
+      list.Add (staticRouting, 0);
+      list.Add (olsr, 10);
+    }
+
+  InternetStackHelper internet;
+
+  if (enableRouting)
+    {
+      internet.SetRoutingHelper(list);
+    }
+  internet.Install (c);
+
+
+  Ipv4AddressHelper address;
+  address.SetBase ("10.0.0.0", "255.255.255.0");
+
+  Ipv4InterfaceContainer ipInterfaces;
+  ipInterfaces = address.Assign(devices);
+  
+  MobilityHelper mobil= mobility;
+  mobil.SetPositionAllocator ("ns3::GridPositionAllocator",
+                                "MinX", DoubleValue (0.0),
+                                "MinY", DoubleValue (0.0),
+                                "DeltaX", DoubleValue (nodeDistance),
+                                "DeltaY", DoubleValue (nodeDistance),
+                                "GridWidth", UintegerValue (gridSize),
+                                "LayoutType", StringValue ("RowFirst"));
+
+  mobil.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+
+  if (enableMobility && enableRouting)
+    {
+      //Rectangle (xMin, xMax, yMin, yMax)
+      mobil.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
+                              "Bounds", RectangleValue (Rectangle (0, 500, 0, 500)),
+                              "Speed", RandomVariableValue (ConstantVariable (10)),
+                              "Pause", RandomVariableValue (ConstantVariable (0.2)));
+    }
+  mobil.Install (c);
+
+
+
+  if (enableRouting)
+    {
+      SelectSrcDest(c);
+
+/*
+      //another setup
+      //All flows begin at the same time
+      for (uint32_t i = 0,j = 0; i < nodeSize - 1; i = i+2)
+        {
+          NS_LOG_DEBUG("Flow " << ++j);
+          ApplicationSetup (c.Get (i), c.Get (i+1),  1, totalTime);
+        }
+*/
+
+//    NS_LOG_INFO ("Enabling global routing on all nodes");
+//    Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+    }
+  else
+    {
+      AssignNeighbors(c);
+
+      //Note: these senders are hand-picked in order to ensure good coverage
+      //for 10x10 grid, basically one sender for each quadrant
+      //you might have to change these values for other grids 
+      NS_LOG_DEBUG(">>>>>>>>>region A<<<<<<<<<");
+      SendMultiDestinations(c.Get(22), containerA);
+
+      NS_LOG_DEBUG(">>>>>>>>>region B<<<<<<<<<");
+      SendMultiDestinations(c.Get(26), containerB);
+
+      NS_LOG_DEBUG(">>>>>>>>>region C<<<<<<<<<");
+      SendMultiDestinations(c.Get(72), containerC);
+
+      NS_LOG_DEBUG(">>>>>>>>>region D<<<<<<<<<");
+      SendMultiDestinations(c.Get(76), containerD);
+    }
+
+
+  CheckThroughput ();
+
+  if (enablePcap)
+    {
+      phy.EnablePcapAll("multirate");
+    }
+
+  if (enableTracing)
+    {
+      std::ofstream ascii;
+      ascii.open ("multirate.tr");
+      phy.EnableAsciiAll (ascii);
+    }
+
+  Ptr<FlowMonitor> flowmon;
+
+  if (enableFlowMon)
+    {
+      FlowMonitorHelper flowmonHelper;
+      flowmon = flowmonHelper.InstallAll ();
+    }
+
+  Simulator::Stop (Seconds (totalTime));
+  Simulator::Run ();
+
+  if (enableFlowMon)
+    {
+      flowmon->SerializeToXmlFile ("multirate.flowmon", false, false);
+    }
+
+  Simulator::Destroy ();
+  
+  return m_output;
+}
+
+bool
+Experiment::CommandSetup (int argc, char **argv)
+{
+  // for commandline input
+  CommandLine cmd;
+  cmd.AddValue ("packetSize", "packet size", packetSize);
+  cmd.AddValue ("totalTime", "simulation time", totalTime);
+
+  cmd.Parse (argc, argv);
+  return true;
+}
+
+int main (int argc, char *argv[])
+{
+  std::ofstream outfile ("multirate.plt");
+
+  // disable fragmentation
+  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
+ 
+  //set value to 0 for enabling RTS/CTS
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+
+  MobilityHelper mobility;
+  Experiment experiment;
+
+  Gnuplot gnuplot;
+  Gnuplot2dDataset dataset;
+
+  WifiHelper wifi = WifiHelper::Default ();
+  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+  YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+  Ssid ssid = Ssid ("Testbed");
+  
+
+  wifiMac.SetType ("ns3::AdhocWifiMac", "Ssid", SsidValue(ssid));
+  wifi.SetStandard (WIFI_PHY_STANDARD_holland);
+
+
+
+  //To ensure repeatable experiment scenario
+  //for each multirate, please uncomment one at a time and obtain results 
+  experiment = Experiment ("minstrel");
+  //experiment = Experiment ("ideal");
+
+  //for commandline input
+  if (!experiment.CommandSetup(argc, argv))
+    {
+      std::cout << "exiting ..." << std::endl;
+      exit(1);
+    }
+
+  wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
+  gnuplot.AddDataset (dataset);
+
+  /*
+  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
+  gnuplot.AddDataset (dataset);
+  */
+
+  gnuplot.GenerateOutput (outfile);
+
+  return 0;
+}