--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wireless/power-adaptation-distance.cc Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,472 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+
+/**
+ * This example program is designed to illustrate the behavior of two
+ * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager
+ * and ns3::AparfWifiManager.
+ *
+ * The output of this is typically two plot files, named throughput-parf.plt
+ * (or throughput-aparf.plt, if Aparf is used) and power-parf.plt If
+ * Gnuplot program is available, one can use it to convert the plt file
+ * into an eps file, by running:
+ * \code{.sh}
+ * gnuplot throughput-parf.plt
+ * \endcode
+ * Also, to enable logging of rate and power changes to the terminal, set this
+ * environment variable:
+ * \code{.sh}
+ * export NS_LOG=PowerAdaptationDistance=level_info
+ * \endcode
+ *
+ * This simulation consist of 2 nodes, one AP and one STA.
+ * The AP generates UDP traffic with a CBR of 54 Mbps to the STA.
+ * The AP can use any power and rate control mechanism and the STA uses
+ * only Minstrel rate control.
+ * The STA can be configured to move away from (or towards to) the AP.
+ * By default, the AP is at coordinate (0,0,0) and the STA starts at
+ * coordinate (5,0,0) (meters) and moves away on the x axis by 1 meter every
+ * second.
+ *
+ * The output consists of:
+ * - A plot of average throughput vs. distance.
+ * - A plot of average transmit power vs. distance.
+ * - (if logging is enabled) the changes of power and rate to standard output.
+ *
+ * The Average Transmit Power is defined as an average of the power
+ * consumed per measurement interval, expressed in milliwatts. The
+ * power level for each frame transmission is reported by the simulator,
+ * and the energy consumed is obtained by multiplying the power by the
+ * frame duration. At every 'stepTime' (defaulting to 1 second), the
+ * total energy for the collection period is divided by the step time
+ * and converted from dbm to milliwatt units, and this average is
+ * plotted against time.
+ *
+ * When neither Parf nor Aparf is selected as the rate control, the
+ * generation of the plot of average transmit power vs distance is suppressed
+ * since the other Wifi rate controls do not support the necessary callbacks
+ * for computing the average power.
+ *
+ * To display all the possible arguments and their defaults:
+ * \code{.sh}
+ * ./waf --run "power-adaptation-distance --help"
+ * \endcode
+ *
+ * Example usage (selecting Aparf rather than Parf):
+ * \code{.sh}
+ * ./waf --run "power-adaptation-distance --manager=ns3::AparfWifiManager --outputFileName=aparf"
+ * \endcode
+ *
+ * Another example (moving towards the AP):
+ * \code{.sh}
+ * ./waf --run "power-adaptation-distance --manager=ns3::AparfWifiManager --outputFileName=aparf --stepsSize=-1 --STA1_x=200"
+ * \endcode
+ *
+ * To enable the log of rate and power changes:
+ * \code{.sh}
+ * export NS_LOG=PowerAdaptationDistance=level_info
+ * \endcode
+ */
+
+#include <sstream>
+#include <fstream>
+#include <math.h>
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/stats-module.h"
+#include "ns3/flow-monitor-module.h"
+
+using namespace ns3;
+using namespace std;
+
+NS_LOG_COMPONENT_DEFINE ("PowerAdaptationDistance");
+
+// packet size generated at the AP
+static const uint32_t packetSize = 1420;
+
+class NodeStatistics
+{
+public:
+ NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas);
+
+ void CheckStatistics (double time);
+
+ void PhyCallback (std::string path, Ptr<const Packet> packet);
+ void RxCallback (std::string path, Ptr<const Packet> packet, const Address &from);
+ void PowerCallback (std::string path, uint8_t power, Mac48Address dest);
+ void RateCallback (std::string path, uint32_t rate, Mac48Address dest);
+ void SetPosition (Ptr<Node> node, Vector position);
+ void AdvancePosition (Ptr<Node> node, int stepsSize, int stepsTime);
+ Vector GetPosition (Ptr<Node> node);
+
+ Gnuplot2dDataset GetDatafile ();
+ Gnuplot2dDataset GetPowerDatafile ();
+
+private:
+ typedef std::vector<std::pair<Time,WifiMode> > TxTime;
+ void SetupPhy (Ptr<WifiPhy> phy);
+ Time GetCalcTxTime (WifiMode mode);
+
+ std::map<Mac48Address, uint32_t> actualPower;
+ std::map<Mac48Address, WifiMode> actualMode;
+ uint32_t m_bytesTotal;
+ double totalEnergy;
+ double totalTime;
+ Ptr<WifiPhy> myPhy;
+ TxTime timeTable;
+ Gnuplot2dDataset m_output;
+ Gnuplot2dDataset m_output_power;
+};
+
+NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
+{
+ Ptr<NetDevice> device = aps.Get (0);
+ Ptr<WifiNetDevice> wifiDevice = DynamicCast<WifiNetDevice> (device);
+ Ptr<WifiPhy> phy = wifiDevice->GetPhy ();
+ myPhy = phy;
+ SetupPhy (phy);
+ for (uint32_t j = 0; j < stas.GetN (); j++)
+ {
+ Ptr<NetDevice> staDevice = stas.Get (j);
+ Ptr<WifiNetDevice> wifiStaDevice = DynamicCast<WifiNetDevice> (staDevice);
+ Mac48Address addr = wifiStaDevice->GetMac ()->GetAddress ();
+ actualPower[addr] = 17;
+ actualMode[addr] = phy->GetMode (0);
+ }
+ actualMode[Mac48Address ("ff:ff:ff:ff:ff:ff")] = phy->GetMode (0);
+ totalEnergy = 0;
+ totalTime = 0;
+ m_bytesTotal = 0;
+ m_output.SetTitle ("Throughput Mbits/s");
+ m_output_power.SetTitle ("Average Transmit Power");
+}
+
+void
+NodeStatistics::SetupPhy (Ptr<WifiPhy> phy)
+{
+ uint32_t nModes = phy->GetNModes ();
+ for (uint32_t i = 0; i < nModes; i++)
+ {
+ WifiMode mode = phy->GetMode (i);
+ WifiTxVector txVector;
+ txVector.SetMode (mode);
+ timeTable.push_back (std::make_pair (phy->CalculateTxDuration (packetSize, txVector, WIFI_PREAMBLE_LONG, phy->GetFrequency ()), mode));
+ }
+}
+
+Time
+NodeStatistics::GetCalcTxTime (WifiMode mode)
+{
+ for (TxTime::const_iterator i = timeTable.begin (); i != timeTable.end (); i++)
+ {
+ if (mode == i->second)
+ {
+ return i->first;
+ }
+ }
+ NS_ASSERT (false);
+ return Seconds (0);
+}
+
+void
+NodeStatistics::PhyCallback (std::string path, Ptr<const Packet> packet)
+{
+ WifiMacHeader head;
+ packet->PeekHeader (head);
+ Mac48Address dest = head.GetAddr1 ();
+
+ totalEnergy += actualPower[dest] * GetCalcTxTime (actualMode[dest]).GetSeconds ();
+ totalTime += GetCalcTxTime (actualMode[dest]).GetSeconds ();
+
+}
+
+void
+NodeStatistics::PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+{
+ double txPowerBaseDbm = myPhy->GetTxPowerStart ();
+ double txPowerEndDbm = myPhy->GetTxPowerEnd ();
+ uint32_t nTxPower = myPhy->GetNTxPower ();
+ double dbm;
+ if (nTxPower > 1)
+ {
+ dbm = txPowerBaseDbm + power * (txPowerEndDbm - txPowerBaseDbm) / (nTxPower - 1);
+ }
+ else
+ {
+ NS_ASSERT_MSG (txPowerBaseDbm == txPowerEndDbm, "cannot have TxPowerEnd != TxPowerStart with TxPowerLevels == 1");
+ dbm = txPowerBaseDbm;
+ }
+ actualPower[dest] = dbm;
+}
+
+void
+NodeStatistics::RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+{
+ actualMode[dest] = myPhy->GetMode (rate);
+}
+
+void
+NodeStatistics::RxCallback (std::string path, Ptr<const Packet> packet, const Address &from)
+{
+ m_bytesTotal += packet->GetSize ();
+}
+
+void
+NodeStatistics::CheckStatistics (double time)
+{
+
+}
+
+void
+NodeStatistics::SetPosition (Ptr<Node> node, Vector position)
+{
+ Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+ mobility->SetPosition (position);
+}
+
+Vector
+NodeStatistics::GetPosition (Ptr<Node> node)
+{
+ Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+ return mobility->GetPosition ();
+}
+
+void
+NodeStatistics::AdvancePosition (Ptr<Node> node, int stepsSize, int stepsTime)
+{
+ Vector pos = GetPosition (node);
+ double mbs = ((m_bytesTotal * 8.0) / (1000000 * stepsTime));
+ m_bytesTotal = 0;
+ double atm = pow (10, ((totalEnergy / stepsTime) / 10));
+ totalEnergy = 0;
+ totalTime = 0;
+ m_output_power.Add (pos.x, atm);
+ m_output.Add (pos.x, mbs);
+ pos.x += stepsSize;
+ SetPosition (node, pos);
+ NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds () << " sec; setting new position to " << pos);
+ Simulator::Schedule (Seconds (stepsTime), &NodeStatistics::AdvancePosition, this, node, stepsSize, stepsTime);
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetDatafile ()
+{
+ return m_output;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetPowerDatafile ()
+{
+ return m_output_power;
+}
+
+void PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+{
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Power " << (int)power);
+}
+
+void RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+{
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Rate " << rate);
+}
+
+int main (int argc, char *argv[])
+{
+ double maxPower = 17;
+ double minPower = 0;
+ uint32_t powerLevels = 18;
+
+ uint32_t rtsThreshold = 2346;
+ std::string manager = "ns3::ParfWifiManager";
+ std::string outputFileName = "parf";
+ int ap1_x = 0;
+ int ap1_y = 0;
+ int sta1_x = 5;
+ int sta1_y = 0;
+ uint32_t steps = 200;
+ uint32_t stepsSize = 1;
+ uint32_t stepsTime = 1;
+
+ CommandLine cmd;
+ cmd.AddValue ("manager", "PRC Manager", manager);
+ cmd.AddValue ("rtsThreshold", "RTS threshold", rtsThreshold);
+ cmd.AddValue ("outputFileName", "Output filename", outputFileName);
+ cmd.AddValue ("steps", "How many different distances to try", steps);
+ cmd.AddValue ("stepsTime", "Time on each step", stepsTime);
+ cmd.AddValue ("stepsSize", "Distance between steps", stepsSize);
+ cmd.AddValue ("maxPower", "Maximum available transmission level (dbm).", maxPower);
+ cmd.AddValue ("minPower", "Minimum available transmission level (dbm).", minPower);
+ cmd.AddValue ("powerLevels", "Number of transmission power levels available between "
+ "TxPowerStart and TxPowerEnd included.", powerLevels);
+ cmd.AddValue ("AP1_x", "Position of AP1 in x coordinate", ap1_x);
+ cmd.AddValue ("AP1_y", "Position of AP1 in y coordinate", ap1_y);
+ cmd.AddValue ("STA1_x", "Position of STA1 in x coordinate", sta1_x);
+ cmd.AddValue ("STA1_y", "Position of STA1 in y coordinate", sta1_y);
+ cmd.Parse (argc, argv);
+
+ if (steps == 0)
+ {
+ std::cout << "Exiting without running simulation; steps value of 0" << std::endl;
+ }
+
+ uint32_t simuTime = (steps + 1) * stepsTime;
+
+ // Define the APs
+ NodeContainer wifiApNodes;
+ wifiApNodes.Create (1);
+
+ //Define the STAs
+ NodeContainer wifiStaNodes;
+ wifiStaNodes.Create (1);
+
+ WifiHelper wifi = WifiHelper::Default ();
+ wifi.SetStandard (WIFI_PHY_STANDARD_80211a);
+ NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+
+ wifiPhy.SetChannel (wifiChannel.Create ());
+
+ NetDeviceContainer wifiApDevices;
+ NetDeviceContainer wifiStaDevices;
+ NetDeviceContainer wifiDevices;
+
+ //Configure the STA node
+ wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager", "RtsCtsThreshold", UintegerValue (rtsThreshold));
+ wifiPhy.Set ("TxPowerStart", DoubleValue (maxPower));
+ wifiPhy.Set ("TxPowerEnd", DoubleValue (maxPower));
+
+ Ssid ssid = Ssid ("AP");
+ wifiMac.SetType ("ns3::StaWifiMac",
+ "Ssid", SsidValue (ssid),
+ "ActiveProbing", BooleanValue (false));
+ wifiStaDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiStaNodes.Get (0)));
+
+ //Configure the AP node
+ wifi.SetRemoteStationManager (manager, "DefaultTxPowerLevel", UintegerValue (maxPower), "RtsCtsThreshold", UintegerValue (rtsThreshold));
+ wifiPhy.Set ("TxPowerStart", DoubleValue (minPower));
+ wifiPhy.Set ("TxPowerEnd", DoubleValue (maxPower));
+ wifiPhy.Set ("TxPowerLevels", UintegerValue (powerLevels));
+
+ ssid = Ssid ("AP");
+ wifiMac.SetType ("ns3::ApWifiMac",
+ "Ssid", SsidValue (ssid));
+ wifiApDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiApNodes.Get (0)));
+
+ wifiDevices.Add (wifiStaDevices);
+ wifiDevices.Add (wifiApDevices);
+
+ // Configure the mobility.
+ MobilityHelper mobility;
+ Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+ //Initial position of AP and STA
+ positionAlloc->Add (Vector (ap1_x, ap1_y, 0.0));
+ NS_LOG_INFO ("Setting initial AP position to " << Vector (ap1_x, ap1_y, 0.0));
+ positionAlloc->Add (Vector (sta1_x, sta1_y, 0.0));
+ NS_LOG_INFO ("Setting initial STA position to " << Vector (sta1_x, sta1_y, 0.0));
+ mobility.SetPositionAllocator (positionAlloc);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (wifiApNodes.Get (0));
+ mobility.Install (wifiStaNodes.Get (0));
+
+ //Statistics counter
+ NodeStatistics statistics = NodeStatistics (wifiApDevices, wifiStaDevices);
+
+ //Move the STA by stepsSize meters every stepsTime seconds
+ Simulator::Schedule (Seconds (0.5 + stepsTime), &NodeStatistics::AdvancePosition, &statistics, wifiStaNodes.Get (0), stepsSize, stepsTime);
+
+ //Configure the IP stack
+ InternetStackHelper stack;
+ stack.Install (wifiApNodes);
+ stack.Install (wifiStaNodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer i = address.Assign (wifiDevices);
+ Ipv4Address sinkAddress = i.GetAddress (0);
+ uint16_t port = 9;
+
+ //Configure the CBR generator
+ PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress, port));
+ ApplicationContainer apps_sink = sink.Install (wifiStaNodes.Get (0));
+
+ OnOffHelper onoff ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress, port));
+ onoff.SetConstantRate (DataRate ("54Mb/s"), packetSize);
+ onoff.SetAttribute ("StartTime", TimeValue (Seconds (0.5)));
+ onoff.SetAttribute ("StopTime", TimeValue (Seconds (simuTime)));
+ ApplicationContainer apps_source = onoff.Install (wifiApNodes.Get (0));
+
+ apps_sink.Start (Seconds (0.5));
+ apps_sink.Stop (Seconds (simuTime));
+
+ //------------------------------------------------------------
+ //-- Setup stats and data collection
+ //--------------------------------------------
+
+ //Register packet receptions to calculate throughput
+ Config::Connect ("/NodeList/1/ApplicationList/*/$ns3::PacketSink/Rx",
+ MakeCallback (&NodeStatistics::RxCallback, &statistics));
+
+ //Register power and rate changes to calculate the Average Transmit Power
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/PowerChange",
+ MakeCallback (&NodeStatistics::PowerCallback, &statistics));
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/RateChange",
+ MakeCallback (&NodeStatistics::RateCallback, &statistics));
+
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
+ MakeCallback (&NodeStatistics::PhyCallback, &statistics));
+
+ //Callbacks to print every change of power and rate
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/PowerChange",
+ MakeCallback (PowerCallback));
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/RateChange",
+ MakeCallback (RateCallback));
+
+ Simulator::Stop (Seconds (simuTime));
+ Simulator::Run ();
+
+ std::ofstream outfile (("throughput-" + outputFileName + ".plt").c_str ());
+ Gnuplot gnuplot = Gnuplot (("throughput-" + outputFileName + ".eps").c_str (), "Throughput");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Throughput (Mb/s)");
+ gnuplot.SetTitle ("Throughput (AP to STA) vs time");
+ gnuplot.AddDataset (statistics.GetDatafile ());
+ gnuplot.GenerateOutput (outfile);
+
+ if (manager.compare ("ns3::ParfWifiManager") == 0 ||
+ manager.compare ("ns3::AparfWifiManager") == 0)
+ {
+ std::ofstream outfile2 (("power-" + outputFileName + ".plt").c_str ());
+ gnuplot = Gnuplot (("power-" + outputFileName + ".eps").c_str (), "Average Transmit Power");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Power (mW)");
+ gnuplot.SetTitle ("Average transmit power (AP to STA) vs time");
+ gnuplot.AddDataset (statistics.GetPowerDatafile ());
+ gnuplot.GenerateOutput (outfile2);
+ }
+
+ Simulator::Destroy ();
+
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wireless/power-adaptation-interference.cc Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,671 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+
+/**
+ * This example program is designed to illustrate the behavior of two
+ * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager
+ * and ns3::AparfWifiManager.
+ *
+ * This simulation consist of 4 nodes, two APs and two STAs.
+ * The APs generates UDP traffic with a CBR of 54 Mbps to the STAs.
+ * The APa use any power and rate control mechanism, and the STAs use only
+ * Minstrel rate control.
+ * The STAs can be configured to be at any distance from the APs.
+ *
+ * The objective is to test power and rate control in the links with
+ * interference from the other link.
+ *
+ * The output consists of:
+ * - A plot of average throughput vs. time.
+ * - A plot of average transmit power vs. time.
+ * - Plots for the percentage of time the APs are in each MAC state (IDLE, TX, RX, BUSY)
+ * - If enabled, the changes of power and rate to standard output.
+ * - If enabled, the average throughput, delay, jitter and tx opportunity for the total simulation time.
+ *
+ * Example usage:
+ * \code{.sh}
+ * ./waf --run "power-adaptation-interference --manager=ns3::AparfWifiManager --outputFileName=aparf"
+ * \endcode
+ *
+ * Another example (changing STAs position):
+ * \code{.sh}
+ * ./waf --run "power-adaptation-interference --manager=ns3::AparfWifiManager --outputFileName=aparf --STA1_x=5 --STA2_x=205"
+ * \endcode
+ *
+ * To enable the log of rate and power changes:
+ * \code{.sh}
+ * export NS_LOG=PowerAdaptationInterference=level_info
+ * \endcode
+ */
+
+#include <sstream>
+#include <fstream>
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/stats-module.h"
+#include "ns3/flow-monitor-module.h"
+
+using namespace ns3;
+using namespace std;
+
+NS_LOG_COMPONENT_DEFINE ("PowerAdaptationInterference");
+
+// packet size generated at the AP
+static const uint32_t packetSize = 1420;
+
+class NodeStatistics
+{
+public:
+ NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas);
+
+ void CheckStatistics (double time);
+
+ void PhyCallback (std::string path, Ptr<const Packet> packet);
+ void RxCallback (std::string path, Ptr<const Packet> packet, const Address &from);
+ void PowerCallback (std::string path, uint8_t power, Mac48Address dest);
+ void RateCallback (std::string path, uint32_t rate, Mac48Address dest);
+ void StateCallback (std::string path, Time init, Time duration, enum WifiPhy::State state);
+
+ Gnuplot2dDataset GetDatafile ();
+ Gnuplot2dDataset GetPowerDatafile ();
+ Gnuplot2dDataset GetIdleDatafile ();
+ Gnuplot2dDataset GetBusyDatafile ();
+ Gnuplot2dDataset GetTxDatafile ();
+ Gnuplot2dDataset GetRxDatafile ();
+
+ double GetBusyTime ();
+
+private:
+ typedef std::vector<std::pair<Time,WifiMode> > TxTime;
+ void SetupPhy (Ptr<WifiPhy> phy);
+ Time GetCalcTxTime (WifiMode mode);
+
+ std::map<Mac48Address, uint32_t> actualPower;
+ std::map<Mac48Address, WifiMode> actualMode;
+ uint32_t m_bytesTotal;
+ double totalEnergy;
+ double totalTime;
+ double busyTime;
+ double idleTime;
+ double txTime;
+ double rxTime;
+ double totalBusyTime;
+ double totalIdleTime;
+ double totalTxTime;
+ double totalRxTime;
+ Ptr<WifiPhy> myPhy;
+ TxTime timeTable;
+ Gnuplot2dDataset m_output;
+ Gnuplot2dDataset m_output_power;
+ Gnuplot2dDataset m_output_idle;
+ Gnuplot2dDataset m_output_busy;
+ Gnuplot2dDataset m_output_rx;
+ Gnuplot2dDataset m_output_tx;
+};
+
+NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
+{
+ Ptr<NetDevice> device = aps.Get (0);
+ Ptr<WifiNetDevice> wifiDevice = DynamicCast<WifiNetDevice> (device);
+ Ptr<WifiPhy> phy = wifiDevice->GetPhy ();
+ myPhy = phy;
+ SetupPhy (phy);
+ for (uint32_t j = 0; j < stas.GetN (); j++)
+ {
+ Ptr<NetDevice> staDevice = stas.Get (j);
+ Ptr<WifiNetDevice> wifiStaDevice = DynamicCast<WifiNetDevice> (staDevice);
+ Mac48Address addr = wifiStaDevice->GetMac ()->GetAddress ();
+ actualPower[addr] = 17;
+ actualMode[addr] = phy->GetMode (0);
+ }
+ actualMode[Mac48Address ("ff:ff:ff:ff:ff:ff")] = phy->GetMode (0);
+ totalEnergy = 0;
+ totalTime = 0;
+ busyTime = 0;
+ idleTime = 0;
+ txTime = 0;
+ rxTime = 0;
+ totalBusyTime = 0;
+ totalIdleTime = 0;
+ totalTxTime = 0;
+ totalRxTime = 0;
+ m_bytesTotal = 0;
+ m_output.SetTitle ("Throughput Mbits/s");
+ m_output_idle.SetTitle ("Idle Time");
+ m_output_busy.SetTitle ("Busy Time");
+ m_output_rx.SetTitle ("RX Time");
+ m_output_tx.SetTitle ("TX Time");
+}
+
+void
+NodeStatistics::SetupPhy (Ptr<WifiPhy> phy)
+{
+ uint32_t nModes = phy->GetNModes ();
+ for (uint32_t i = 0; i < nModes; i++)
+ {
+ WifiMode mode = phy->GetMode (i);
+ WifiTxVector txVector;
+ txVector.SetMode (mode);
+ timeTable.push_back (std::make_pair (phy->CalculateTxDuration (packetSize, txVector, WIFI_PREAMBLE_LONG, phy->GetFrequency ()), mode));
+ }
+}
+
+Time
+NodeStatistics::GetCalcTxTime (WifiMode mode)
+{
+ for (TxTime::const_iterator i = timeTable.begin (); i != timeTable.end (); i++)
+ {
+ if (mode == i->second)
+ {
+ return i->first;
+ }
+ }
+ NS_ASSERT (false);
+ return Seconds (0);
+}
+
+void
+NodeStatistics::PhyCallback (std::string path, Ptr<const Packet> packet)
+{
+ WifiMacHeader head;
+ packet->PeekHeader (head);
+ Mac48Address dest = head.GetAddr1 ();
+
+ totalEnergy += actualPower[dest] * GetCalcTxTime (actualMode[dest]).GetSeconds ();
+ totalTime += GetCalcTxTime (actualMode[dest]).GetSeconds ();
+
+}
+
+void
+NodeStatistics::PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+{
+ double txPowerBaseDbm = myPhy->GetTxPowerStart ();
+ double txPowerEndDbm = myPhy->GetTxPowerEnd ();
+ uint32_t nTxPower = myPhy->GetNTxPower ();
+ double dbm;
+ if (nTxPower > 1)
+ {
+ dbm = txPowerBaseDbm + power * (txPowerEndDbm - txPowerBaseDbm) / (nTxPower - 1);
+ }
+ else
+ {
+ NS_ASSERT_MSG (txPowerBaseDbm == txPowerEndDbm, "cannot have TxPowerEnd != TxPowerStart with TxPowerLevels == 1");
+ dbm = txPowerBaseDbm;
+ }
+ actualPower[dest] = dbm;
+}
+
+void
+NodeStatistics::RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+{
+ actualMode[dest] = myPhy->GetMode (rate);
+}
+
+void
+NodeStatistics::StateCallback (std::string path, Time init, Time duration, enum WifiPhy::State state)
+{
+ if (state == WifiPhy::CCA_BUSY)
+ {
+ busyTime += duration.GetSeconds ();
+ totalBusyTime += duration.GetSeconds ();
+ }
+ else if (state == WifiPhy::IDLE)
+ {
+ idleTime += duration.GetSeconds ();
+ totalIdleTime += duration.GetSeconds ();
+ }
+ else if (state == WifiPhy::TX)
+ {
+ txTime += duration.GetSeconds ();
+ totalTxTime += duration.GetSeconds ();
+ }
+ else if (state == WifiPhy::RX)
+ {
+ rxTime += duration.GetSeconds ();
+ totalRxTime += duration.GetSeconds ();
+ }
+}
+
+void
+NodeStatistics::RxCallback (std::string path, Ptr<const Packet> packet, const Address &from)
+{
+ m_bytesTotal += packet->GetSize ();
+}
+
+void
+NodeStatistics::CheckStatistics (double time)
+{
+ double mbs = ((m_bytesTotal * 8.0) / (1000000 * time));
+ m_bytesTotal = 0;
+ double atm = pow (10, ((totalEnergy / time) / 10));
+ totalEnergy = 0;
+ totalTime = 0;
+ m_output_power.Add ((Simulator::Now ()).GetSeconds (), atm);
+ m_output.Add ((Simulator::Now ()).GetSeconds (), mbs);
+
+ m_output_idle.Add ((Simulator::Now ()).GetSeconds (), idleTime * 100);
+ m_output_busy.Add ((Simulator::Now ()).GetSeconds (), busyTime * 100);
+ m_output_tx.Add ((Simulator::Now ()).GetSeconds (), txTime * 100);
+ m_output_rx.Add ((Simulator::Now ()).GetSeconds (), rxTime * 100);
+ busyTime = 0;
+ idleTime = 0;
+ txTime = 0;
+ rxTime = 0;
+
+ Simulator::Schedule (Seconds (time), &NodeStatistics::CheckStatistics, this, time);
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetDatafile ()
+{
+ return m_output;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetPowerDatafile ()
+{
+ return m_output_power;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetIdleDatafile ()
+{
+ return m_output_idle;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetBusyDatafile ()
+{
+ return m_output_busy;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetRxDatafile ()
+{
+ return m_output_rx;
+}
+
+Gnuplot2dDataset
+NodeStatistics::GetTxDatafile ()
+{
+ return m_output_tx;
+}
+
+double
+NodeStatistics::GetBusyTime ()
+{
+ return totalBusyTime + totalRxTime;
+}
+
+void PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+{
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Power " << (int)power);
+ // end PowerCallback
+}
+
+void RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+{
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Rate " << rate);
+ // end PowerCallback
+}
+
+int main (int argc, char *argv[])
+{
+ //LogComponentEnable("ConstantRateWifiManager", LOG_LEVEL_FUNCTION);
+
+ double maxPower = 17;
+ double minPower = 0;
+ uint32_t powerLevels = 18;
+
+ uint32_t rtsThreshold = 2346;
+ std::string manager = "ns3::ParfWifiManager";
+ std::string outputFileName = "parf";
+ int ap1_x = 0;
+ int ap1_y = 0;
+ int sta1_x = 10;
+ int sta1_y = 0;
+ int ap2_x = 200;
+ int ap2_y = 0;
+ int sta2_x = 180;
+ int sta2_y = 0;
+ uint32_t simuTime = 100;
+
+ CommandLine cmd;
+ cmd.AddValue ("manager", "PRC Manager", manager);
+ cmd.AddValue ("rtsThreshold", "RTS threshold", rtsThreshold);
+ cmd.AddValue ("outputFileName", "Output filename", outputFileName);
+ cmd.AddValue ("simuTime", "Total simulation time (sec)", simuTime);
+ cmd.AddValue ("maxPower", "Maximum available transmission level (dbm).", maxPower);
+ cmd.AddValue ("minPower", "Minimum available transmission level (dbm).", minPower);
+ cmd.AddValue ("powerLevels", "Number of transmission power levels available between "
+ "TxPowerStart and TxPowerEnd included.", powerLevels);
+ cmd.AddValue ("AP1_x", "Position of AP1 in x coordinate", ap1_x);
+ cmd.AddValue ("AP1_y", "Position of AP1 in y coordinate", ap1_y);
+ cmd.AddValue ("STA1_x", "Position of STA1 in x coordinate", sta1_x);
+ cmd.AddValue ("STA1_y", "Position of STA1 in y coordinate", sta1_y);
+ cmd.AddValue ("AP2_x", "Position of AP2 in x coordinate", ap2_x);
+ cmd.AddValue ("AP2_y", "Position of AP2 in y coordinate", ap2_y);
+ cmd.AddValue ("STA2_x", "Position of STA2 in x coordinate", sta2_x);
+ cmd.AddValue ("STA2_y", "Position of STA2 in y coordinate", sta2_y);
+ cmd.Parse (argc, argv);
+
+ // Define the APs
+ NodeContainer wifiApNodes;
+ wifiApNodes.Create (2);
+
+ //Define the STAs
+ NodeContainer wifiStaNodes;
+ wifiStaNodes.Create (2);
+
+ WifiHelper wifi = WifiHelper::Default ();
+ wifi.SetStandard (WIFI_PHY_STANDARD_80211a);
+ NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+
+ wifiPhy.SetChannel (wifiChannel.Create ());
+
+ NetDeviceContainer wifiApDevices;
+ NetDeviceContainer wifiStaDevices;
+ NetDeviceContainer wifiDevices;
+
+ //Configure the STA nodes
+ wifi.SetRemoteStationManager ("ns3::AarfWifiManager", "RtsCtsThreshold", UintegerValue (rtsThreshold));
+ //wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode",StringValue ("ErpOfdmRate6Mbps"),"ControlMode",StringValue ("ErpOfdmRate6Mbps"));
+ wifiPhy.Set ("TxPowerStart", DoubleValue (maxPower));
+ wifiPhy.Set ("TxPowerEnd", DoubleValue (maxPower));
+
+ Ssid ssid = Ssid ("AP0");
+ wifiMac.SetType ("ns3::StaWifiMac",
+ "Ssid", SsidValue (ssid),
+ "ActiveProbing", BooleanValue (false),
+ "MaxMissedBeacons", UintegerValue (1000));
+ wifiStaDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiStaNodes.Get (0)));
+
+ ssid = Ssid ("AP1");
+ wifiMac.SetType ("ns3::StaWifiMac",
+ "Ssid", SsidValue (ssid),
+ "ActiveProbing", BooleanValue (false));
+ wifiStaDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiStaNodes.Get (1)));
+
+ //Configure the AP nodes
+ wifi.SetRemoteStationManager (manager, "DefaultTxPowerLevel", UintegerValue (maxPower), "RtsCtsThreshold", UintegerValue (rtsThreshold));
+ wifiPhy.Set ("TxPowerStart", DoubleValue (minPower));
+ wifiPhy.Set ("TxPowerEnd", DoubleValue (maxPower));
+ wifiPhy.Set ("TxPowerLevels", UintegerValue (powerLevels));
+
+ ssid = Ssid ("AP0");
+ wifiMac.SetType ("ns3::ApWifiMac",
+ "Ssid", SsidValue (ssid));
+ wifiApDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiApNodes.Get (0)));
+
+ ssid = Ssid ("AP1");
+ wifiMac.SetType ("ns3::ApWifiMac",
+ "Ssid", SsidValue (ssid),
+ "BeaconInterval", TimeValue (MicroSeconds (103424))); //for avoiding collisions);
+ wifiApDevices.Add (wifi.Install (wifiPhy, wifiMac, wifiApNodes.Get (1)));
+
+ wifiDevices.Add (wifiStaDevices);
+ wifiDevices.Add (wifiApDevices);
+
+ // Configure the mobility.
+ MobilityHelper mobility;
+ Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+ positionAlloc->Add (Vector (ap1_x, ap1_y, 0.0));
+ positionAlloc->Add (Vector (sta1_x, sta1_y, 0.0));
+ positionAlloc->Add (Vector (ap2_x, ap2_y, 0.0));
+ positionAlloc->Add (Vector (sta2_x, sta2_y, 0.0));
+ mobility.SetPositionAllocator (positionAlloc);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (wifiApNodes.Get (0));
+ mobility.Install (wifiStaNodes.Get (0));
+ mobility.Install (wifiApNodes.Get (1));
+ mobility.Install (wifiStaNodes.Get (1));
+
+
+ //Configure the IP stack
+ InternetStackHelper stack;
+ stack.Install (wifiApNodes);
+ stack.Install (wifiStaNodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer i = address.Assign (wifiDevices);
+ Ipv4Address sinkAddress = i.GetAddress (0);
+ Ipv4Address sinkAddress1 = i.GetAddress (1);
+ uint16_t port = 9;
+
+ //Configure the CBR generator
+ PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress, port));
+ ApplicationContainer apps_sink = sink.Install (wifiStaNodes.Get (0));
+
+ OnOffHelper onoff ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress, port));
+ onoff.SetConstantRate (DataRate ("54Mb/s"), packetSize);
+ onoff.SetAttribute ("StartTime", TimeValue (Seconds (0.0)));
+ onoff.SetAttribute ("StopTime", TimeValue (Seconds (100.0)));
+ ApplicationContainer apps_source = onoff.Install (wifiApNodes.Get (0));
+
+ PacketSinkHelper sink1 ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress1, port));
+ apps_sink.Add (sink1.Install (wifiStaNodes.Get (1)));
+
+ OnOffHelper onoff1 ("ns3::UdpSocketFactory", InetSocketAddress (sinkAddress1, port));
+ onoff1.SetConstantRate (DataRate ("54Mb/s"), packetSize);
+ onoff1.SetAttribute ("StartTime", TimeValue (Seconds (0.0)));
+ onoff1.SetAttribute ("StopTime", TimeValue (Seconds (100.0)));
+ apps_source.Add (onoff1.Install (wifiApNodes.Get (1)));
+
+ apps_sink.Start (Seconds (0.5));
+ apps_sink.Stop (Seconds (simuTime));
+
+ //------------------------------------------------------------
+ //-- Setup stats and data collection
+ //--------------------------------------------
+
+ //Statistics counters
+ NodeStatistics statisticsAp0 = NodeStatistics (wifiApDevices, wifiStaDevices);
+ NodeStatistics statisticsAp1 = NodeStatistics (wifiApDevices, wifiStaDevices);
+
+ //Register packet receptions to calculate throughput
+ Config::Connect ("/NodeList/2/ApplicationList/*/$ns3::PacketSink/Rx",
+ MakeCallback (&NodeStatistics::RxCallback, &statisticsAp0));
+ Config::Connect ("/NodeList/3/ApplicationList/*/$ns3::PacketSink/Rx",
+ MakeCallback (&NodeStatistics::RxCallback, &statisticsAp1));
+
+ //Register power and rate changes to calculate the Average Transmit Power
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/PowerChange",
+ MakeCallback (&NodeStatistics::PowerCallback, &statisticsAp0));
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/RateChange",
+ MakeCallback (&NodeStatistics::RateCallback, &statisticsAp0));
+ Config::Connect ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/PowerChange",
+ MakeCallback (&NodeStatistics::PowerCallback, &statisticsAp1));
+ Config::Connect ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/RateChange",
+ MakeCallback (&NodeStatistics::RateCallback, &statisticsAp1));
+
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
+ MakeCallback (&NodeStatistics::PhyCallback, &statisticsAp0));
+ Config::Connect ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
+ MakeCallback (&NodeStatistics::PhyCallback, &statisticsAp1));
+
+ //Register States
+ Config::Connect ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/State/State",
+ MakeCallback (&NodeStatistics::StateCallback, &statisticsAp0));
+ Config::Connect ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/State/State",
+ MakeCallback (&NodeStatistics::StateCallback, &statisticsAp1));
+
+ statisticsAp0.CheckStatistics (1);
+ statisticsAp1.CheckStatistics (1);
+
+ //Callbacks to print every change of power and rate
+ Config::Connect ("/NodeList/[0-1]/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/PowerChange",
+ MakeCallback (PowerCallback));
+ Config::Connect ("/NodeList/[0-1]/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + manager + "/RateChange",
+ MakeCallback (RateCallback));
+
+
+ // Calculate Throughput using Flowmonitor
+ //
+
+ FlowMonitorHelper flowmon;
+ Ptr<FlowMonitor> monitor = flowmon.InstallAll ();
+
+ Simulator::Stop (Seconds (simuTime));
+ Simulator::Run ();
+
+ Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flowmon.GetClassifier ());
+ std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats ();
+ for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin (); i != stats.end (); ++i)
+ {
+ Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (i->first);
+ if ((t.sourceAddress == "10.1.1.3" && t.destinationAddress == "10.1.1.1"))
+ {
+ NS_LOG_INFO ("Flow " << i->first << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n");
+ NS_LOG_INFO (" Tx Bytes: " << i->second.txBytes << "\n");
+ NS_LOG_INFO (" Rx Bytes: " << i->second.rxBytes << "\n");
+ NS_LOG_UNCOND (" Throughput to 10.1.1.1: " << i->second.rxBytes * 8.0 / (i->second.timeLastRxPacket.GetSeconds () - i->second.timeFirstTxPacket.GetSeconds ()) / 1024 / 1024 << " Mbps\n");
+ NS_LOG_INFO (" Mean delay: " << i->second.delaySum.GetSeconds () / i->second.rxPackets << "\n");
+ NS_LOG_INFO (" Mean jitter: " << i->second.jitterSum.GetSeconds () / (i->second.rxPackets - 1) << "\n");
+ NS_LOG_INFO (" Tx Opp: " << 1 - (statisticsAp0.GetBusyTime () / simuTime));
+ }
+ if ((t.sourceAddress == "10.1.1.4" && t.destinationAddress == "10.1.1.2"))
+ {
+ NS_LOG_INFO ("Flow " << i->first << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n");
+ NS_LOG_INFO (" Tx Bytes: " << i->second.txBytes << "\n");
+ NS_LOG_INFO (" Rx Bytes: " << i->second.rxBytes << "\n");
+ NS_LOG_UNCOND (" Throughput to 10.1.1.2: " << i->second.rxBytes * 8.0 / (i->second.timeLastRxPacket.GetSeconds () - i->second.timeFirstTxPacket.GetSeconds ()) / 1024 / 1024 << " Mbps\n");
+ NS_LOG_INFO (" Mean delay: " << i->second.delaySum.GetSeconds () / i->second.rxPackets << "\n");
+ NS_LOG_INFO (" Mean jitter: " << i->second.jitterSum.GetSeconds () / (i->second.rxPackets - 1) << "\n");
+ NS_LOG_INFO (" Tx Opp: " << 1 - (statisticsAp1.GetBusyTime () / simuTime));
+ }
+ }
+
+ //Plots for AP0
+ std::ofstream outfileTh0 (("throughput-" + outputFileName + "-0.plt").c_str ());
+ Gnuplot gnuplot = Gnuplot (("throughput-" + outputFileName + "-0.eps").c_str (), "Throughput");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Throughput (Mb/s)");
+ gnuplot.SetTitle ("Throughput (AP0 to STA) vs time");
+ gnuplot.AddDataset (statisticsAp0.GetDatafile ());
+ gnuplot.GenerateOutput (outfileTh0);
+
+ if (manager.compare ("ns3::ParfWifiManager") == 0 ||
+ manager.compare ("ns3::AparfWifiManager") == 0)
+ {
+ std::ofstream outfilePower0 (("power-" + outputFileName + "-0.plt").c_str ());
+ gnuplot = Gnuplot (("power-" + outputFileName + "-0.eps").c_str (), "Average Transmit Power");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Power (mW)");
+ gnuplot.SetTitle ("Average transmit power (AP0 to STA) vs time");
+ gnuplot.AddDataset (statisticsAp0.GetPowerDatafile ());
+ gnuplot.GenerateOutput (outfilePower0);
+ }
+
+ std::ofstream outfileTx0 (("tx-" + outputFileName + "-0.plt").c_str ());
+ gnuplot = Gnuplot (("tx-" + outputFileName + "-0.eps").c_str (), "Time in TX State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP0 in TX state vs time");
+ gnuplot.AddDataset (statisticsAp0.GetTxDatafile ());
+ gnuplot.GenerateOutput (outfileTx0);
+
+ std::ofstream outfileRx0 (("rx-" + outputFileName + "-0.plt").c_str ());
+ gnuplot = Gnuplot (("rx-" + outputFileName + "-0.eps").c_str (), "Time in RX State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP0 in RX state vs time");
+ gnuplot.AddDataset (statisticsAp0.GetRxDatafile ());
+ gnuplot.GenerateOutput (outfileRx0);
+
+ std::ofstream outfileBusy0 (("busy-" + outputFileName + "-0.plt").c_str ());
+ gnuplot = Gnuplot (("busy-" + outputFileName + "-0.eps").c_str (), "Time in Busy State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP0 in Busy state vs time");
+ gnuplot.AddDataset (statisticsAp0.GetBusyDatafile ());
+ gnuplot.GenerateOutput (outfileBusy0);
+
+ std::ofstream outfileIdle0 (("idle-" + outputFileName + "-0.plt").c_str ());
+ gnuplot = Gnuplot (("idle-" + outputFileName + "-0.eps").c_str (), "Time in Idle State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP0 in Idle state vs time");
+ gnuplot.AddDataset (statisticsAp0.GetIdleDatafile ());
+ gnuplot.GenerateOutput (outfileIdle0);
+
+ //Plots for AP1
+ std::ofstream outfileTh1 (("throughput-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("throughput-" + outputFileName + "-1.eps").c_str (), "Throughput");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Throughput (Mb/s)");
+ gnuplot.SetTitle ("Throughput (AP1 to STA) vs time");
+ gnuplot.AddDataset (statisticsAp1.GetDatafile ());
+ gnuplot.GenerateOutput (outfileTh1);
+
+ if (manager.compare ("ns3::ParfWifiManager") == 0 ||
+ manager.compare ("ns3::AparfWifiManager") == 0)
+ {
+ std::ofstream outfilePower1 (("power-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("power-" + outputFileName + "-1.eps").c_str (), "Average Transmit Power");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Power (mW)");
+ gnuplot.SetTitle ("Average transmit power (AP1 to STA) vs time");
+ gnuplot.AddDataset (statisticsAp1.GetPowerDatafile ());
+ gnuplot.GenerateOutput (outfilePower1);
+ }
+
+ std::ofstream outfileTx1 (("tx-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("tx-" + outputFileName + "-1.eps").c_str (), "Time in TX State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP1 in TX state vs time");
+ gnuplot.AddDataset (statisticsAp1.GetTxDatafile ());
+ gnuplot.GenerateOutput (outfileTx1);
+
+ std::ofstream outfileRx1 (("rx-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("rx-" + outputFileName + "-1.eps").c_str (), "Time in RX State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP1 in RX state vs time");
+ gnuplot.AddDataset (statisticsAp1.GetRxDatafile ());
+ gnuplot.GenerateOutput (outfileRx1);
+
+ std::ofstream outfileBusy1 (("busy-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("busy-" + outputFileName + "-1.eps").c_str (), "Time in Busy State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP1 in Busy state vs time");
+ gnuplot.AddDataset (statisticsAp1.GetBusyDatafile ());
+ gnuplot.GenerateOutput (outfileBusy1);
+
+ std::ofstream outfileIdle1 (("idle-" + outputFileName + "-1.plt").c_str ());
+ gnuplot = Gnuplot (("idle-" + outputFileName + "-1.eps").c_str (), "Time in Idle State");
+ gnuplot.SetTerminal ("post eps color enhanced");
+ gnuplot.SetLegend ("Time (seconds)", "Percent");
+ gnuplot.SetTitle ("Percentage time AP1 in Idle state vs time");
+ gnuplot.AddDataset (statisticsAp1.GetIdleDatafile ());
+ gnuplot.GenerateOutput (outfileIdle1);
+
+ Simulator::Destroy ();
+
+ return 0;
+}
--- a/examples/wireless/wscript Sat Jan 24 23:16:24 2015 +0100
+++ b/examples/wireless/wscript Sun Jan 25 11:21:46 2015 -0800
@@ -57,3 +57,9 @@
obj = bld.create_ns3_program('wifi-sleep', ['core', 'network', 'internet', 'mobility', 'wifi', 'applications', 'energy', 'config-store'])
obj.source = 'wifi-sleep.cc'
+
+ obj = bld.create_ns3_program('power-adaptation-distance', ['core', 'mobility', 'wifi', 'applications', 'flow-monitor'])
+ obj.source = 'power-adaptation-distance.cc'
+
+ obj = bld.create_ns3_program('power-adaptation-interference', ['core', 'mobility', 'wifi', 'applications', 'flow-monitor'])
+ obj.source = 'power-adaptation-interference.cc'
--- a/src/wifi/doc/wifi.rst Sat Jan 24 23:16:24 2015 +0100
+++ b/src/wifi/doc/wifi.rst Sun Jan 25 11:21:46 2015 -0800
@@ -598,6 +598,8 @@
* ``CaraWifiManager`` [kim2006cara]_
* ``RraaWifiManager`` [wong2006rraa]_
* ``AarfcdWifiManager`` [maguolo2008aarfcd]_
+* ``ParfWifiManager`` [akella2007parf]_
+* ``AparfWifiManager`` [chevillat2005aparf]_
ConstantRateWifiManager
=======================
@@ -734,3 +736,7 @@
.. [wong2006rraa] \ S. Wong, H. Yang, S. Lu, and V. Bharghavan, *Robust Rate Adaptation for 802.11 Wireless Networks*, in Proc. 12th Annual International Conference on Mobile Computing and Networking, 2006
.. [maguolo2008aarfcd] \ F. Maguolo, M. Lacage, and T. Turletti, *Efficient collision detection for auto rate fallback algorithm*, in IEEE Symposium on Computers and Communications, 2008
+
+.. [akella2007parf] \ A. Akella, G. Judd, S. Seshan, and P. Steenkiste, 'Self-management in chaotic wireless deployments', in Wireless Networks, Kluwer Academic Publishers, 2007, 13, 737-755. `<http://www.cs.odu.edu/~nadeem/classes/cs795-WNS-S13/papers/enter-006.pdf>`_
+
+.. [chevillat2005aparf] \ Chevillat, P.; Jelitto, J., and Truong, H. L., 'Dynamic data rate and transmit power adjustment in IEEE 802.11 wireless LANs', in International Journal of Wireless Information Networks, Springer, 2005, 12, 123-145. `<http://www.cs.mun.ca/~yzchen/papers/papers/rate_adaptation/80211_dynamic_rate_power_adjustment_chevillat_j2005.pdf>`_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/aparf-wifi-manager.cc Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,338 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+#include "aparf-wifi-manager.h"
+#include "wifi-phy.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#define Min(a,b) ((a < b) ? a : b)
+NS_LOG_COMPONENT_DEFINE ("ns3::AparfWifiManager");
+
+namespace ns3 {
+
+/**
+ * Hold per-remote-station state for APARF Wifi manager.
+ *
+ * This struct extends from WifiRemoteStation struct to hold additional
+ * information required by the APARF Wifi manager
+ */
+struct
+AparfWifiRemoteStation : public WifiRemoteStation
+{
+ uint32_t m_nSuccess; //!< Number of successful transmission attempts.
+ uint32_t m_nFailed; //!< Number of failed transmission attempts.
+ uint32_t m_pCount; //!< Number of power changes.
+
+ uint32_t m_successThreshold; //!< The minimum number of successful transmissions to try a new power or rate.
+ uint32_t m_failThreshold; //!< The minimum number of failed transmissions to try a new power or rate.
+
+ uint32_t m_rate; //!< Current rate.
+ uint32_t m_rateCrit; //!< Critical rate.
+ uint8_t m_power; //!< Current power.
+
+ uint32_t m_nSupported; //!< Number of supported rates by the remote station.
+ bool m_initialized; //!< For initializing variables.
+
+ AparfWifiManager::State m_aparfState; //!< The estimated state of the channel.
+};
+
+NS_OBJECT_ENSURE_REGISTERED (AparfWifiManager);
+
+TypeId
+AparfWifiManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::AparfWifiManager")
+ .SetParent<WifiRemoteStationManager> ()
+ .AddConstructor<AparfWifiManager> ()
+ .AddAttribute ("SuccessThreshold 1",
+ "The minimum number of successful transmissions in \"High\" state to try a new power or rate.",
+ UintegerValue (3),
+ MakeUintegerAccessor (&AparfWifiManager::m_succesMax1),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("SuccessThreshold 2",
+ "The minimum number of successful transmissions in \"Low\" state to try a new power or rate.",
+ UintegerValue (10),
+ MakeUintegerAccessor (&AparfWifiManager::m_succesMax2),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("FailThreshold",
+ "The minimum number of failed transmissions to try a new power or rate.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&AparfWifiManager::m_failMax),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("PowerThreshold",
+ "The maximum number of power changes.",
+ UintegerValue (10),
+ MakeUintegerAccessor (&AparfWifiManager::m_powerMax),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("Power decrement step",
+ "Step size for decrement the power.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&AparfWifiManager::m_powerDec),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("Power increment step",
+ "Step size for increment the power.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&AparfWifiManager::m_powerInc),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("Rate decrement step",
+ "Step size for decrement the rate.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&AparfWifiManager::m_rateDec),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("Rate increment step",
+ "Step size for increment the rate.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&AparfWifiManager::m_rateInc),
+ MakeUintegerChecker<uint32_t> ())
+ .AddTraceSource ("PowerChange",
+ "The transmission power has change",
+ MakeTraceSourceAccessor (&AparfWifiManager::m_powerChange),
+ "ns3::AparfWifiManager::PowerChangeTracedCallback")
+ .AddTraceSource ("RateChange",
+ "The transmission rate has change",
+ MakeTraceSourceAccessor (&AparfWifiManager::m_rateChange),
+ "ns3::AparfWifiManager::RateChangeTracedCallback")
+ ;
+ return tid;
+}
+
+AparfWifiManager::AparfWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+}
+AparfWifiManager::~AparfWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+AparfWifiManager::SetupPhy (Ptr<WifiPhy> phy)
+{
+ m_nPower = phy->GetNTxPower ();
+ WifiRemoteStationManager::SetupPhy (phy);
+}
+
+WifiRemoteStation *
+AparfWifiManager::DoCreateStation (void) const
+{
+ NS_LOG_FUNCTION (this);
+ AparfWifiRemoteStation *station = new AparfWifiRemoteStation ();
+
+ station->m_successThreshold = m_succesMax1;
+ station->m_failThreshold = m_failMax;
+ station->m_nSuccess = 0;
+ station->m_nFailed = 0;
+ station->m_pCount = 0;
+ station->m_aparfState = AparfWifiManager::High;
+ station->m_initialized = false;
+
+ NS_LOG_DEBUG ("create station=" << station << ", rate=" << station->m_rate
+ << ", power=" << (int)station->m_power);
+
+ return station;
+}
+
+void
+AparfWifiManager::CheckInit (AparfWifiRemoteStation *station)
+{
+ if (!station->m_initialized)
+ {
+ station->m_nSupported = GetNSupported (station);
+ station->m_rate = station->m_nSupported - 1;
+ station->m_power = m_nPower - 1;
+ station->m_rateCrit = 0;
+ m_powerChange (station->m_power, station->m_state->m_address);
+ m_rateChange (station->m_rate, station->m_state->m_address);
+ station->m_initialized = true;
+ }
+}
+
+void AparfWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+
+void AparfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
+ CheckInit (station);
+ station->m_nFailed++;
+ station->m_nSuccess = 0;
+ NS_LOG_DEBUG ("station=" << station << ", rate=" << station->m_rate
+ << ", power=" << (int)station->m_power);
+
+ if (station->m_aparfState == AparfWifiManager::Low)
+ {
+ station->m_aparfState = AparfWifiManager::High;
+ station->m_successThreshold = m_succesMax1;
+ }
+ else if (station->m_aparfState == AparfWifiManager::Spread)
+ {
+ station->m_aparfState = AparfWifiManager::Low;
+ station->m_successThreshold = m_succesMax2;
+ }
+
+ if (station->m_nFailed == station->m_failThreshold)
+ {
+ station->m_nFailed = 0;
+ station->m_nSuccess = 0;
+ station->m_pCount = 0;
+ if (station->m_power == (m_nPower - 1))
+ {
+ station->m_rateCrit = station->m_rate;
+ if (station->m_rate != 0)
+ {
+ NS_LOG_DEBUG ("station=" << station << " dec rate");
+ station->m_rate -= m_rateDec;
+ m_rateChange (station->m_rate, station->m_state->m_address);
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("station=" << station << " inc power");
+ station->m_power += m_powerInc;
+ m_powerChange (station->m_power, station->m_state->m_address);
+ }
+ }
+}
+void
+AparfWifiManager::DoReportRxOk (WifiRemoteStation *station, double rxSnr, WifiMode txMode)
+{
+ NS_LOG_FUNCTION (this << station << rxSnr << txMode);
+}
+void
+AparfWifiManager::DoReportRtsOk (WifiRemoteStation *station, double ctsSnr,
+ WifiMode ctsMode, double rtsSnr)
+{
+ NS_LOG_FUNCTION (this << station << ctsSnr << ctsMode << rtsSnr);
+ NS_LOG_DEBUG ("station=" << station << " rts ok");
+}
+void
+AparfWifiManager::DoReportDataOk (WifiRemoteStation *st, double ackSnr,
+ WifiMode ackMode, double dataSnr)
+{
+ NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
+ AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
+ CheckInit (station);
+ station->m_nSuccess++;
+ station->m_nFailed = 0;
+ NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_nSuccess << ", rate=" << station->m_rate << ", power=" << (int)station->m_power);
+
+ if ((station->m_aparfState == AparfWifiManager::High) && (station->m_nSuccess >= station->m_successThreshold))
+ {
+ station->m_aparfState = AparfWifiManager::Spread;
+ }
+ else if ((station->m_aparfState == AparfWifiManager::Low) && (station->m_nSuccess >= station->m_successThreshold))
+ {
+ station->m_aparfState = AparfWifiManager::Spread;
+ }
+ else if (station->m_aparfState == AparfWifiManager::Spread)
+ {
+ station->m_aparfState = AparfWifiManager::High;
+ station->m_successThreshold = m_succesMax1;
+ }
+
+ if (station->m_nSuccess == station->m_successThreshold)
+ {
+ station->m_nSuccess = 0;
+ station->m_nFailed = 0;
+ if (station->m_rate == (station->m_state->m_operationalRateSet.size () - 1))
+ {
+ if (station->m_power != 0)
+ {
+ NS_LOG_DEBUG ("station=" << station << " dec power");
+ station->m_power -= m_powerDec;
+ m_powerChange (station->m_power, station->m_state->m_address);
+ }
+ }
+ else
+ {
+ if (station->m_rateCrit == 0)
+ {
+ if (station->m_rate != (station->m_state->m_operationalRateSet.size () - 1))
+ {
+ NS_LOG_DEBUG ("station=" << station << " inc rate");
+ station->m_rate += m_rateInc;
+ m_rateChange (station->m_rate, station->m_state->m_address);
+ }
+ }
+ else
+ {
+ if (station->m_pCount == m_powerMax)
+ {
+ station->m_power = (m_nPower - 1);
+ m_powerChange (station->m_power, station->m_state->m_address);
+ station->m_rate = station->m_rateCrit;
+ m_rateChange (station->m_rate, station->m_state->m_address);
+ station->m_pCount = 0;
+ station->m_rateCrit = 0;
+ }
+ else
+ {
+ if (station->m_power != 0)
+ {
+ station->m_power -= m_powerDec;
+ m_powerChange (station->m_power, station->m_state->m_address);
+ station->m_pCount++;
+ }
+ }
+ }
+ }
+ }
+}
+void
+AparfWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+void
+AparfWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+
+WifiTxVector
+AparfWifiManager::DoGetDataTxVector (WifiRemoteStation *st, uint32_t size)
+{
+ NS_LOG_FUNCTION (this << st << size);
+ AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
+ CheckInit (station);
+ return WifiTxVector (GetSupported (station, station->m_rate), station->m_power, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+}
+WifiTxVector
+AparfWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ /// \todo we could/should implement the Arf algorithm for
+ /// RTS only by picking a single rate within the BasicRateSet.
+ AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
+ return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+}
+
+bool
+AparfWifiManager::IsLowLatency (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return true;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/aparf-wifi-manager.h Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+#ifndef APARF_WIFI_MANAGER_H
+#define APARF_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+struct AparfWifiRemoteStation;
+
+/**
+ * \ingroup wifi
+ * APARF Power and rate control algorithm
+ *
+ * This class implements the High Performance power and rate control algorithm
+ * described in <i>Dynamic data rate and transmit power adjustment
+ * in IEEE 802.11 wireless LANs</i> by Chevillat, P.; Jelitto, J.
+ * and Truong, H. L. in International Journal of Wireless Information
+ * Networks, Springer, 2005, 12, 123-145.
+ * http://www.cs.mun.ca/~yzchen/papers/papers/rate_adaptation/80211_dynamic_rate_power_adjustment_chevillat_j2005.pdf
+ *
+ */
+class AparfWifiManager : public WifiRemoteStationManager
+{
+public:
+ /**
+ * Register this type.
+ * \return The object TypeId.
+ */
+ static TypeId GetTypeId (void);
+ AparfWifiManager ();
+ virtual ~AparfWifiManager ();
+
+ virtual void SetupPhy (Ptr<WifiPhy> phy);
+
+ /**
+ * Enumeration of the possible states of the channel.
+ */
+ enum State
+ {
+ High,
+ Low,
+ Spread
+ };
+
+ /**
+ * TracedCallback signature for power change events.
+ *
+ * \param [in] power The new power.
+ * \param [in] address The remote station MAC address.
+ */
+ typedef void (*PowerChangeTracedCallback)(const uint8_t power, const Mac48Address remoteAddress);
+
+ /**
+ * TracedCallback signature for rate change events.
+ *
+ * \param [in] rate The new rate.
+ * \param [in] address The remote station MAC address.
+ */
+ typedef void (*RateChangeTracedCallback)(const uint32_t rate, const Mac48Address remoteAddress);
+
+private:
+ // overriden from base class
+ virtual WifiRemoteStation * DoCreateStation (void) const;
+ virtual void DoReportRxOk (WifiRemoteStation *station,
+ double rxSnr, WifiMode txMode);
+ virtual void DoReportRtsFailed (WifiRemoteStation *station);
+ virtual void DoReportDataFailed (WifiRemoteStation *station);
+ virtual void DoReportRtsOk (WifiRemoteStation *station,
+ double ctsSnr, WifiMode ctsMode, double rtsSnr);
+ virtual void DoReportDataOk (WifiRemoteStation *station,
+ double ackSnr, WifiMode ackMode, double dataSnr);
+ virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+ virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+ virtual WifiTxVector DoGetDataTxVector (WifiRemoteStation *station, uint32_t size);
+ virtual WifiTxVector DoGetRtsTxVector (WifiRemoteStation *station);
+ virtual bool IsLowLatency (void) const;
+
+ /** Check for initializations.
+ *
+ * \param station The remote station.
+ */
+ void CheckInit (AparfWifiRemoteStation *station);
+
+ uint32_t m_succesMax1; //!< The minimum number of successful transmissions in \"High\" state to try a new power or rate.
+ uint32_t m_succesMax2; //!< The minimum number of successful transmissions in \"Low\" state to try a new power or rate.
+ uint32_t m_failMax; //!< The minimum number of failed transmissions to try a new power or rate.
+ uint32_t m_powerMax; //!< The maximum number of power changes.
+ uint32_t m_powerInc; //!< Step size for increment the power.
+ uint32_t m_powerDec; //!< Step size for decrement the power.
+ uint32_t m_rateInc; //!< Step size for increment the rate.
+ uint32_t m_rateDec; //!< Step size for decrement the rate.
+ /**
+ * Number of power levels.
+ * Differently form rate, power levels do not depend on the remote station.
+ * The levels depend only on the physical layer of the device.
+ */
+ uint32_t m_nPower;
+
+ /**
+ * The trace source fired when the transmission power change
+ */
+ TracedCallback<uint8_t, Mac48Address> m_powerChange;
+ /**
+ * The trace source fired when the transmission rate change
+ */
+ TracedCallback<uint32_t, Mac48Address> m_rateChange;
+
+};
+
+} // namespace ns3
+
+#endif /* APARF_WIFI_MANAGER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/parf-wifi-manager.cc Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,311 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+
+#include "parf-wifi-manager.h"
+#include "wifi-phy.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+
+#define Min(a,b) ((a < b) ? a : b)
+
+NS_LOG_COMPONENT_DEFINE ("ns3::ParfWifiManager");
+
+
+namespace ns3 {
+
+/**
+ * Hold per-remote-station state for PARF Wifi manager.
+ *
+ * This struct extends from WifiRemoteStation struct to hold additional
+ * information required by the PARF Wifi manager
+ */
+struct ParfWifiRemoteStation : public WifiRemoteStation
+{
+ uint32_t m_nAttempt; //!< Number of transmission attempts.
+ uint32_t m_nSuccess; //!< Number of successful transmission attempts.
+ uint32_t m_nFail; //!< Number of failed transmission attempts.
+ bool m_usingRecoveryRate; //!< If using recovery rate.
+ bool m_usingRecoveryPower; //!< If using recovery power.
+ uint32_t m_nRetry; //!< Number of transmission retries.
+
+ uint32_t m_currentRate; //!< Current rate used by the remote station.
+
+ uint8_t m_currentPower; //!< Current power used by the remote station.
+
+ uint32_t m_nSupported; //!< Number of supported rates by the remote station.
+ bool m_initialized; //!< For initializing variables.
+};
+
+NS_OBJECT_ENSURE_REGISTERED (ParfWifiManager);
+
+TypeId
+ParfWifiManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ParfWifiManager")
+ .SetParent<WifiRemoteStationManager> ()
+ .AddConstructor<ParfWifiManager> ()
+ .AddAttribute ("AttemptThreshold",
+ "The minimum number of transmission attempts to try a new power or rate.",
+ UintegerValue (15),
+ MakeUintegerAccessor (&ParfWifiManager::m_attemptThreshold),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("SuccessThreshold",
+ "The minimum number of successful transmissions to try a new power or rate.",
+ UintegerValue (10),
+ MakeUintegerAccessor (&ParfWifiManager::m_successThreshold),
+ MakeUintegerChecker<uint32_t> ())
+ .AddTraceSource ("PowerChange",
+ "The transmission power has change",
+ MakeTraceSourceAccessor (&ParfWifiManager::m_powerChange),
+ "ns3::ParfWifiManager::PowerChangeTracedCallback")
+ .AddTraceSource ("RateChange",
+ "The transmission rate has change",
+ MakeTraceSourceAccessor (&ParfWifiManager::m_rateChange),
+ "ns3::ParfWifiManager::RateChangeTracedCallback")
+ ;
+ return tid;
+}
+
+ParfWifiManager::ParfWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+}
+ParfWifiManager::~ParfWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+ParfWifiManager::SetupPhy (Ptr<WifiPhy> phy)
+{
+ m_nPower = phy->GetNTxPower ();
+ WifiRemoteStationManager::SetupPhy (phy);
+}
+
+WifiRemoteStation *
+ParfWifiManager::DoCreateStation (void) const
+{
+ NS_LOG_FUNCTION (this);
+ ParfWifiRemoteStation *station = new ParfWifiRemoteStation ();
+
+ station->m_nSuccess = 0;
+ station->m_nFail = 0;
+ station->m_usingRecoveryRate = false;
+ station->m_usingRecoveryPower = false;
+ station->m_initialized = false;
+ station->m_nRetry = 0;
+ station->m_nAttempt = 0;
+
+ NS_LOG_DEBUG ("create station=" << station << ", timer=" << station->m_nAttempt
+ << ", rate=" << station->m_currentRate << ", power=" << (int)station->m_currentPower);
+
+ return station;
+}
+
+void
+ParfWifiManager::CheckInit (ParfWifiRemoteStation *station)
+{
+ if (!station->m_initialized)
+ {
+ station->m_nSupported = GetNSupported (station);
+ station->m_currentRate = station->m_nSupported - 1;
+ station->m_currentPower = m_nPower - 1;
+ m_powerChange (station->m_currentPower, station->m_state->m_address);
+ m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_initialized = true;
+ }
+}
+
+void
+ParfWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+/**
+ * \internal
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode spans retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void
+ParfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ ParfWifiRemoteStation *station = (ParfWifiRemoteStation *)st;
+ CheckInit (station);
+ station->m_nAttempt++;
+ station->m_nFail++;
+ station->m_nRetry++;
+ station->m_nSuccess = 0;
+
+ NS_LOG_DEBUG ("station=" << station << " data fail retry=" << station->m_nRetry << ", timer=" << station->m_nAttempt
+ << ", rate=" << station->m_currentRate << ", power=" << (int)station->m_currentPower);
+ if (station->m_usingRecoveryRate)
+ {
+ NS_ASSERT (station->m_nRetry >= 1);
+ if (station->m_nRetry == 1)
+ {
+ // need recovery fallback
+ if (station->m_currentRate != 0)
+ {
+ NS_LOG_DEBUG ("station=" << station << " dec rate");
+ station->m_currentRate--;
+ m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_usingRecoveryRate = false;
+ }
+ }
+ station->m_nAttempt = 0;
+ }
+ else if (station->m_usingRecoveryPower)
+ {
+ NS_ASSERT (station->m_nRetry >= 1);
+ if (station->m_nRetry == 1)
+ {
+ // need recovery fallback
+ if (station->m_currentPower < m_nPower - 1)
+ {
+ NS_LOG_DEBUG ("station=" << station << " inc power");
+ station->m_currentPower++;
+ m_powerChange (station->m_currentPower, station->m_state->m_address);
+ station->m_usingRecoveryPower = false;
+ }
+ }
+ station->m_nAttempt = 0;
+ }
+ else
+ {
+ NS_ASSERT (station->m_nRetry >= 1);
+ if (((station->m_nRetry - 1) % 2) == 1)
+ {
+ // need normal fallback
+ if (station->m_currentPower == m_nPower - 1)
+ {
+ if (station->m_currentRate != 0)
+ {
+ NS_LOG_DEBUG ("station=" << station << " dec rate");
+ station->m_currentRate--;
+ m_rateChange (station->m_currentRate, station->m_state->m_address);
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("station=" << station << " inc power");
+ station->m_currentPower++;
+ m_powerChange (station->m_currentPower, station->m_state->m_address);
+ }
+ }
+ if (station->m_nRetry >= 2)
+ {
+ station->m_nAttempt = 0;
+ }
+ }
+}
+void
+ParfWifiManager::DoReportRxOk (WifiRemoteStation *station,
+ double rxSnr, WifiMode txMode)
+{
+ NS_LOG_FUNCTION (this << station << rxSnr << txMode);
+}
+void ParfWifiManager::DoReportRtsOk (WifiRemoteStation *station,
+ double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+ NS_LOG_FUNCTION (this << station << ctsSnr << ctsMode << rtsSnr);
+ NS_LOG_DEBUG ("station=" << station << " rts ok");
+}
+void ParfWifiManager::DoReportDataOk (WifiRemoteStation *st,
+ double ackSnr, WifiMode ackMode, double dataSnr)
+{
+ NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
+ ParfWifiRemoteStation *station = (ParfWifiRemoteStation *) st;
+ CheckInit (station);
+ station->m_nAttempt++;
+ station->m_nSuccess++;
+ station->m_nFail = 0;
+ station->m_usingRecoveryRate = false;
+ station->m_usingRecoveryPower = false;
+ station->m_nRetry = 0;
+ NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_nSuccess << ", timer=" << station->m_nAttempt << ", rate=" << station->m_currentRate << ", power=" << (int)station->m_currentPower);
+ if ((station->m_nSuccess == m_successThreshold
+ || station->m_nAttempt == m_attemptThreshold)
+ && (station->m_currentRate < (station->m_state->m_operationalRateSet.size () - 1)))
+ {
+ NS_LOG_DEBUG ("station=" << station << " inc rate");
+ station->m_currentRate++;
+ m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_nAttempt = 0;
+ station->m_nSuccess = 0;
+ station->m_usingRecoveryRate = true;
+ }
+ else if (station->m_nSuccess == m_successThreshold || station->m_nAttempt == m_attemptThreshold)
+ {
+ //we are at the maximum rate, we decrease power
+ if (station->m_currentPower != 0)
+ {
+ NS_LOG_DEBUG ("station=" << station << " dec power");
+ station->m_currentPower--;
+ m_powerChange (station->m_currentPower, station->m_state->m_address);
+ }
+ station->m_nAttempt = 0;
+ station->m_nSuccess = 0;
+ station->m_usingRecoveryPower = true;
+ }
+}
+void
+ParfWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+void
+ParfWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+}
+
+WifiTxVector
+ParfWifiManager::DoGetDataTxVector (WifiRemoteStation *st, uint32_t size)
+{
+ NS_LOG_FUNCTION (this << st << size);
+ ParfWifiRemoteStation *station = (ParfWifiRemoteStation *) st;
+ CheckInit (station);
+ return WifiTxVector (GetSupported (station, station->m_currentRate), station->m_currentPower, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+}
+WifiTxVector
+ParfWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ /// \todo we could/should implement the Arf algorithm for
+ /// RTS only by picking a single rate within the BasicRateSet.
+ ParfWifiRemoteStation *station = (ParfWifiRemoteStation *) st;
+ return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+}
+
+bool
+ParfWifiManager::IsLowLatency (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return true;
+}
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/parf-wifi-manager.h Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,115 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matias Richart <mrichart@fing.edu.uy>
+ */
+
+#ifndef PARF_WIFI_MANAGER_H
+#define PARF_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+struct ParfWifiRemoteStation;
+/**
+ * \ingroup wifi
+ * PARF Rate control algorithm
+ *
+ * This class implements the PARF algorithm as described in
+ * <i>Self-management in chaotic wireless deployments</i>, by
+ * Akella, A.; Judd, G.; Seshan, S. and Steenkiste, P. in
+ * Wireless Networks, Kluwer Academic Publishers, 2007, 13, 737-755
+ * http://www.cs.odu.edu/~nadeem/classes/cs795-WNS-S13/papers/enter-006.pdf
+ *
+ */
+class ParfWifiManager : public WifiRemoteStationManager
+{
+public:
+ /**
+ * Register this type.
+ * \return The object TypeId.
+ */
+ static TypeId GetTypeId (void);
+ ParfWifiManager ();
+ virtual ~ParfWifiManager ();
+
+ virtual void SetupPhy (Ptr<WifiPhy> phy);
+
+ /**
+ * TracedCallback signature for power change events.
+ *
+ * \param [in] power The new power.
+ * \param [in] address The remote station MAC address.
+ */
+ typedef void (*PowerChangeTracedCallback)(const uint8_t power, const Mac48Address remoteAddress);
+
+ /**
+ * TracedCallback signature for rate change events.
+ *
+ * \param [in] rate The new rate.
+ * \param [in] address The remote station MAC address.
+ */
+ typedef void (*RateChangeTracedCallback)(const uint32_t rate, const Mac48Address remoteAddress);
+
+private:
+ // overriden from base class
+ virtual WifiRemoteStation * DoCreateStation (void) const;
+ virtual void DoReportRxOk (WifiRemoteStation *station,
+ double rxSnr, WifiMode txMode);
+ virtual void DoReportRtsFailed (WifiRemoteStation *station);
+ virtual void DoReportDataFailed (WifiRemoteStation *station);
+ virtual void DoReportRtsOk (WifiRemoteStation *station,
+ double ctsSnr, WifiMode ctsMode, double rtsSnr);
+ virtual void DoReportDataOk (WifiRemoteStation *station,
+ double ackSnr, WifiMode ackMode, double dataSnr);
+ virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+ virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+ virtual WifiTxVector DoGetDataTxVector (WifiRemoteStation *station, uint32_t size);
+ virtual WifiTxVector DoGetRtsTxVector (WifiRemoteStation *station);
+ virtual bool IsLowLatency (void) const;
+
+ /** Check for initializations.
+ *
+ * \param station The remote station.
+ */
+ void CheckInit (ParfWifiRemoteStation *station);
+
+
+ uint32_t m_attemptThreshold; //!< The minimum number of transmission attempts to try a new power or rate. The 'timer' threshold in the ARF algorithm.
+ uint32_t m_successThreshold; //!< The minimum number of successful transmissions to try a new power or rate.
+ /**
+ * Number of power levels.
+ * In contrast to rate, power levels do not depend on the remote station.
+ * The levels depend only on the physical layer of the device.
+ */
+ uint32_t m_nPower;
+
+ /**
+ * The trace source fired when the transmission power changes....
+ */
+ TracedCallback<uint8_t, Mac48Address> m_powerChange;
+ /**
+ * The trace source fired when the transmission rate changes.
+ */
+ TracedCallback<uint32_t, Mac48Address> m_rateChange;
+
+};
+
+} // namespace ns3
+
+#endif /* PARF_WIFI_MANAGER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/test/power-rate-adaptation-test.cc Sun Jan 25 11:21:46 2015 -0800
@@ -0,0 +1,601 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 Universidad de la República - Uruguay
+ *
+ * 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: Matías Richart <mrichart@fing.edu.uy>
+ */
+
+#include "ns3/wifi-net-device.h"
+#include "ns3/yans-wifi-channel.h"
+#include "ns3/adhoc-wifi-mac.h"
+#include "ns3/yans-wifi-phy.h"
+#include "ns3/parf-wifi-manager.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/error-rate-model.h"
+#include "ns3/yans-error-rate-model.h"
+#include "ns3/constant-position-mobility-model.h"
+#include "ns3/node.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/object-factory.h"
+#include "ns3/dca-txop.h"
+#include "ns3/mac-rx-middle.h"
+#include "ns3/pointer.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/edca-txop-n.h"
+#include "ns3/config.h"
+#include "ns3/boolean.h"
+
+using namespace ns3;
+
+class PowerRateAdaptationTest : public TestCase
+{
+public:
+ PowerRateAdaptationTest ();
+
+ virtual void DoRun (void);
+private:
+ void TestParf ();
+ void TestAparf ();
+ Ptr<Node> ConfigureNode ();
+
+ ObjectFactory m_manager;
+};
+
+PowerRateAdaptationTest::PowerRateAdaptationTest ()
+ : TestCase ("PowerRateAdaptation")
+{
+}
+
+Ptr<Node>
+PowerRateAdaptationTest::ConfigureNode ()
+{
+ /*
+ * Create channel model. Is is necessary to configure correctly the phy layer.
+ */
+ Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
+
+ /*
+ * Create mac layer. We use Adhoc because association is not needed to get supported rates.
+ */
+ Ptr<AdhocWifiMac> mac = CreateObject<AdhocWifiMac> ();
+ mac->ConfigureStandard (WIFI_PHY_STANDARD_80211a);
+
+ /*
+ * Create mobility model. Is needed by the phy layer for transmission.
+ */
+ Ptr<ConstantPositionMobilityModel> mobility = CreateObject<ConstantPositionMobilityModel> ();
+
+ /*
+ * Create and configure phy layer.
+ */
+ Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice> ();
+ Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy> ();
+ phy->SetChannel (channel);
+ phy->SetDevice (dev);
+ phy->SetMobility (mobility);
+ phy->ConfigureStandard (WIFI_PHY_STANDARD_80211a);
+
+ /*
+ * Configure power control parameters.
+ */
+ phy->SetNTxPower(18);
+ phy->SetTxPowerStart(0);
+ phy->SetTxPowerEnd(17);
+
+ /*
+ * Create manager.
+ */
+ Ptr<WifiRemoteStationManager> manager = m_manager.Create<WifiRemoteStationManager> ();
+
+ /*
+ * Create and configure node. Add mac and phy layer and the manager.
+ */
+ Ptr<Node> node = CreateObject<Node> ();
+ mac->SetAddress (Mac48Address::Allocate ());
+ dev->SetMac (mac);
+ dev->SetPhy (phy);
+ dev->SetRemoteStationManager (manager);
+ node->AddDevice (dev);
+
+ return node;
+}
+
+void
+PowerRateAdaptationTest::TestParf ()
+{
+ m_manager.SetTypeId ("ns3::ParfWifiManager");
+ Ptr<Node> node = ConfigureNode();
+ Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice> (node->GetDevice(0));
+ Ptr<WifiRemoteStationManager> manager = dev->GetRemoteStationManager();
+
+ /*
+ * Configure thresholds for rate and power control.
+ */
+ manager->SetAttribute("AttemptThreshold",UintegerValue (15));
+ manager->SetAttribute("SuccessThreshold",UintegerValue(10));
+
+ /*
+ * Create a dummy packet to simulate transmission.
+ */
+ Mac48Address remoteAddress = Mac48Address::Allocate ();
+ WifiMacHeader packetHeader;
+ packetHeader.SetTypeData ();
+ packetHeader.SetQosTid (0);
+ Ptr<Packet> packet = Create<Packet> (10);
+ WifiMode ackMode;
+
+ /*
+ * To initialize the manager we need to generate a transmission.
+ */
+ Ptr<Packet> p = Create<Packet> ();
+ dev->Send (p, remoteAddress, 1);
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * Parf initiates with maximal rate and power.
+ */
+ WifiTxVector txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ WifiMode mode = txVector.GetMode();
+ int power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Initial data rate wrong");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Initial power level wrong");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 10 consecutive successful transmissions parf increase rate or decrease power.
+ * As we are at maximal rate, the power should be decreased. recoveryPower=true.
+ */
+ for(int i = 0; i<10; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are using recovery power, one failure make power increase.
+ *
+ */
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 15 transmissions attempts parf increase rate or decrease power.
+ * As we are at maximal rate, the power should be decreased. recoveryPower=true.
+ */
+ for(int i = 0; i<7; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+ }
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are using recovery power, one failure make power increase. recoveryPower=false.
+ */
+
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After two consecutive fails the rate is decreased or the power increased.
+ * As we are at maximal power, the rate should be decreased.
+ */
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 48000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 10 consecutive successful transmissions parf increase rate or decrease power.
+ * As we are not at maximal rate, the rate is increased again. recoveryRate=true.
+ */
+ for(int i = 0; i<10; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are using recovery rate, one failure make rate decrease. recoveryRate=false.
+ */
+
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 48000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 10 consecutive successful transmissions parf increase rate or decrease power.
+ * As we are not at maximal rate, the rate is increased again. recoveryRate=true.
+ */
+ for(int i = 0; i<10; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 10 consecutive successful transmissions parf increase rate or decrease power.
+ * As we are at maximal rate, the power is decreased. recoveryRate=false, recoveryPower=true.
+ */
+ for(int i = 0; i<10; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "PARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * One successful transmissions after a power decrease make recoverPower=false.
+ * So we need two consecutive failures to increase power again.
+ */
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+
+ for(int i = 0; i<2; i++)
+ {
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "PARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "PARF: Incorrect value of power level");
+
+ Simulator::Stop (Seconds (10.0));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+}
+
+void
+PowerRateAdaptationTest::TestAparf ()
+{
+ m_manager.SetTypeId ("ns3::AparfWifiManager");
+ Ptr<Node> node = ConfigureNode();
+ Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice> (node->GetDevice(0));
+ Ptr<WifiRemoteStationManager> manager = dev->GetRemoteStationManager();
+
+ /*
+ * Configure thresholds for rate and power control.
+ */
+ manager->SetAttribute("SuccessThreshold 1",UintegerValue (3));
+ manager->SetAttribute("SuccessThreshold 2",UintegerValue(10));
+ manager->SetAttribute("FailThreshold",UintegerValue (1));
+ manager->SetAttribute("PowerThreshold",UintegerValue(10));
+
+ /*
+ * Create a dummy packet to simulate transmission.
+ */
+ Mac48Address remoteAddress = Mac48Address::Allocate ();
+ WifiMacHeader packetHeader;
+ packetHeader.SetTypeData ();
+ packetHeader.SetQosTid (0);
+ Ptr<Packet> packet = Create<Packet> (10);
+ WifiMode ackMode;
+
+ /*
+ * To initialize the manager we need to generate a transmission.
+ */
+ Ptr<Packet> p = Create<Packet> ();
+ dev->Send (p, remoteAddress, 1);
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * Aparf initiates with maximal rate and power.
+ */
+ WifiTxVector txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ WifiMode mode = txVector.GetMode();
+ int power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Initial data rate wrong");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "APARF: Initial power level wrong");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As Aparf starts in state High, after 3 consecutive successful transmissions aparf increase rate or decrease power.
+ * As we are at maximal rate, the power should be decreased.
+ * Change to state Spread.
+ */
+ for(int i = 0; i<3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * One failure make the power to be increased again.
+ * Change to state Low.
+ */
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are in state Low we need 10 successful transmissions to increase rate or decrease power.
+ * As we are at maximal rate, the power should be decreased.
+ * Change to state Spread.
+ */
+ for(int i = 0; i<10; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * One more successful transmission make to change to state High.
+ * Two more successful transmissions make power decrease.
+ */
+
+ for(int i = 0; i<3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 15, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are in state High we need 3 successful transmissions to increase rate or decrease power.
+ * After 16*3 successful transmissions power is decreased to zero.
+ */
+ for(int i = 0; i<16*3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 0, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After one fail the rate is decreased or the power increased.
+ * As we are at minimal power, the power should be increased.
+ */
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 1, "Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After one fail the rate is decreased or the power increased.
+ * After 16 failed transmissions power is increase to 17.
+ */
+ for(int i = 0; i<16; i++)
+ {
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After one fail the rate is decreased or the power increased.
+ * As we are at maximal power, the rate should be decreased.
+ * Set critical rate to 54 Mbps.
+ */
+ manager->ReportDataFailed(remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 48000000, "Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are in state High we need 3 successful transmissions to increase rate or decrease power.
+ * As rate critical is set, after 3 successful transmissions power is decreased.
+ */
+ for(int i = 0; i<3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 48000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "APARF: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As we are in state High we need 3 successful transmissions to increase rate or decrease power.
+ * After 10 power changes critical rate is reseted.
+ * So after 10*3 successful transmissions critical rate is set to 0.
+ * And 3 successful transmissions more will make power increase to maximum and rate increase to the critical rate.
+ */
+ for(int i = 0; i<9*3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 48000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 7, "APARF: Incorrect value of power level");
+
+ for(int i = 0; i<3; i++)
+ {
+ manager->ReportDataOk(remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector(remoteAddress,&packetHeader,packet,packet->GetSize());
+ mode = txVector.GetMode();
+ power = (int) txVector.GetTxPowerLevel();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate(), 54000000, "APARF: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "APARF: Incorrect value of power level");
+
+ Simulator::Stop (Seconds (10.0));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+}
+
+void
+PowerRateAdaptationTest::DoRun (void)
+{
+
+ TestParf ();
+ TestAparf ();
+}
+
+//-----------------------------------------------------------------------------
+class PowerRateAdaptationTestSuite : public TestSuite
+{
+public:
+ PowerRateAdaptationTestSuite ();
+};
+
+PowerRateAdaptationTestSuite::PowerRateAdaptationTestSuite ()
+ : TestSuite ("power-rate-adaptation-wifi", UNIT)
+{
+ AddTestCase (new PowerRateAdaptationTest, TestCase::QUICK);
+}
+
+static PowerRateAdaptationTestSuite g_powerRateAdaptationTestSuite;
--- a/src/wifi/wscript Sat Jan 24 23:16:24 2015 +0100
+++ b/src/wifi/wscript Sun Jan 25 11:21:46 2015 -0800
@@ -63,6 +63,8 @@
'model/snr-tag.cc',
'model/ht-capabilities.cc',
'model/wifi-tx-vector.cc',
+ 'model/parf-wifi-manager.cc',
+ 'model/aparf-wifi-manager.cc',
'helper/ht-wifi-mac-helper.cc',
'helper/athstats-helper.cc',
'helper/wifi-helper.cc',
@@ -76,6 +78,7 @@
'test/block-ack-test-suite.cc',
'test/dcf-manager-test.cc',
'test/tx-duration-test.cc',
+ 'test/power-rate-adaptation-test.cc',
'test/wifi-test.cc',
]
@@ -139,6 +142,8 @@
'model/block-ack-cache.h',
'model/snr-tag.h',
'model/ht-capabilities.h',
+ 'model/parf-wifi-manager.h',
+ 'model/aparf-wifi-manager.h',
'model/wifi-tx-vector.h',
'helper/ht-wifi-mac-helper.h',
'helper/athstats-helper.h',