--- /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;
+}