Index: examples/uan/uan-rc-example.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/examples/uan/uan-rc-example.cc |
@@ -0,0 +1,304 @@ |
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) 2009 University of Washington |
+ * |
+ * 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: Leonard Tracy <lentracy@gmail.com> |
+ */ |
+ |
+/** |
+ * \file uan-rc-example.cc |
+ * \ingroup UAN |
+ * This example uses UanMacRc and UanMacRcGw which combined form a system |
+ * using what is reffered to as RC-MAC. Details of RC-MAC will be published |
+ * soon. In brief terms, RC-MAC is a dual channel protocol wherein the |
+ * available bandwidth is dynamically divided into two channels, |
+ * a reservation channel and a data channel. The network is assumed |
+ * to consist of a single gateway node which services several |
+ * non-gateway nodes. |
+ * |
+ * Time is divided into cycles. The non-gateway nodes transmit RTS packets |
+ * on the reservation channel in parallel to scheduled data transmissions |
+ * (scheduled in the previous cycle), and the gateway stores these requests |
+ * for the duration of the cycle. At the start of the next cycle |
+ * the gateway node transmits a CTS which contains packet transmission times |
+ * for reserved packets as well as bandwidth allocation information |
+ * |
+ * This script deploys a single gateway node (current UanMacRc only supports |
+ * a single gateway) in the center of a region and then distributes |
+ * non-gateway nodes around the gateway with a uniformly distributed range |
+ * between each node and the gateway. |
+ * |
+ * The script supports two simulation types. By default the gateway |
+ * dynamically determines the optimal parameter settings and |
+ * simulations are run with varying number of nodes (SimMin to SimMax as |
+ * set by the command line). If DoNode=0 is given as a command line option |
+ * then the mac parameter "a" (approximate expected number of successful |
+ * RTS arrivals per cycle) is varied as the simulation parameter. |
+ * |
+ * For questions about this MAC protocol email "lentracy@gmail.com" |
+ */ |
+ |
+#include "uan-rc-example.h" |
+#include "ns3/core-module.h" |
+#include "ns3/common-module.h" |
+#include "ns3/uan-module.h" |
+#include "ns3/helper-module.h" |
+#include "ns3/mobility-module.h" |
+#include "ns3/node-module.h" |
+#include "ns3/log.h" |
+#include "ns3/config.h" |
+#include "ns3/callback.h" |
+#include "ns3/contrib-module.h" |
+ |
+#include <fstream> |
+ |
+using namespace ns3; |
+ |
+NS_LOG_COMPONENT_DEFINE ("UanRcExample"); |
+ |
+ |
+Experiment::Experiment () |
+ : m_simMin (1), |
+ m_simMax (1), |
+ m_simStep (1), |
+ m_numRates (1023), |
+ m_totalRate (4096), |
+ m_maxRange (3000), |
+ m_numNodes (15), |
+ m_pktSize (1000), |
+ m_doNode (true), |
+ m_sifs (Seconds (0.05)), |
+ m_simTime (Seconds (5000)), |
+ m_gnuplotfile ("uan-rc-example.gpl"), |
+ m_bytesTotal (0) |
+{ |
+} |
+ |
+void |
+Experiment::ReceivePacket (Ptr<Socket> socket) |
+{ |
+ Ptr<Packet> packet; |
+ while (packet = socket->Recv ()) |
+ { |
+ m_bytesTotal += packet->GetSize (); |
+ } |
+} |
+ |
+UanTxMode |
+Experiment::CreateMode (uint32_t kass, |
+ uint32_t fc, |
+ bool upperblock, |
+ std::string name) |
+{ |
+ |
+ std::ostringstream buf; |
+ buf << name << " " << kass; |
+ |
+ uint32_t rate = m_totalRate/(m_numRates+1)* (kass); |
+ uint32_t bw = kass * m_totalRate / (m_numRates+1); |
+ uint32_t fcmode; |
+ if(upperblock) |
+ fcmode = (m_totalRate - bw)/2 + fc; |
+ else |
+ fcmode = (uint32_t) ((-((double) m_totalRate ) + (double) bw)/2.0 + (double) fc); |
+ |
+ |
+ uint32_t phyrate = m_totalRate; |
+ |
+ UanTxMode mode; |
+ mode = UanTxModeFactory::CreateMode (UanTxMode::OTHER, |
+ rate, |
+ phyrate, |
+ fcmode, |
+ bw, |
+ 2, |
+ buf.str()); |
+ return mode; |
+} |
+ |
+//Creates m_numRates different modes each dividing m_totalRate Hz (assumes 1 bit per hz) |
+//centered at frequency fc |
+void |
+Experiment::CreateDualModes (uint32_t fc) |
+{ |
+ |
+ |
+ for (uint32_t i=1;i < m_numRates+1; i++) |
+ { |
+ m_controlModes.AppendMode (CreateMode (i, fc, false, "control ")); |
+ } |
+ for (uint32_t i=m_numRates; i > 0; i--) |
+ { |
+ m_dataModes.AppendMode (CreateMode (i, fc, true, "data ")); |
+ } |
+} |
+ |
+uint32_t |
+Experiment::Run (UanHelper &uan, uint32_t param) |
+{ |
+ |
+ m_bytesTotal=0; |
+ |
+ uint32_t nNodes; |
+ uint32_t a; |
+ if(m_doNode) |
+ { |
+ a=0; |
+ nNodes = param; |
+ } |
+ else |
+ { |
+ nNodes = m_numNodes; |
+ a = param; |
+ } |
+ Time pDelay = Seconds((double) m_maxRange / 1500.0); |
+ |
+ uan.SetMac ("ns3::UanMacRcGw", |
+ "NumberOfRates", UintegerValue (m_numRates), |
+ "NumberOfNodes", UintegerValue (nNodes), |
+ "MaxReservations", UintegerValue (a), |
+ "RetryRate", DoubleValue(1/30.0), |
+ "SIFS", TimeValue (m_sifs), |
+ "MaxPropDelay", TimeValue (pDelay), |
+ "FrameSize", UintegerValue (m_pktSize)); |
+ Ptr<UanChannel> chan = CreateObject<UanChannel>(); |
+ |
+ NodeContainer sink; |
+ sink.Create(1); |
+ NetDeviceContainer sinkDev = uan.Install(sink, chan); |
+ |
+ uan.SetMac ("ns3::UanMacRc", |
+ "NumberOfRates", UintegerValue (m_numRates), |
+ "MaxPropDelay", TimeValue (pDelay), |
+ "RetryRate", DoubleValue(1.0/100.0)); |
+ NodeContainer nodes; |
+ nodes.Create (nNodes); |
+ NetDeviceContainer devices = uan.Install (nodes, chan); |
+ |
+ MobilityHelper mobility; |
+ uint32_t depth = 70; |
+ Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> (); |
+ |
+ UniformVariable urv (0,m_maxRange); |
+ UniformVariable utheta (0, 2.0*M_PI); |
+ pos->Add (Vector (m_maxRange, m_maxRange, depth)); |
+ |
+ for (uint32_t i=0;i<nNodes;i++) |
+ { |
+ double theta = utheta.GetValue (); |
+ double r = urv.GetValue (); |
+ |
+ double x = m_maxRange + r*std::cos (theta); |
+ double y = m_maxRange + r*std::sin (theta); |
+ |
+ pos->Add (Vector (x, y, depth)); |
+ |
+ } |
+ |
+ mobility.SetPositionAllocator (pos); |
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); |
+ mobility.Install (sink); |
+ mobility.Install (nodes); |
+ |
+ PacketSocketHelper pktskth; |
+ pktskth.Install (nodes); |
+ pktskth.Install (sink); |
+ |
+ PacketSocketAddress socket; |
+ socket.SetSingleDevice (sinkDev.Get(0)->GetIfIndex ()); |
+ socket.SetPhysicalAddress (sinkDev.Get(0)->GetAddress ()); |
+ socket.SetProtocol (0); |
+ |
+ OnOffHelper app ("ns3::PacketSocketFactory", Address (socket)); |
+ app.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1))); |
+ app.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); |
+ app.SetAttribute ("DataRate", DataRateValue (m_totalRate)); |
+ app.SetAttribute ("PacketSize", UintegerValue (m_pktSize)); |
+ |
+ ApplicationContainer apps = app.Install (nodes); |
+ |
+ apps.Start (Seconds (0.5)); |
+ apps.Stop (m_simTime + Seconds(0.5)); |
+ |
+ Ptr<Node> sinkNode = sink.Get (0); |
+ TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory"); |
+ |
+ Ptr<Socket> sinkSocket = Socket::CreateSocket(sinkNode, psfid); |
+ sinkSocket->Bind(socket); |
+ sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this)); |
+ |
+ Simulator::Stop (m_simTime + Seconds(0.6)); |
+ Simulator::Run (); |
+ Simulator::Destroy (); |
+ |
+ chan = Ptr<UanChannel> ((UanChannel *) 0); |
+ return m_bytesTotal; |
+} |
+int |
+main(int argc, char *argv[]) |
+{ |
+ |
+ LogComponentEnable ("UanRcExample", LOG_LEVEL_ALL); |
+ |
+ Experiment exp; |
+ |
+ CommandLine cmd; |
+ cmd.AddValue ("TotalRate", "Total channel capacity", exp.m_totalRate); |
+ cmd.AddValue ("NumberRates", "Number of divided rates ( (NumberRates+1)%TotalRate should be 0)", exp.m_numRates); |
+ cmd.AddValue ("MaxRange", "Maximum range between gateway and acoustic node", exp.m_maxRange); |
+ cmd.AddValue ("SimMin", "Minimum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMin); |
+ cmd.AddValue ("SimMax", "Maximum parameter to test (nodes if DoNode=1, \"a\" param otherwise)", exp.m_simMax); |
+ cmd.AddValue ("SimStep", "Ammount to increment param per trial", exp.m_simStep); |
+ cmd.AddValue ("DataFile", "Filename for GnuPlot", exp.m_gnuplotfile); |
+ cmd.AddValue ("NumberNodes", "Number of nodes (invalid for doNode=1)", exp.m_numNodes); |
+ cmd.AddValue ("SIFS", "SIFS time duration", exp.m_sifs); |
+ cmd.AddValue ("PktSize", "Packet size in bytes", exp.m_pktSize); |
+ cmd.AddValue ("SimTime", "Simulation time per trial", exp.m_simTime); |
+ cmd.AddValue ("DoNode", "1 for do max nodes simulation (invalidates AMin and AMax values)", exp.m_doNode); |
+ cmd.Parse (argc, argv); |
+ |
+ |
+ |
+ exp.CreateDualModes (12000); |
+ |
+ UanHelper uan; |
+ uan.SetPhy ("ns3::UanPhyDual", |
+ "SupportedModesPhy1", UanModesListValue (exp.m_dataModes), |
+ "SupportedModesPhy2", UanModesListValue (exp.m_controlModes)); |
+ |
+ Gnuplot2dDataset ds; |
+ for (uint32_t param=exp.m_simMin; param<=exp.m_simMax; param += exp.m_simStep) |
+ { |
+ uint32_t bytesRx = exp.Run (uan, param); |
+ NS_LOG_DEBUG ("param=" << param << ": Received " << bytesRx << " bytes at sink"); |
+ |
+ double util = bytesRx*8.0/(exp.m_simTime.GetSeconds ()*exp.m_totalRate); |
+ |
+ ds.Add (param, util); |
+ |
+ SeedManager::SetRun (SeedManager::GetRun () + 1); |
+ } |
+ |
+ Gnuplot gp; |
+ gp.AddDataset (ds); |
+ std::ofstream of (exp.m_gnuplotfile.c_str ()); |
+ if (!of.is_open ()) |
+ { |
+ NS_FATAL_ERROR ("Can not open GNU Plot outfile: " << exp.m_gnuplotfile); |
+ } |
+ gp.GenerateOutput (of); |
+ |
+} |