From ba433f9a207d6fd6af6945dbe6e2f39928c5248e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Deronne?=
Date: Wed, 15 Feb 2017 23:44:05 +0100
Subject: [PATCH] wifi: add RRPAA wifi rate control (patch from Matias Richart)
---
CHANGES.html | 1 +
doc/doxygen.conf | 6 +-
examples/wireless/examples-to-run.py | 1 +
.../wireless/power-adaptation-distance.cc | 87 ++-
.../wireless/power-adaptation-interference.cc | 86 ++-
.../traced-callback-typedef-test-suite.cc | 146 ++--
src/wifi/model/aparf-wifi-manager.cc | 91 +--
src/wifi/model/aparf-wifi-manager.h | 8 +-
src/wifi/model/parf-wifi-manager.cc | 74 +-
src/wifi/model/parf-wifi-manager.h | 6 +-
src/wifi/model/rrpaa-wifi-manager.cc | 644 ++++++++++++++++++
src/wifi/model/rrpaa-wifi-manager.h | 239 +++++++
src/wifi/model/wifi-phy.h | 20 +-
src/wifi/model/wifi-remote-station-manager.h | 11 +-
src/wifi/test/power-rate-adaptation-test.cc | 438 ++++++++++++
src/wifi/wscript | 2 +
16 files changed, 1615 insertions(+), 245 deletions(-)
create mode 100644 src/wifi/model/rrpaa-wifi-manager.cc
create mode 100644 src/wifi/model/rrpaa-wifi-manager.h
diff --git a/CHANGES.html b/CHANGES.html
index c078960bb..f46d3e29e 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -67,6 +67,7 @@ us a note on ns-developers mailing list.
A new information element has been added: HeCapabilities. This information element is added to the MAC frame header if the node is a HE node. This HeCapabilites information element is used to advertise the HE capabilites of the node to other nodes in the network.
+ A new class were added for the RRPAA WiFi rate control mechanism.
Included carrier aggregation feature in LTE module
- LTE model is extended to support carrier aggregation feature according to 3GPP Release 10, for up to 5 component
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
index addac3f75..a212cbffc 100644
--- a/doc/doxygen.conf
+++ b/doc/doxygen.conf
@@ -434,7 +434,7 @@ LOOKUP_CACHE_SIZE = 1
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
-EXTRACT_ALL = YES
+EXTRACT_ALL = no
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
@@ -732,7 +732,7 @@ QUIET = NO
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
-WARNINGS = YES
+WARNINGS = no
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
@@ -2205,7 +2205,7 @@ HIDE_UNDOC_RELATIONS = YES
# set to NO
# The default value is: NO.
-HAVE_DOT = YES
+HAVE_DOT = no
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py
index 596f71d4a..78cec1d0c 100755
--- a/examples/wireless/examples-to-run.py
+++ b/examples/wireless/examples-to-run.py
@@ -26,6 +26,7 @@ cpp_examples = [
("wifi-wired-bridging", "True", "True"),
("power-adaptation-distance --manager=ns3::ParfWifiManager --outputFileName=parf --steps=5 --stepsSize=10", "True", "True"),
("power-adaptation-distance --manager=ns3::AparfWifiManager --outputFileName=aparf --steps=5 --stepsSize=10", "True", "True"),
+ ("power-adaptation-distance --manager=ns3::RrpaaWifiManager --outputFileName=rrpaa --steps=5 --stepsSize=10", "True", "True"),
("ofdm-ht-validation", "True", "True"),
("ofdm-validation", "True", "True"),
("ofdm-vht-validation", "True", "True"),
diff --git a/examples/wireless/power-adaptation-distance.cc b/examples/wireless/power-adaptation-distance.cc
index 345ed9f9a..98c22291d 100644
--- a/examples/wireless/power-adaptation-distance.cc
+++ b/examples/wireless/power-adaptation-distance.cc
@@ -19,12 +19,12 @@
*/
/**
- * This example program is designed to illustrate the behavior of two
- * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager
- * and ns3::AparfWifiManager.
+ * This example program is designed to illustrate the behavior of three
+ * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager,
+ * ns3::AparfWifiManager and ns3::RrpaaWifiManager.
*
* 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
+ * (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}
@@ -59,7 +59,7 @@
* 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
+ * When neither Parf, Aparf or Rrpaa 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.
@@ -97,7 +97,7 @@ using namespace std;
NS_LOG_COMPONENT_DEFINE ("PowerAdaptationDistance");
-// packet size generated at the AP
+//packet size generated at the AP
static const uint32_t packetSize = 1420;
class NodeStatistics
@@ -107,8 +107,8 @@ public:
void PhyCallback (std::string path, Ptr packet);
void RxCallback (std::string path, Ptr 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 PowerCallback (std::string path, double oldPower, double newPower, Mac48Address dest);
+ void RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest);
void SetPosition (Ptr node, Vector position);
void AdvancePosition (Ptr node, int stepsSize, int stepsTime);
Vector GetPosition (Ptr node);
@@ -116,13 +116,14 @@ public:
Gnuplot2dDataset GetDatafile ();
Gnuplot2dDataset GetPowerDatafile ();
-private:
- typedef std::vector > TxTime;
- void SetupPhy (Ptr phy);
- Time GetCalcTxTime (WifiMode mode);
- std::map actualPower;
- std::map actualMode;
+private:
+ typedef std::vector > TxTime;
+ void SetupPhy (Ptr phy);
+ Time GetCalcTxTime (DataRate rate);
+
+ std::map currentPower;
+ std::map currentRate;
uint32_t m_bytesTotal;
double totalEnergy;
double totalTime;
@@ -139,15 +140,17 @@ NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
Ptr phy = wifiDevice->GetPhy ();
myPhy = phy;
SetupPhy (phy);
+ DataRate dataRate = DataRate (phy->GetMode (0).GetDataRate (phy->GetChannelWidth ()));
+ double power = phy->GetTxPowerEnd ();
for (uint32_t j = 0; j < stas.GetN (); j++)
{
Ptr staDevice = stas.Get (j);
Ptr wifiStaDevice = DynamicCast (staDevice);
Mac48Address addr = wifiStaDevice->GetMac ()->GetAddress ();
- actualPower[addr] = 17;
- actualMode[addr] = phy->GetMode (0);
+ currentPower[addr] = power;
+ currentRate[addr] = dataRate;
}
- actualMode[Mac48Address ("ff:ff:ff:ff:ff:ff")] = phy->GetMode (0);
+ currentRate[Mac48Address ("ff:ff:ff:ff:ff:ff")] = dataRate;
totalEnergy = 0;
totalTime = 0;
m_bytesTotal = 0;
@@ -165,16 +168,20 @@ NodeStatistics::SetupPhy (Ptr phy)
WifiTxVector txVector;
txVector.SetMode (mode);
txVector.SetPreambleType (WIFI_PREAMBLE_LONG);
- timeTable.push_back (std::make_pair (phy->CalculateTxDuration (packetSize, txVector, phy->GetFrequency ()), mode));
+ txVector.SetChannelWidth (phy->GetChannelWidth ());
+ DataRate dataRate = DataRate (mode.GetDataRate (phy->GetChannelWidth ()));
+ Time time = phy->CalculateTxDuration (packetSize, txVector, phy->GetFrequency ());
+ NS_LOG_DEBUG (i << " " << time.GetSeconds () << " " << dataRate);
+ timeTable.push_back (std::make_pair (time, dataRate));
}
}
Time
-NodeStatistics::GetCalcTxTime (WifiMode mode)
+NodeStatistics::GetCalcTxTime (DataRate rate)
{
for (TxTime::const_iterator i = timeTable.begin (); i != timeTable.end (); i++)
{
- if (mode == i->second)
+ if (rate == i->second)
{
return i->first;
}
@@ -192,34 +199,21 @@ NodeStatistics::PhyCallback (std::string path, Ptr packet)
if (head.GetType () == WIFI_MAC_DATA)
{
- totalEnergy += pow (10.0, actualPower[dest] / 10.0) * GetCalcTxTime (actualMode[dest]).GetSeconds ();
- totalTime += GetCalcTxTime (actualMode[dest]).GetSeconds ();
+ totalEnergy += pow (10.0, currentPower[dest] / 10.0) * GetCalcTxTime (currentRate[dest]).GetSeconds ();
+ totalTime += GetCalcTxTime (currentRate[dest]).GetSeconds ();
}
}
void
-NodeStatistics::PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+NodeStatistics::PowerCallback (std::string path, double oldPower, double newPower, 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;
+ currentPower[dest] = newPower;
}
void
-NodeStatistics::RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+NodeStatistics::RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest)
{
- actualMode[dest] = myPhy->GetMode (rate);
+ currentRate[dest] = newRate;
}
void
@@ -271,14 +265,14 @@ NodeStatistics::GetPowerDatafile ()
return m_output_power;
}
-void PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+void PowerCallback (std::string path, double oldPower, double newPower, Mac48Address dest)
{
- NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Power " << (int)power);
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Old power=" << oldPower << " New power=" << newPower);
}
-void RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+void RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest)
{
- NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Rate " << rate);
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Old rate=" << oldRate << " New rate=" << newRate);
}
int main (int argc, char *argv[])
@@ -322,7 +316,7 @@ int main (int argc, char *argv[])
uint32_t simuTime = (steps + 1) * stepsTime;
- // Define the APs
+ //Define the APs
NodeContainer wifiApNodes;
wifiApNodes.Create (1);
@@ -366,7 +360,7 @@ int main (int argc, char *argv[])
wifiDevices.Add (wifiStaDevices);
wifiDevices.Add (wifiApDevices);
- // Configure the mobility.
+ //Configure the mobility.
MobilityHelper mobility;
Ptr positionAlloc = CreateObject ();
//Initial position of AP and STA
@@ -443,7 +437,8 @@ int main (int argc, char *argv[])
gnuplot.GenerateOutput (outfile);
if (manager.compare ("ns3::ParfWifiManager") == 0
- || manager.compare ("ns3::AparfWifiManager") == 0)
+ || manager.compare ("ns3::AparfWifiManager") == 0
+ || manager.compare ("ns3::RrpaaWifiManager") == 0)
{
std::ofstream outfile2 (("power-" + outputFileName + ".plt").c_str ());
gnuplot = Gnuplot (("power-" + outputFileName + ".eps").c_str (), "Average Transmit Power");
diff --git a/examples/wireless/power-adaptation-interference.cc b/examples/wireless/power-adaptation-interference.cc
index ca03d8041..eb3201ca7 100644
--- a/examples/wireless/power-adaptation-interference.cc
+++ b/examples/wireless/power-adaptation-interference.cc
@@ -19,9 +19,9 @@
*/
/**
- * This example program is designed to illustrate the behavior of two
- * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager
- * and ns3::AparfWifiManager.
+ * This example program is designed to illustrate the behavior of three
+ * power/rate-adaptive WiFi rate controls; namely, ns3::ParfWifiManager,
+ * ns3::AparfWifiManager and ns3::RrpaaWifiManager.
*
* 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.
@@ -68,7 +68,7 @@ using namespace std;
NS_LOG_COMPONENT_DEFINE ("PowerAdaptationInterference");
-// packet size generated at the AP
+//Packet size generated at the AP.
static const uint32_t packetSize = 1420;
class NodeStatistics
@@ -80,8 +80,8 @@ public:
void PhyCallback (std::string path, Ptr packet);
void RxCallback (std::string path, Ptr 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 PowerCallback (std::string path, double oldPower, double newPower, Mac48Address dest);
+ void RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest);
void StateCallback (std::string path, Time init, Time duration, enum WifiPhy::State state);
Gnuplot2dDataset GetDatafile ();
@@ -94,12 +94,12 @@ public:
double GetBusyTime ();
private:
- typedef std::vector > TxTime;
+ typedef std::vector > TxTime;
void SetupPhy (Ptr phy);
- Time GetCalcTxTime (WifiMode mode);
+ Time GetCalcTxTime (DataRate rate);
- std::map actualPower;
- std::map actualMode;
+ std::map currentPower;
+ std::map currentRate;
uint32_t m_bytesTotal;
double totalEnergy;
double totalTime;
@@ -128,15 +128,17 @@ NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
Ptr phy = wifiDevice->GetPhy ();
myPhy = phy;
SetupPhy (phy);
+ DataRate dataRate = DataRate (phy->GetMode (0).GetDataRate (phy->GetChannelWidth ()));
+ double power = phy->GetTxPowerEnd ();
for (uint32_t j = 0; j < stas.GetN (); j++)
{
Ptr staDevice = stas.Get (j);
Ptr wifiStaDevice = DynamicCast (staDevice);
Mac48Address addr = wifiStaDevice->GetMac ()->GetAddress ();
- actualPower[addr] = 17;
- actualMode[addr] = phy->GetMode (0);
+ currentPower[addr] = power;
+ currentRate[addr] = dataRate;
}
- actualMode[Mac48Address ("ff:ff:ff:ff:ff:ff")] = phy->GetMode (0);
+ currentRate[Mac48Address ("ff:ff:ff:ff:ff:ff")] = dataRate;
totalEnergy = 0;
totalTime = 0;
busyTime = 0;
@@ -165,16 +167,20 @@ NodeStatistics::SetupPhy (Ptr phy)
WifiTxVector txVector;
txVector.SetMode (mode);
txVector.SetPreambleType (WIFI_PREAMBLE_LONG);
- timeTable.push_back (std::make_pair (phy->CalculateTxDuration (packetSize, txVector, phy->GetFrequency ()), mode));
+ txVector.SetChannelWidth (phy->GetChannelWidth ());
+ DataRate dataRate = DataRate (mode.GetDataRate (phy->GetChannelWidth ()));
+ Time time = phy->CalculateTxDuration (packetSize, txVector, phy->GetFrequency ());
+ NS_LOG_DEBUG (i << " " << time.GetSeconds () << " " << dataRate);
+ timeTable.push_back (std::make_pair (time, dataRate));
}
}
Time
-NodeStatistics::GetCalcTxTime (WifiMode mode)
+NodeStatistics::GetCalcTxTime (DataRate rate)
{
for (TxTime::const_iterator i = timeTable.begin (); i != timeTable.end (); i++)
{
- if (mode == i->second)
+ if (rate == i->second)
{
return i->first;
}
@@ -192,34 +198,21 @@ NodeStatistics::PhyCallback (std::string path, Ptr packet)
if (head.GetType () == WIFI_MAC_DATA)
{
- totalEnergy += pow (10.0, actualPower[dest] / 10.0) * GetCalcTxTime (actualMode[dest]).GetSeconds ();
- totalTime += GetCalcTxTime (actualMode[dest]).GetSeconds ();
+ totalEnergy += pow (10.0, currentPower[dest] / 10.0) * GetCalcTxTime (currentRate[dest]).GetSeconds ();
+ totalTime += GetCalcTxTime (currentRate[dest]).GetSeconds ();
}
}
void
-NodeStatistics::PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+NodeStatistics::PowerCallback (std::string path, double oldPower, double newPower, 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;
+ currentPower[dest] = newPower;
}
void
-NodeStatistics::RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+NodeStatistics::RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest)
{
- actualMode[dest] = myPhy->GetMode (rate);
+ currentRate[dest] = newRate;
}
void
@@ -318,16 +311,14 @@ NodeStatistics::GetBusyTime ()
return totalBusyTime + totalRxTime;
}
-void PowerCallback (std::string path, uint8_t power, Mac48Address dest)
+void PowerCallback (std::string path, double oldPower, double newPower, Mac48Address dest)
{
- NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Power " << (int)power);
- // end PowerCallback
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Old power=" << oldPower << " New power=" << newPower);
}
-void RateCallback (std::string path, uint32_t rate, Mac48Address dest)
+void RateCallback (std::string path, DataRate oldRate, DataRate newRate, Mac48Address dest)
{
- NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Rate " << rate);
- // end PowerCallback
+ NS_LOG_INFO ((Simulator::Now ()).GetSeconds () << " " << dest << " Old rate=" << oldRate << " New rate=" << newRate);
}
int main (int argc, char *argv[])
@@ -370,7 +361,7 @@ int main (int argc, char *argv[])
cmd.AddValue ("STA2_y", "Position of STA2 in y coordinate", sta2_y);
cmd.Parse (argc, argv);
- // Define the APs
+ //Define the APs
NodeContainer wifiApNodes;
wifiApNodes.Create (2);
@@ -427,7 +418,7 @@ int main (int argc, char *argv[])
wifiDevices.Add (wifiStaDevices);
wifiDevices.Add (wifiApDevices);
- // Configure the mobility.
+ //Configure the mobility.
MobilityHelper mobility;
Ptr positionAlloc = CreateObject ();
positionAlloc->Add (Vector (ap1_x, ap1_y, 0.0));
@@ -520,8 +511,7 @@ int main (int argc, char *argv[])
MakeCallback (RateCallback));
- // Calculate Throughput using Flowmonitor
- //
+ //Calculate Throughput using Flowmonitor
FlowMonitorHelper flowmon;
Ptr monitor = flowmon.InstallAll ();
@@ -566,7 +556,8 @@ int main (int argc, char *argv[])
gnuplot.GenerateOutput (outfileTh0);
if (manager.compare ("ns3::ParfWifiManager") == 0
- || manager.compare ("ns3::AparfWifiManager") == 0)
+ || manager.compare ("ns3::AparfWifiManager") == 0
+ || manager.compare ("ns3::RrpaaWifiManager") == 0)
{
std::ofstream outfilePower0 (("power-" + outputFileName + "-0.plt").c_str ());
gnuplot = Gnuplot (("power-" + outputFileName + "-0.eps").c_str (), "Average Transmit Power");
@@ -619,7 +610,8 @@ int main (int argc, char *argv[])
gnuplot.GenerateOutput (outfileTh1);
if (manager.compare ("ns3::ParfWifiManager") == 0
- || manager.compare ("ns3::AparfWifiManager") == 0)
+ || manager.compare ("ns3::AparfWifiManager") == 0
+ || manager.compare ("ns3::RrpaaWifiManager") == 0)
{
std::ofstream outfilePower1 (("power-" + outputFileName + "-1.plt").c_str ());
gnuplot = Gnuplot (("power-" + outputFileName + "-1.eps").c_str (), "Average Transmit Power");
diff --git a/src/test/traced/traced-callback-typedef-test-suite.cc b/src/test/traced/traced-callback-typedef-test-suite.cc
index 663ec745d..f6af3c72d 100644
--- a/src/test/traced/traced-callback-typedef-test-suite.cc
+++ b/src/test/traced/traced-callback-typedef-test-suite.cc
@@ -50,7 +50,9 @@ class TracedCallbackTypedefTestCase : public TestCase
{
public:
TracedCallbackTypedefTestCase ();
- virtual ~TracedCallbackTypedefTestCase () {}
+ virtual ~TracedCallbackTypedefTestCase ()
+ {
+ }
/**
* Number of arguments passed to callback.
@@ -61,24 +63,23 @@ public:
* in the CheckType() method.
*/
static int m_nArgs;
-
+
private:
-
/** Invoker boilerplate. */
template
class CheckerBase;
-
+
/** Callback checkers. */
template
class Checker;
-
+
template
class Checker;
template
class Checker;
-
+
template
class Checker;
@@ -111,13 +112,13 @@ Duplicates (void)
return dupes;
}
-
+
/**
* Container for duplicate types.
*/
std::set g_dupes = Duplicates ();
-
+
/**
* Stringify the known TracedCallback type names.
*
@@ -125,16 +126,21 @@ std::set g_dupes = Duplicates ();
* \param [in] N The number of arguments expected.
* \returns The \c TracedCallback type name.
*/
-template inline
-std::string TypeName (int N) { return "unknown"; }
+template
+inline
+std::string TypeName (int N)
+{
+ return "unknown";
+}
-#define TYPENAME(T) \
- template <> inline std::string \
- TypeName < T > (int N) \
- { \
- std::stringstream ss; \
+#define TYPENAME(T) \
+ template <> \
+ inline std::string \
+ TypeName < T > (int N) \
+ { \
+ std::stringstream ss; \
ss << # T << "(" << N << ")"; \
- return ss.str (); \
+ return ss.str (); \
}
/**
@@ -160,12 +166,12 @@ TYPENAME (LteEnbRrc::ConnectionHandoverTracedCallback);
TYPENAME (LteEnbRrc::HandoverStartTracedCallback);
TYPENAME (LteEnbRrc::NewUeContextTracedCallback);
TYPENAME (LteEnbRrc::ReceiveReportTracedCallback);
-TYPENAME (LtePdcp::PduRxTracedCallback);
+TYPENAME (LtePdcp::PduRxTracedCallback);
TYPENAME (LtePdcp::PduTxTracedCallback);
TYPENAME (LteUePhy::StateTracedCallback);
-TYPENAME (LteUePhy::RsrpSinrTracedCallback);
+TYPENAME (LteUePhy::RsrpSinrTracedCallback);
TYPENAME (LteUeRrc::CellSelectionTracedCallback);
-TYPENAME (LteUeRrc::StateTracedCallback);
+TYPENAME (LteUeRrc::StateTracedCallback);
TYPENAME (Mac48Address::TracedCallback);
TYPENAME (MobilityModel::TracedCallback);
TYPENAME (olsr::RoutingProtocol::PacketTxRxTracedCallback);
@@ -222,35 +228,50 @@ template
class TracedCbSink
{
public:
- static void Sink (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { SinkIt (5); }
+ static void Sink (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+ {
+ SinkIt (5);
+ }
};
template
class TracedCbSink
{
public:
- static void Sink (T1 a1, T2 a2, T3 a3, T4 a4) { SinkIt (4); }
+ static void Sink (T1 a1, T2 a2, T3 a3, T4 a4)
+ {
+ SinkIt (4);
+ }
};
template
class TracedCbSink
{
public:
- static void Sink (T1 a1, T2 a2, T3 a3) { SinkIt (3); }
+ static void Sink (T1 a1, T2 a2, T3 a3)
+ {
+ SinkIt (3);
+ }
};
template
class TracedCbSink
{
public:
- static void Sink (T1 a1, T2 a2) { SinkIt (2); }
+ static void Sink (T1 a1, T2 a2)
+ {
+ SinkIt (2);
+ }
};
template
class TracedCbSink< T1, empty, empty, empty, empty>
{
public:
- static void Sink (T1 a1) { SinkIt (1); }
+ static void Sink (T1 a1)
+ {
+ SinkIt (1);
+ }
};
/** @} */
@@ -278,10 +299,13 @@ public:
typename TypeTraits::BaseType m3;
typename TypeTraits::BaseType m4;
typename TypeTraits::BaseType m5;
-
+
void Cleanup (int N)
{
- if (m_nArgs == 0) std::cout << std::endl;
+ if (m_nArgs == 0)
+ {
+ std::cout << std::endl;
+ }
NS_ASSERT_MSG (m_nArgs && m_nArgs == N, "failed.");
m_nArgs = 0;
}
@@ -291,7 +315,7 @@ template
class TracedCallbackTypedefTestCase::Checker : public CheckerBase
{
TracedCallback m_cb;
-
+
public:
template
void Invoke (void)
@@ -299,7 +323,7 @@ public:
const int N = 5;
U sink = TracedCbSink::Sink;
Callback cb = MakeCallback (sink);
-
+
std::cout << TypeName (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2, this->m3, this->m4, this->m5);
@@ -312,7 +336,7 @@ class TracedCallbackTypedefTestCase::Checker
: public CheckerBase
{
TracedCallback m_cb;
-
+
public:
template
void Invoke (void)
@@ -320,20 +344,20 @@ public:
const int N = 4;
U sink = TracedCbSink::Sink;
Callback cb = MakeCallback (sink);
-
+
std::cout << TypeName (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2, this->m3, this->m4);
this->Cleanup (N);
}
}; // Checker <4>
-
+
template
class TracedCallbackTypedefTestCase::Checker
: public CheckerBase
{
TracedCallback m_cb;
-
+
public:
template
void Invoke (void)
@@ -341,7 +365,7 @@ public:
const int N = 3;
U sink = TracedCbSink::Sink;
Callback cb = MakeCallback (sink);
-
+
std::cout << TypeName (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2, this->m3);
@@ -354,7 +378,7 @@ class TracedCallbackTypedefTestCase::Checker
: public CheckerBase
{
TracedCallback m_cb;
-
+
public:
template
void Invoke (void)
@@ -362,7 +386,7 @@ public:
const int N = 2;
U sink = TracedCbSink::Sink;
Callback cb = MakeCallback (sink);
-
+
std::cout << TypeName (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2);
@@ -375,7 +399,7 @@ class TracedCallbackTypedefTestCase::Checker
: public CheckerBase
{
TracedCallback m_cb;
-
+
public:
template
void Invoke (void)
@@ -383,7 +407,7 @@ public:
const int N = 1;
U sink = TracedCbSink::Sink;
Callback cb = MakeCallback (sink);
-
+
std::cout << TypeName (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1);
@@ -401,20 +425,20 @@ TracedCallbackTypedefTestCase::DoRun (void)
{
#define DUPE(U, T1) \
- if (g_dupes.find ( # U ) == g_dupes.end ()) \
- NS_TEST_ASSERT_MSG_NE (0, 1, \
- "expected to find " << # U << " in dupes."); \
- if (TypeName (0) == TypeName (0)) \
- std::cout << # U << " matches " << # T1 << std::endl; \
+ if (g_dupes.find ( # U ) == g_dupes.end ()) { \
+ NS_TEST_ASSERT_MSG_NE (0, 1, \
+ "expected to find " << # U << " in dupes."); } \
+ if (TypeName (0) == TypeName (0)) { \
+ std::cout << # U << " matches " << # T1 << std::endl; } \
else \
NS_TEST_ASSERT_MSG_EQ \
(TypeName (0), TypeName (0), \
- "the typedef " << # U << \
- " used to match the typedef " << # T1 << \
- " but no longer does. Please add a new CHECK call.")
+ "the typedef " << # U << \
+ " used to match the typedef " << # T1 << \
+ " but no longer does. Please add a new CHECK call.")
#define CHECK(U, T1, T2, T3, T4, T5) \
- CreateObject< Checker > () -> Invoke ()
+ CreateObject< Checker > ()->Invoke ()
CHECK (dsr::DsrOptionSRHeader::TracedCallback,
const dsr::DsrOptionSRHeader &,
@@ -435,11 +459,11 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (Ipv4L3Protocol::TxRxTracedCallback,
Ptr, Ptr, uint32_t,
empty, empty);
-
+
CHECK (Ipv6L3Protocol::DropTracedCallback,
const Ipv6Header &, Ptr,
Ipv6L3Protocol::DropReason, Ptr, uint32_t
- );
+ );
CHECK (Ipv6L3Protocol::SentTracedCallback,
const Ipv6Header &, Ptr, uint32_t,
@@ -461,7 +485,7 @@ TracedCallbackTypedefTestCase::DoRun (void)
Time, LrWpanPhyEnumeration, LrWpanPhyEnumeration,
empty, empty);
-
+
/* Too many args :(
CHECK (LteEnbMac::DlSchedulingTracedCallback,
uint32_t, uint32_t, uint16_t,
@@ -486,7 +510,7 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (LteEnbRrc::HandoverStartTracedCallback,
uint64_t, uint16_t, uint16_t, uint16_t,
empty);
-
+
CHECK (LteEnbRrc::NewUeContextTracedCallback,
uint16_t, uint16_t,
empty, empty, empty);
@@ -524,7 +548,7 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (LteUeRrc::StateTracedCallback,
uint64_t, uint16_t, uint16_t, LteUeRrc::State, LteUeRrc::State);
-
+
CHECK (Mac48Address::TracedCallback,
Mac48Address,
empty, empty, empty, empty);
@@ -568,7 +592,7 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (dot11s::PeerManagementProtocol::LinkOpenCloseTracedCallback,
Mac48Address, Mac48Address,
empty, empty, empty);
-
+
CHECK (PhyReceptionStatParameters::TracedCallback,
PhyReceptionStatParameters,
empty, empty, empty, empty);
@@ -589,7 +613,7 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (SpectrumChannel::LossTracedCallback,
Ptr, Ptr, double,
empty, empty);
-
+
CHECK (SpectrumValue::TracedCallback,
Ptr,
empty, empty, empty, empty);
@@ -601,11 +625,11 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (UanMac::PacketModeTracedCallback,
Ptr, UanTxMode,
empty, empty, empty);
-
+
CHECK (UanMacCw::QueueTracedCallback,
Ptr, uint16_t,
empty, empty, empty);
-
+
CHECK (UanMacRc::QueueTracedCallback,
Ptr, uint32_t,
empty, empty, empty);
@@ -613,14 +637,14 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (UanNetDevice::RxTxTracedCallback,
Ptr, UanAddress,
empty, empty, empty);
-
+
CHECK (UanPhy::TracedCallback,
Ptr, double, UanTxMode,
empty, empty);
CHECK (UeManager::StateTracedCallback,
uint64_t, uint16_t, uint16_t, UeManager::State, UeManager::State);
-
+
CHECK (WifiMacHeader::TracedCallback,
const WifiMacHeader &,
empty, empty, empty, empty);
@@ -642,12 +666,12 @@ TracedCallbackTypedefTestCase::DoRun (void)
empty);
CHECK (WifiRemoteStationManager::PowerChangeTracedCallback,
- uint8_t, Mac48Address,
- empty, empty, empty);
+ double, double, Mac48Address,
+ empty, empty);
CHECK (WifiRemoteStationManager::RateChangeTracedCallback,
- uint32_t, Mac48Address,
- empty, empty, empty);
+ DataRate, DataRate, Mac48Address,
+ empty, empty);
}
class TracedCallbackTypedefTestSuite : public TestSuite
diff --git a/src/wifi/model/aparf-wifi-manager.cc b/src/wifi/model/aparf-wifi-manager.cc
index 6f730daff..9eb92a3f3 100644
--- a/src/wifi/model/aparf-wifi-manager.cc
+++ b/src/wifi/model/aparf-wifi-manager.cc
@@ -43,9 +43,11 @@ AparfWifiRemoteStation : public WifiRemoteStation
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_prevRateIndex; //!< Rate index of the previous transmission.
+ uint32_t m_rateIndex; //!< Current rate index.
+ uint32_t m_critRateIndex; //!< Critical rate.
+ uint8_t m_prevPowerLevel; //!< Power level of the previous transmission.
+ uint8_t m_powerLevel; //!< Current power level.
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.
@@ -144,8 +146,8 @@ AparfWifiManager::DoCreateStation (void) const
station->m_aparfState = AparfWifiManager::High;
station->m_initialized = false;
- NS_LOG_DEBUG ("create station=" << station << ", rate=" << station->m_rate
- << ", power=" << (int)station->m_power);
+ NS_LOG_DEBUG ("create station=" << station << ", rate=" << station->m_rateIndex
+ << ", power=" << (int)station->m_powerLevel);
return station;
}
@@ -156,11 +158,17 @@ AparfWifiManager::CheckInit (AparfWifiRemoteStation *station)
if (!station->m_initialized)
{
station->m_nSupported = GetNSupported (station);
- station->m_rate = station->m_nSupported - 1;
- station->m_power = m_maxPower;
- 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_rateIndex = station->m_nSupported - 1;
+ station->m_prevRateIndex = station->m_nSupported - 1;
+ station->m_powerLevel = m_maxPower;
+ station->m_prevPowerLevel = m_maxPower;
+ station->m_critRateIndex = 0;
+ WifiMode mode = GetSupported (station, station->m_rateIndex);
+ uint8_t channelWidth = GetChannelWidth (station);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (m_maxPower);
+ m_powerChange (power, power, station->m_state->m_address);
+ m_rateChange (rate, rate, station->m_state->m_address);
station->m_initialized = true;
}
}
@@ -177,8 +185,8 @@ void AparfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
CheckInit (station);
station->m_nFailed++;
station->m_nSuccess = 0;
- NS_LOG_DEBUG ("station=" << station << ", rate=" << station->m_rate
- << ", power=" << (int)station->m_power);
+ NS_LOG_DEBUG ("station=" << station << ", rate=" << station->m_rateIndex
+ << ", power=" << (int)station->m_powerLevel);
if (station->m_aparfState == AparfWifiManager::Low)
{
@@ -196,21 +204,19 @@ void AparfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
station->m_nFailed = 0;
station->m_nSuccess = 0;
station->m_pCount = 0;
- if (station->m_power == m_maxPower)
+ if (station->m_powerLevel == m_maxPower)
{
- station->m_rateCrit = station->m_rate;
- if (station->m_rate != 0)
+ station->m_critRateIndex = station->m_rateIndex;
+ if (station->m_rateIndex != 0)
{
NS_LOG_DEBUG ("station=" << station << " dec rate");
- station->m_rate -= m_rateDec;
- m_rateChange (station->m_rate, station->m_state->m_address);
+ station->m_rateIndex -= m_rateDec;
}
}
else
{
NS_LOG_DEBUG ("station=" << station << " inc power");
- station->m_power += m_powerInc;
- m_powerChange (station->m_power, station->m_state->m_address);
+ station->m_powerLevel += m_powerInc;
}
}
}
@@ -238,7 +244,7 @@ AparfWifiManager::DoReportDataOk (WifiRemoteStation *st, double ackSnr,
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);
+ NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_nSuccess << ", rate=" << station->m_rateIndex << ", power=" << (int)station->m_powerLevel);
if ((station->m_aparfState == AparfWifiManager::High) && (station->m_nSuccess >= station->m_successThreshold))
{
@@ -258,43 +264,38 @@ AparfWifiManager::DoReportDataOk (WifiRemoteStation *st, double ackSnr,
{
station->m_nSuccess = 0;
station->m_nFailed = 0;
- if (station->m_rate == (station->m_state->m_operationalRateSet.size () - 1))
+ if (station->m_rateIndex == (station->m_state->m_operationalRateSet.size () - 1))
{
- if (station->m_power != m_minPower)
+ if (station->m_powerLevel != m_minPower)
{
NS_LOG_DEBUG ("station=" << station << " dec power");
- station->m_power -= m_powerDec;
- m_powerChange (station->m_power, station->m_state->m_address);
+ station->m_powerLevel -= m_powerDec;
}
}
else
{
- if (station->m_rateCrit == 0)
+ if (station->m_critRateIndex == 0)
{
- if (station->m_rate != (station->m_state->m_operationalRateSet.size () - 1))
+ if (station->m_rateIndex != (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);
+ station->m_rateIndex += m_rateInc;
}
}
else
{
if (station->m_pCount == m_powerMax)
{
- station->m_power = m_maxPower;
- 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_powerLevel = m_maxPower;
+ station->m_rateIndex = station->m_critRateIndex;
station->m_pCount = 0;
- station->m_rateCrit = 0;
+ station->m_critRateIndex = 0;
}
else
{
- if (station->m_power != m_minPower)
+ if (station->m_powerLevel != m_minPower)
{
- station->m_power -= m_powerDec;
- m_powerChange (station->m_power, station->m_state->m_address);
+ station->m_powerLevel -= m_powerDec;
station->m_pCount++;
}
}
@@ -327,8 +328,22 @@ AparfWifiManager::DoGetDataTxVector (WifiRemoteStation *st)
channelWidth = 20;
}
CheckInit (station);
- WifiMode mode = GetSupported (station, station->m_rate);
- return WifiTxVector (mode, station->m_power, GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (st)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
+ WifiMode mode = GetSupported (station, station->m_rateIndex);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ DataRate prevRate = DataRate (GetSupported (station, station->m_prevRateIndex).GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (station->m_powerLevel);
+ double prevPower = GetPhy ()->GetPowerDbm (station->m_prevPowerLevel);
+ if (station->m_prevPowerLevel != station->m_powerLevel)
+ {
+ m_powerChange (prevPower, power, station->m_state->m_address);
+ station->m_prevPowerLevel = station->m_powerLevel;
+ }
+ if (station->m_prevRateIndex != station->m_rateIndex)
+ {
+ m_rateChange (prevRate, rate, station->m_state->m_address);
+ station->m_prevRateIndex = station->m_rateIndex;
+ }
+ return WifiTxVector (mode, station->m_powerLevel, GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (st)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
}
WifiTxVector
diff --git a/src/wifi/model/aparf-wifi-manager.h b/src/wifi/model/aparf-wifi-manager.h
index a74aeff5d..6df2a77f9 100644
--- a/src/wifi/model/aparf-wifi-manager.h
+++ b/src/wifi/model/aparf-wifi-manager.h
@@ -115,13 +115,13 @@ private:
uint32_t m_maxPower;
/**
- * The trace source fired when the transmission power change
+ * The trace source fired when the transmission power changes.
*/
- TracedCallback m_powerChange;
+ TracedCallback m_powerChange;
/**
- * The trace source fired when the transmission rate change
+ * The trace source fired when the transmission rate changes.
*/
- TracedCallback m_rateChange;
+ TracedCallback m_rateChange;
};
} //namespace ns3
diff --git a/src/wifi/model/parf-wifi-manager.cc b/src/wifi/model/parf-wifi-manager.cc
index 17536ecde..9987c1222 100644
--- a/src/wifi/model/parf-wifi-manager.cc
+++ b/src/wifi/model/parf-wifi-manager.cc
@@ -43,8 +43,10 @@ struct ParfWifiRemoteStation : public WifiRemoteStation
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_prevRateIndex; //!< Rate index of the previous transmission.
+ uint32_t m_rateIndex; //!< Current rate index used by the remote station.
+ uint8_t m_prevPowerLevel; //!< Power level of the previous transmission.
+ uint8_t m_powerLevel; //!< Current power level used by the remote station.
uint32_t m_nSupported; //!< Number of supported rates by the remote station.
bool m_initialized; //!< For initializing variables.
};
@@ -113,7 +115,7 @@ ParfWifiManager::DoCreateStation (void) const
station->m_nAttempt = 0;
NS_LOG_DEBUG ("create station=" << station << ", timer=" << station->m_nAttempt
- << ", rate=" << station->m_currentRate << ", power=" << (int)station->m_currentPower);
+ << ", rate=" << station->m_rateIndex << ", power=" << (int)station->m_powerLevel);
return station;
}
@@ -124,10 +126,16 @@ ParfWifiManager::CheckInit (ParfWifiRemoteStation *station)
if (!station->m_initialized)
{
station->m_nSupported = GetNSupported (station);
- station->m_currentRate = station->m_nSupported - 1;
- station->m_currentPower = m_maxPower;
- m_powerChange (station->m_currentPower, station->m_state->m_address);
- m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_rateIndex = station->m_nSupported - 1;
+ station->m_prevRateIndex = station->m_nSupported - 1;
+ station->m_powerLevel = m_maxPower;
+ station->m_prevPowerLevel = m_maxPower;
+ WifiMode mode = GetSupported (station, station->m_rateIndex);
+ uint8_t channelWidth = GetChannelWidth (station);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (m_maxPower);
+ m_powerChange (power, power, station->m_state->m_address);
+ m_rateChange (rate, rate, station->m_state->m_address);
station->m_initialized = true;
}
}
@@ -159,18 +167,17 @@ ParfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
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);
+ << ", rate=" << station->m_rateIndex << ", power=" << (int)station->m_powerLevel);
if (station->m_usingRecoveryRate)
{
NS_ASSERT (station->m_nRetry >= 1);
if (station->m_nRetry == 1)
{
//need recovery fallback
- if (station->m_currentRate != 0)
+ if (station->m_rateIndex != 0)
{
NS_LOG_DEBUG ("station=" << station << " dec rate");
- station->m_currentRate--;
- m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_rateIndex--;
station->m_usingRecoveryRate = false;
}
}
@@ -182,11 +189,10 @@ ParfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
if (station->m_nRetry == 1)
{
//need recovery fallback
- if (station->m_currentPower < m_maxPower)
+ if (station->m_powerLevel < m_maxPower)
{
NS_LOG_DEBUG ("station=" << station << " inc power");
- station->m_currentPower++;
- m_powerChange (station->m_currentPower, station->m_state->m_address);
+ station->m_powerLevel++;
station->m_usingRecoveryPower = false;
}
}
@@ -198,20 +204,18 @@ ParfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
if (((station->m_nRetry - 1) % 2) == 1)
{
//need normal fallback
- if (station->m_currentPower == m_maxPower)
+ if (station->m_powerLevel == m_maxPower)
{
- if (station->m_currentRate != 0)
+ if (station->m_rateIndex != 0)
{
NS_LOG_DEBUG ("station=" << station << " dec rate");
- station->m_currentRate--;
- m_rateChange (station->m_currentRate, station->m_state->m_address);
+ station->m_rateIndex--;
}
}
else
{
NS_LOG_DEBUG ("station=" << station << " inc power");
- station->m_currentPower++;
- m_powerChange (station->m_currentPower, station->m_state->m_address);
+ station->m_powerLevel++;
}
}
if (station->m_nRetry >= 2)
@@ -247,14 +251,13 @@ void ParfWifiManager::DoReportDataOk (WifiRemoteStation *st,
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);
+ NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_nSuccess << ", timer=" << station->m_nAttempt << ", rate=" << station->m_rateIndex << ", power=" << (int)station->m_powerLevel);
if ((station->m_nSuccess == m_successThreshold
|| station->m_nAttempt == m_attemptThreshold)
- && (station->m_currentRate < (station->m_state->m_operationalRateSet.size () - 1)))
+ && (station->m_rateIndex < (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_rateIndex++;
station->m_nAttempt = 0;
station->m_nSuccess = 0;
station->m_usingRecoveryRate = true;
@@ -262,11 +265,10 @@ void ParfWifiManager::DoReportDataOk (WifiRemoteStation *st,
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 != m_minPower)
+ if (station->m_powerLevel != m_minPower)
{
NS_LOG_DEBUG ("station=" << station << " dec power");
- station->m_currentPower--;
- m_powerChange (station->m_currentPower, station->m_state->m_address);
+ station->m_powerLevel--;
}
station->m_nAttempt = 0;
station->m_nSuccess = 0;
@@ -298,8 +300,22 @@ ParfWifiManager::DoGetDataTxVector (WifiRemoteStation *st)
channelWidth = 20;
}
CheckInit (station);
- WifiMode mode = GetSupported (station, station->m_currentRate);
- return WifiTxVector (mode, station->m_currentPower, GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
+ WifiMode mode = GetSupported (station, station->m_rateIndex);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ DataRate prevRate = DataRate (GetSupported (station, station->m_prevRateIndex).GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (station->m_powerLevel);
+ double prevPower = GetPhy ()->GetPowerDbm (station->m_prevPowerLevel);
+ if (station->m_prevPowerLevel != station->m_powerLevel)
+ {
+ m_powerChange (prevPower, power, station->m_state->m_address);
+ station->m_prevPowerLevel = station->m_powerLevel;
+ }
+ if (station->m_prevRateIndex != station->m_rateIndex)
+ {
+ m_rateChange (prevRate, rate, station->m_state->m_address);
+ station->m_prevRateIndex = station->m_rateIndex;
+ }
+ return WifiTxVector (mode, station->m_powerLevel, GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
}
WifiTxVector
diff --git a/src/wifi/model/parf-wifi-manager.h b/src/wifi/model/parf-wifi-manager.h
index 239e576f7..0c56c9420 100644
--- a/src/wifi/model/parf-wifi-manager.h
+++ b/src/wifi/model/parf-wifi-manager.h
@@ -97,13 +97,13 @@ private:
uint32_t m_maxPower;
/**
- * The trace source fired when the transmission power changes....
+ * The trace source fired when the transmission power changes.
*/
- TracedCallback m_powerChange;
+ TracedCallback m_powerChange;
/**
* The trace source fired when the transmission rate changes.
*/
- TracedCallback m_rateChange;
+ TracedCallback m_rateChange;
};
} //namespace ns3
diff --git a/src/wifi/model/rrpaa-wifi-manager.cc b/src/wifi/model/rrpaa-wifi-manager.cc
new file mode 100644
index 000000000..bf95e894d
--- /dev/null
+++ b/src/wifi/model/rrpaa-wifi-manager.cc
@@ -0,0 +1,644 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2017 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
+ */
+
+#include "rrpaa-wifi-manager.h"
+#include "yans-wifi-phy.h"
+#include "wifi-phy.h"
+#include "wifi-mac.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/simulator.h"
+#include
+
+NS_LOG_COMPONENT_DEFINE ("RrpaaWifiManager");
+
+namespace ns3 {
+
+/**
+ * Hold per-remote-station state for RRPAA Wifi manager.
+ *
+ * This struct extends from WifiRemoteStation struct to hold additional
+ * information required by the APARF Wifi manager
+ */
+struct RrpaaWifiRemoteStation : public WifiRemoteStation
+{
+ uint32_t m_counter; //!< Counter for transmission attempts.
+ uint32_t m_nFailed; //!< Number of failed transmission attempts.
+ uint32_t m_adaptiveRtsWnd; //!< Window size for the Adaptive RTS mechanism.
+ uint32_t m_rtsCounter; //!< Counter for RTS transmission attempts.
+ Time m_lastReset; //!< Time of the last reset.
+ bool m_adaptiveRtsOn; //!< Check if Adaptive RTS mechanism is on.
+ bool m_lastFrameFail; //!< Flag if the last frame sent has failed.
+ bool m_initialized; //!< For initializing variables.
+
+ uint32_t m_nRate; //!< Number of supported rates.
+
+ uint32_t m_prevRateIndex; //!< Rate index of the previous transmission.
+ uint32_t m_rateIndex; //!< Current rate index.
+ uint8_t m_prevPowerLevel; //!< Power level of the previous transmission.
+ uint8_t m_powerLevel; //!< Current power level.
+
+
+ RrpaaThresholdsTable m_thresholds; //!< Rrpaa thresholds for this station.
+
+ RrpaaProbabilitiesTable m_pdTable; //!< Probability table for power and rate changes.
+};
+
+NS_OBJECT_ENSURE_REGISTERED (RrpaaWifiManager);
+
+TypeId
+RrpaaWifiManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::RrpaaWifiManager")
+ .SetParent ()
+ .SetGroupName ("Wifi")
+ .AddConstructor ()
+ .AddAttribute ("Basic",
+ "If true the RRAA-BASIC algorithm will be used, otherwise the RRAA will be used.",
+ BooleanValue (true),
+ MakeBooleanAccessor (&RrpaaWifiManager::m_basic),
+ MakeBooleanChecker ())
+ .AddAttribute ("Timeout",
+ "Timeout for the RRAA-BASIC loss estimation block (s).",
+ TimeValue (MilliSeconds (500)),
+ MakeTimeAccessor (&RrpaaWifiManager::m_timeout),
+ MakeTimeChecker ())
+ .AddAttribute ("FrameLength",
+ "The data frame length (in bytes) used for calculating mode TxTime.",
+ UintegerValue (1420),
+ MakeUintegerAccessor (&RrpaaWifiManager::m_frameLength),
+ MakeUintegerChecker ())
+ .AddAttribute ("AckFrameLength",
+ "The ACK frame length (in bytes) used for calculating mode TxTime.",
+ UintegerValue (14),
+ MakeUintegerAccessor (&RrpaaWifiManager::m_ackLength),
+ MakeUintegerChecker ())
+ .AddAttribute ("Alpha",
+ "Constant for calculating the MTL threshold.",
+ DoubleValue (1.25),
+ MakeDoubleAccessor (&RrpaaWifiManager::m_alpha),
+ MakeDoubleChecker (1))
+ .AddAttribute ("Beta",
+ "Constant for calculating the ORI threshold.",
+ DoubleValue (2),
+ MakeDoubleAccessor (&RrpaaWifiManager::m_beta),
+ MakeDoubleChecker (1))
+ .AddAttribute ("Tau",
+ "Constant for calculating the EWND size.",
+ DoubleValue (0.015),
+ MakeDoubleAccessor (&RrpaaWifiManager::m_tau),
+ MakeDoubleChecker (0))
+ .AddAttribute ("Gamma",
+ "Constant for Probabilistic Decision Table decrements.",
+ DoubleValue (2),
+ MakeDoubleAccessor (&RrpaaWifiManager::m_gamma),
+ MakeDoubleChecker (1))
+ .AddAttribute ("Delta",
+ "Constant for Probabilistic Decision Table increments.",
+ DoubleValue (1.0905),
+ MakeDoubleAccessor (&RrpaaWifiManager::m_delta),
+ MakeDoubleChecker (1))
+ .AddTraceSource ("RateChange",
+ "The transmission rate has change.",
+ MakeTraceSourceAccessor (&RrpaaWifiManager::m_rateChange),
+ "ns3::WifiRemoteStationManager::RateChangeTracedCallback")
+ .AddTraceSource ("PowerChange",
+ "The transmission power has change.",
+ MakeTraceSourceAccessor (&RrpaaWifiManager::m_powerChange),
+ "ns3::WifiRemoteStationManager::PowerChangeTracedCallback")
+ ;
+ return tid;
+}
+
+
+RrpaaWifiManager::RrpaaWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+ m_uniformRandomVariable = CreateObject ();
+}
+
+RrpaaWifiManager::~RrpaaWifiManager ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+int64_t
+RrpaaWifiManager::AssignStreams (int64_t stream)
+{
+ NS_LOG_FUNCTION (this << stream);
+ m_uniformRandomVariable->SetStream (stream);
+ return 1;
+}
+
+void
+RrpaaWifiManager::SetupPhy (Ptr phy)
+{
+ NS_LOG_FUNCTION (this);
+ m_minPower = phy->GetTxPowerStart ();
+ m_maxPower = phy->GetTxPowerEnd ();
+ m_nPower = m_maxPower - m_minPower + 1;
+ uint32_t nModes = phy->GetNModes ();
+ for (uint32_t i = 0; i < nModes; i++)
+ {
+ WifiMode mode = phy->GetMode (i);
+ WifiTxVector txVector;
+ txVector.SetMode (mode);
+ txVector.SetPreambleType (WIFI_PREAMBLE_LONG);
+ /* Calculate the TX Time of the data and the corresponding ACK*/
+ Time dataTxTime = phy->CalculateTxDuration (m_frameLength, txVector, phy->GetFrequency ());
+ Time ackTxTime = phy->CalculateTxDuration (m_ackLength, txVector, phy->GetFrequency ());
+ NS_LOG_DEBUG ("Calculating TX times: Mode= " << mode << " DataTxTime= " << dataTxTime << " AckTxTime= " << ackTxTime);
+ AddCalcTxTime (mode, dataTxTime + ackTxTime);
+ }
+ WifiRemoteStationManager::SetupPhy (phy);
+}
+
+void
+RrpaaWifiManager::SetupMac (Ptr mac)
+{
+ NS_LOG_FUNCTION (this);
+ m_sifs = mac->GetSifs ();
+ m_difs = m_sifs + 2 * mac->GetSlot ();
+ WifiRemoteStationManager::SetupMac (mac);
+}
+
+Time
+RrpaaWifiManager::GetCalcTxTime (WifiMode mode) const
+{
+ NS_LOG_FUNCTION (this << mode);
+ for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
+ {
+ if (mode == i->second)
+ {
+ return i->first;
+ }
+ }
+ NS_ASSERT (false);
+ return Seconds (0);
+}
+
+void
+RrpaaWifiManager::AddCalcTxTime (WifiMode mode, Time t)
+{
+ NS_LOG_FUNCTION (this << mode << t);
+ m_calcTxTime.push_back (std::make_pair (t, mode));
+}
+
+Thresholds
+RrpaaWifiManager::GetThresholds (RrpaaWifiRemoteStation *station, WifiMode mode) const
+{
+ NS_LOG_FUNCTION (this << station << mode);
+ for (RrpaaThresholdsTable::const_iterator i = station->m_thresholds.begin (); i != station->m_thresholds.end (); i++)
+ {
+ if (mode == i->second)
+ {
+ return i->first;
+ }
+ }
+ NS_ASSERT (false);
+}
+
+WifiRemoteStation *
+RrpaaWifiManager::DoCreateStation (void) const
+{
+ NS_LOG_FUNCTION (this);
+ RrpaaWifiRemoteStation *station = new RrpaaWifiRemoteStation ();
+ station->m_adaptiveRtsWnd = 0;
+ station->m_rtsCounter = 0;
+ station->m_adaptiveRtsOn = false;
+ station->m_lastFrameFail = false;
+ station->m_initialized = false;
+ return station;
+}
+
+void
+RrpaaWifiManager::CheckInit (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ if (!station->m_initialized)
+ {
+ //Note: we appear to be doing late initialization of the table
+ //to make sure that the set of supported rates has been initialized
+ //before we perform our own initialization.
+ station->m_nRate = GetNSupported (station);
+ //Initialize at minimal rate and maximal power.
+ station->m_prevRateIndex = 0;
+ station->m_rateIndex = 0;
+ station->m_prevPowerLevel = m_maxPower;
+ station->m_powerLevel = m_maxPower;
+ WifiMode mode = GetSupported (station, 0);
+ uint8_t channelWidth = GetChannelWidth (station);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (m_maxPower);
+ m_rateChange (rate, rate, station->m_state->m_address);
+ m_powerChange (power, power, station->m_state->m_address);
+
+ station->m_pdTable = RrpaaProbabilitiesTable (station->m_nRate, std::vector (m_nPower));
+ NS_LOG_DEBUG ("Initializing pdTable");
+ for (uint32_t i = 0; i < station->m_nRate; i++)
+ {
+ for (uint8_t j = 0; j < m_nPower; j++)
+ {
+ station->m_pdTable[i][j] = 1;
+ }
+ }
+
+ station->m_initialized = true;
+
+ station->m_thresholds = RrpaaThresholdsTable (station->m_nRate);
+ InitThresholds (station);
+ ResetCountersBasic (station);
+ }
+}
+
+void
+RrpaaWifiManager::InitThresholds (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ NS_LOG_DEBUG ("InitThresholds = " << station);
+
+ double nextCritical = 0;
+ double nextMtl = 0;
+ double mtl = 0;
+ double ori = 0;
+ for (uint32_t i = 0; i < station->m_nRate; i++)
+ {
+ WifiMode mode = GetSupported (station, i);
+ Time totalTxTime = GetCalcTxTime (mode) + m_sifs + m_difs;
+ if (i == station->m_nRate - 1)
+ {
+ ori = 0;
+ }
+ else
+ {
+ WifiMode nextMode = GetSupported (station, i + 1);
+ Time nextTotalTxTime = GetCalcTxTime (nextMode) + m_sifs + m_difs;
+ nextCritical = 1 - (nextTotalTxTime.GetSeconds () / totalTxTime.GetSeconds ());
+ nextMtl = m_alpha * nextCritical;
+ ori = nextMtl / m_beta;
+ }
+ if (i == 0)
+ {
+ mtl = nextMtl;
+ }
+ Thresholds th;
+ th.m_ewnd = ceil (m_tau / totalTxTime.GetSeconds ());
+ th.m_ori = ori;
+ th.m_mtl = mtl;
+ station->m_thresholds.push_back (std::make_pair (th, mode));
+ mtl = nextMtl;
+ NS_LOG_DEBUG (mode << " " << th.m_ewnd << " " << th.m_mtl << " " << th.m_ori);
+ }
+}
+
+void
+RrpaaWifiManager::ResetCountersBasic (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ station->m_nFailed = 0;
+ station->m_counter = GetThresholds (station, station->m_rateIndex).m_ewnd;
+ station->m_lastReset = Simulator::Now ();
+}
+
+void
+RrpaaWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+}
+
+void
+RrpaaWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ RrpaaWifiRemoteStation *station = (RrpaaWifiRemoteStation *) st;
+ CheckInit (station);
+ station->m_lastFrameFail = true;
+ CheckTimeout (station);
+ station->m_counter--;
+ station->m_nFailed++;
+ RunBasicAlgorithm (station);
+}
+
+void
+RrpaaWifiManager::DoReportRxOk (WifiRemoteStation *st,
+ double rxSnr, WifiMode txMode)
+{
+ NS_LOG_FUNCTION (this << st << rxSnr << txMode);
+}
+
+void
+RrpaaWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+ double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+ NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode << rtsSnr);
+ NS_LOG_DEBUG ("self=" << st << " rts ok");
+}
+
+void
+RrpaaWifiManager::DoReportDataOk (WifiRemoteStation *st,
+ double ackSnr, WifiMode ackMode, double dataSnr)
+{
+ NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
+ RrpaaWifiRemoteStation *station = (RrpaaWifiRemoteStation *) st;
+ CheckInit (station);
+ station->m_lastFrameFail = false;
+ CheckTimeout (station);
+ station->m_counter--;
+ RunBasicAlgorithm (station);
+}
+void
+RrpaaWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+}
+void
+RrpaaWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+}
+
+WifiTxVector
+RrpaaWifiManager::DoGetDataTxVector (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ RrpaaWifiRemoteStation *station = (RrpaaWifiRemoteStation *) st;
+ uint32_t channelWidth = GetChannelWidth (station);
+ if (channelWidth > 20 && channelWidth != 22)
+ {
+ //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
+ channelWidth = 20;
+ }
+ CheckInit (station);
+ WifiMode mode = GetSupported (station, station->m_rateIndex);
+ DataRate rate = DataRate (mode.GetDataRate (channelWidth));
+ DataRate prevRate = DataRate (GetSupported (station, station->m_prevRateIndex).GetDataRate (channelWidth));
+ double power = GetPhy ()->GetPowerDbm (station->m_powerLevel);
+ double prevPower = GetPhy ()->GetPowerDbm (station->m_prevPowerLevel);
+ if (station->m_prevRateIndex != station->m_rateIndex)
+ {
+ m_rateChange (prevRate, rate, station->m_state->m_address);
+ station->m_prevRateIndex = station->m_rateIndex;
+ }
+ if (station->m_prevPowerLevel != station->m_powerLevel)
+ {
+ m_powerChange (prevPower, power, station->m_state->m_address);
+ station->m_prevPowerLevel = station->m_powerLevel;
+ }
+ return WifiTxVector (mode, station->m_powerLevel, GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
+}
+WifiTxVector
+RrpaaWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
+{
+ NS_LOG_FUNCTION (this << st);
+ RrpaaWifiRemoteStation *station = (RrpaaWifiRemoteStation *) st;
+ uint32_t channelWidth = GetChannelWidth (station);
+ if (channelWidth > 20 && channelWidth != 22)
+ {
+ //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
+ channelWidth = 20;
+ }
+ WifiTxVector rtsTxVector;
+ WifiMode mode;
+ if (GetUseNonErpProtection () == false)
+ {
+ mode = GetSupported (station, 0);
+ }
+ else
+ {
+ mode = GetNonErpSupported (station, 0);
+ }
+ rtsTxVector = WifiTxVector (mode, GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetPreambleForTransmission (mode, GetAddress (st)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
+ return rtsTxVector;
+}
+
+bool
+RrpaaWifiManager::DoNeedRts (WifiRemoteStation *st,
+ Ptr packet, bool normally)
+{
+ NS_LOG_FUNCTION (this << st << packet << normally);
+ RrpaaWifiRemoteStation *station = (RrpaaWifiRemoteStation *) st;
+ CheckInit (station);
+ if (m_basic)
+ {
+ return normally;
+ }
+ RunAdaptiveRtsAlgorithm (station);
+ return station->m_adaptiveRtsOn;
+}
+
+void
+RrpaaWifiManager::CheckTimeout (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ Time d = Simulator::Now () - station->m_lastReset;
+ if (station->m_counter == 0 || d > m_timeout)
+ {
+ ResetCountersBasic (station);
+ }
+}
+
+void
+RrpaaWifiManager::RunBasicAlgorithm (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ Thresholds thresholds = GetThresholds (station, station->m_rateIndex);
+ double bploss = (double) station->m_nFailed / (double) thresholds.m_ewnd;
+ double wploss = (double) (station->m_counter + station->m_nFailed) / (double) thresholds.m_ewnd;
+ NS_LOG_DEBUG ("Best loss prob= " << bploss);
+ NS_LOG_DEBUG ("Worst loss prob= " << wploss);
+ if (bploss >= thresholds.m_mtl)
+ {
+ if (station->m_powerLevel < m_maxPower)
+ {
+ NS_LOG_DEBUG ("bploss >= MTL and power < maxPower => Increase Power");
+ station->m_pdTable[station->m_rateIndex][station->m_powerLevel] /= m_gamma;
+ NS_LOG_DEBUG ("pdTable[" << station->m_rateIndex << "][" << station->m_powerLevel << "] = " << station->m_pdTable[station->m_rateIndex][station->m_powerLevel]);
+ station->m_powerLevel++;
+ ResetCountersBasic (station);
+ }
+ else if (station->m_rateIndex != 0)
+ {
+ NS_LOG_DEBUG ("bploss >= MTL and power = maxPower => Decrease Rate");
+ station->m_pdTable[station->m_rateIndex][station->m_powerLevel] /= m_gamma;
+ NS_LOG_DEBUG ("pdTable[" << station->m_rateIndex << "][" << station->m_powerLevel << "] = " << station->m_pdTable[station->m_rateIndex][station->m_powerLevel]);
+ station->m_rateIndex--;
+ ResetCountersBasic (station);
+ }
+ else
+ {
+ NS_LOG_DEBUG ("bploss >= MTL but already at maxPower and minRate");
+ }
+ }
+ else if (wploss <= thresholds.m_ori)
+ {
+ if (station->m_rateIndex < station->m_nRate - 1)
+ {
+ NS_LOG_DEBUG ("wploss <= ORI and rate < maxRate => Probabilistic Rate Increase");
+
+ // Recalculate probabilities of lower rates.
+ for (uint32_t i = 0; i <= station->m_rateIndex; i++)
+ {
+ station->m_pdTable[i][station->m_powerLevel] *= m_delta;
+ if (station->m_pdTable[i][station->m_powerLevel] > 1)
+ {
+ station->m_pdTable[i][station->m_powerLevel] = 1;
+ }
+ NS_LOG_DEBUG ("pdTable[" << i << "][" << station->m_powerLevel << "] = " << station->m_pdTable[i][station->m_powerLevel]);
+ }
+ double rand = m_uniformRandomVariable->GetValue (0,1);
+ if (rand < station->m_pdTable[station->m_rateIndex + 1][station->m_powerLevel])
+ {
+ NS_LOG_DEBUG ("Increase Rate");
+ station->m_rateIndex++;
+ }
+ }
+ else if (station->m_powerLevel > m_minPower)
+ {
+ NS_LOG_DEBUG ("wploss <= ORI and rate = maxRate => Probabilistic Power Decrease");
+
+ // Recalculate probabilities of higher powers.
+ for (uint32_t i = m_maxPower; i > station->m_powerLevel; i--)
+ {
+ station->m_pdTable[station->m_rateIndex][i] *= m_delta;
+ if (station->m_pdTable[station->m_rateIndex][i] > 1)
+ {
+ station->m_pdTable[station->m_rateIndex][i] = 1;
+ }
+ NS_LOG_DEBUG ("pdTable[" << station->m_rateIndex << "][" << i << "] = " << station->m_pdTable[station->m_rateIndex][i]);
+ }
+ double rand = m_uniformRandomVariable->GetValue (0,1);
+ if (rand < station->m_pdTable[station->m_rateIndex][station->m_powerLevel - 1])
+ {
+ NS_LOG_DEBUG ("Decrease Power");
+ station->m_powerLevel--;
+ }
+ }
+ ResetCountersBasic (station);
+ }
+ else if (bploss > thresholds.m_ori && wploss < thresholds.m_mtl)
+ {
+ if (station->m_powerLevel > m_minPower)
+ {
+ NS_LOG_DEBUG ("loss between ORI and MTL and power > minPower => Probabilistic Power Decrease");
+
+ // Recalculate probabilities of higher powers.
+ for (uint32_t i = m_maxPower; i >= station->m_powerLevel; i--)
+ {
+ station->m_pdTable[station->m_rateIndex][i] *= m_delta;
+ if (station->m_pdTable[station->m_rateIndex][i] > 1)
+ {
+ station->m_pdTable[station->m_rateIndex][i] = 1;
+ }
+ NS_LOG_DEBUG ("pdTable[" << station->m_rateIndex << "][" << i << "] = " << station->m_pdTable[station->m_rateIndex][i]);
+ }
+ double rand = m_uniformRandomVariable->GetValue (0,1);
+ if (rand < station->m_pdTable[station->m_rateIndex][station->m_powerLevel - 1])
+ {
+ NS_LOG_DEBUG ("Decrease Power");
+ station->m_powerLevel--;
+ }
+ ResetCountersBasic (station);
+ }
+ }
+ if (station->m_counter == 0)
+ {
+ ResetCountersBasic (station);
+ }
+}
+
+void
+RrpaaWifiManager::RunAdaptiveRtsAlgorithm (RrpaaWifiRemoteStation *station)
+{
+ NS_LOG_FUNCTION (this << station);
+ if (!station->m_adaptiveRtsOn
+ && station->m_lastFrameFail)
+ {
+ station->m_adaptiveRtsWnd += 2;
+ station->m_rtsCounter = station->m_adaptiveRtsWnd;
+ }
+ else if ((station->m_adaptiveRtsOn && station->m_lastFrameFail)
+ || (!station->m_adaptiveRtsOn && !station->m_lastFrameFail))
+ {
+ station->m_adaptiveRtsWnd = station->m_adaptiveRtsWnd / 2;
+ station->m_rtsCounter = station->m_adaptiveRtsWnd;
+ }
+ if (station->m_rtsCounter > 0)
+ {
+ station->m_adaptiveRtsOn = true;
+ station->m_rtsCounter--;
+ }
+ else
+ {
+ station->m_adaptiveRtsOn = false;
+ }
+}
+
+Thresholds
+RrpaaWifiManager::GetThresholds (RrpaaWifiRemoteStation *station,
+ uint32_t rate) const
+{
+ NS_LOG_FUNCTION (this << station << rate);
+ WifiMode mode = GetSupported (station, rate);
+ return GetThresholds (station, mode);
+}
+
+bool
+RrpaaWifiManager::IsLowLatency (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return true;
+}
+
+
+
+void
+RrpaaWifiManager::SetHtSupported (bool enable)
+{
+ //HT is not supported by this algorithm.
+ if (enable)
+ {
+ NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
+ }
+}
+
+void
+RrpaaWifiManager::SetVhtSupported (bool enable)
+{
+ //VHT is not supported by this algorithm.
+ if (enable)
+ {
+ NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
+ }
+}
+
+void
+RrpaaWifiManager::SetHeSupported (bool enable)
+{
+ //HE is not supported by this algorithm.
+ if (enable)
+ {
+ NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
+ }
+}
+
+} // namespace ns3
diff --git a/src/wifi/model/rrpaa-wifi-manager.h b/src/wifi/model/rrpaa-wifi-manager.h
new file mode 100644
index 000000000..926c65442
--- /dev/null
+++ b/src/wifi/model/rrpaa-wifi-manager.h
@@ -0,0 +1,239 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2017 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
+ */
+
+#ifndef RRPAA_WIFI_MANAGER_H
+#define RRPAA_WIFI_MANAGER_H
+
+#include "ns3/nstime.h"
+#include "ns3/random-variable-stream.h"
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+struct RrpaaWifiRemoteStation;
+
+/**
+ * \ingroup wifi
+ * Robust Rate and Power Adaptation Algorithm
+ *
+ * This class implements the RRPAA algorithm as described in Rate, Power and Carrier-Sense
+ * Threshold Coordinated Management for High-Density IEEE 802.11 Networks
+ * by Matías Richart; Jorge Visca and Javier Baliosian in Integrated Network Management (IM),
+ * 2015 IFIP/IEEE International Symposium on (pp. 139-146). IEEE.
+ * http://dl.ifip.org/db/conf/im/im2015/137430.pdf
+ *
+ * RRPAA adds power control to the RRAA mechanism. RRAA is described in
+ * Robust rate adaptation for 802.11 wireless networks by Starsky H. Y. Wong;
+ * Hao Yang; Songwu Lu and Vaduvur Bharghavan in Proceedings of the 12th annual
+ * international conference on Mobile computing and networking (pp. 146-157). ACM.
+ * http://ocw.cs.pub.ro/courses/_media/isrm/articole/rrate_adapt_mobicom06.pdf
+ *
+ */
+
+/**
+ * For each rate there is a Opportunistic Rate Increase threshold,
+ * a Maximum Tolerable Loss threshold and an Evaluation Window.
+ */
+struct Thresholds
+{
+ double m_ori; //!< The Oportunistic Rate Increase threshold.
+ double m_mtl; //!< The Maximum Tolerable Loss threshold.
+ uint32_t m_ewnd; //!< The Estimation Window size.
+};
+
+/**
+ * List of thresholds for each mode.
+ */
+typedef std::vector > RrpaaThresholdsTable;
+
+/**
+ * List of probabilities.
+ */
+typedef std::vector > RrpaaProbabilitiesTable;
+
+class RrpaaWifiManager : public WifiRemoteStationManager
+{
+public:
+ /**
+ * Register this type.
+ * \return The object TypeId.
+ */
+ static TypeId GetTypeId (void);
+ RrpaaWifiManager ();
+ virtual ~RrpaaWifiManager ();
+
+ // Inherited from WifiRemoteStationManager
+ virtual void SetupPhy (Ptr phy);
+ virtual void SetupMac (Ptr mac);
+ virtual void SetHtSupported (bool enable);
+ virtual void SetVhtSupported (bool enable);
+ virtual void SetHeSupported (bool enable);
+
+ /**
+ * Assign a fixed random variable stream number to the random variables
+ * used by this model. Return the number of streams (possibly zero) that
+ * have been assigned.
+ *
+ * \param stream first stream index to use
+ *
+ * \return the number of stream indices assigned by this model
+ */
+ int64_t AssignStreams (int64_t stream);
+
+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);
+ virtual WifiTxVector DoGetRtsTxVector (WifiRemoteStation *station);
+ virtual bool DoNeedRts (WifiRemoteStation *st,
+ Ptr packet, bool normally);
+ virtual bool IsLowLatency (void) const;
+
+ /**
+ * Check for initializations.
+ * \param station The remote station.
+ */
+ void CheckInit (RrpaaWifiRemoteStation *station);
+
+ /**
+ * Check if the counter should be reseted.
+ *
+ * \param station
+ */
+ void CheckTimeout (RrpaaWifiRemoteStation *station);
+ /**
+ * Find an appropriate rate and power for the given station, using
+ * a basic algorithm.
+ *
+ * \param station
+ */
+ void RunBasicAlgorithm (RrpaaWifiRemoteStation *station);
+ /**
+ * Run an enhanced algorithm which activates the use of RTS
+ * for the given station if the conditions are met.
+ *
+ * \param station
+ */
+ void RunAdaptiveRtsAlgorithm (RrpaaWifiRemoteStation *station);
+ /**
+ * Reset the counters of the given station.
+ *
+ * \param station
+ */
+ void ResetCountersBasic (RrpaaWifiRemoteStation *station);
+
+ /**
+ * Initialize the thresholds internal list for the given station.
+ *
+ * \param station
+ */
+ void InitThresholds (RrpaaWifiRemoteStation *station);
+
+ /**
+ * Get the thresholds for the given station and mode.
+ *
+ * \param station
+ * \param mode
+ *
+ * \return threshold
+ */
+ Thresholds GetThresholds (RrpaaWifiRemoteStation *station, WifiMode mode) const;
+
+ /**
+ * Get the thresholds for the given station and mode index.
+ *
+ * \param station
+ * \param rate
+ *
+ * \return threshold
+ */
+ Thresholds GetThresholds (RrpaaWifiRemoteStation *station, uint32_t rate) const;
+
+ /**
+ * Get the estimated TxTime of a packet with a given mode.
+ *
+ * \param mode
+ *
+ * \return time
+ */
+ Time GetCalcTxTime (WifiMode mode) const;
+ /**
+ * Add transmission time for the given mode to an internal list.
+ *
+ * \param mode Wi-Fi mode
+ * \param t transmission time
+ */
+ void AddCalcTxTime (WifiMode mode, Time t);
+
+ /**
+ * typedef for a vector of a pair of Time, WifiMode.
+ * Essentially a list for WifiMode and its corresponding transmission time
+ * to transmit a reference packet.
+ */
+ typedef std::vector > TxTime;
+
+ TxTime m_calcTxTime; //!< To hold all the calculated TxTime for all modes.
+ Time m_sifs; //!< Value of SIFS configured in the device.
+ Time m_difs; //!< Value of DIFS configured in the device.
+
+ uint32_t m_frameLength; //!< Data frame length used for calculate mode TxTime.
+ uint32_t m_ackLength; //!< Ack frame length used for calculate mode TxTime.
+
+ bool m_basic; //!< If using the basic algorithm (without RTS/CTS).
+ Time m_timeout; //!< Timeout for the RRAA BASIC loss estimation block.
+ double m_alpha; //!< Alpha value for RRPAA (value for calculating MTL threshold)
+ double m_beta; //!< Beta value for RRPAA (value for calculating ORI threshold).
+ double m_tau; //!< Tau value for RRPAA (value for calculating EWND size).
+ double m_gamma; //!< Gamma value for RRPAA (value for pdTable decrements).
+ double m_delta; //!< Delta value for RRPAA (value for pdTable increments).
+
+ /**
+ * 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_minPower; //!< Minimal power level.
+ uint32_t m_maxPower; //!< Maximal power level.
+ uint32_t m_nPower; //!< Number of power levels.
+
+ /**
+ * The trace source fired when the transmission power change
+ */
+ TracedCallback m_powerChange;
+ /**
+ * The trace source fired when the transmission rate change
+ */
+ TracedCallback m_rateChange;
+
+ Ptr m_uniformRandomVariable; //!< Provides uniform random variables for probabilistic changes.
+};
+
+} //namespace ns3
+
+#endif /* RRPAA__WIFI_MANAGER_H */
diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h
index 63ed2b2ce..48200d082 100644
--- a/src/wifi/model/wifi-phy.h
+++ b/src/wifi/model/wifi-phy.h
@@ -1625,6 +1625,16 @@ public:
*/
std::vector GetSupportedChannelWidthSet (void) const;
+ /**
+ * Get the power of the given power level in dBm.
+ * In SpectrumWifiPhy implementation, the power levels are equally spaced (in dBm).
+ *
+ * \param power the power level
+ *
+ * \return the transmission power in dBm at the given power level
+ */
+ double GetPowerDbm (uint8_t power) const;
+
protected:
// Inherited
@@ -1652,16 +1662,6 @@ protected:
*/
bool DoFrequencySwitch (uint16_t frequency);
- /**
- * Get the power of the given power level in dBm.
- * In SpectrumWifiPhy implementation, the power levels are equally spaced (in dBm).
- *
- * \param power the power level
- *
- * \return the transmission power in dBm at the given power level
- */
- double GetPowerDbm (uint8_t power) const;
-
/**
* Check if Phy state should move to CCA busy state based on current
* state of interference tracker. In this model, CCA becomes busy when
diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h
index a634e362f..6d526c1d8 100644
--- a/src/wifi/model/wifi-remote-station-manager.h
+++ b/src/wifi/model/wifi-remote-station-manager.h
@@ -25,6 +25,7 @@
#include "ns3/packet.h"
#include "ns3/object.h"
#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
#include "wifi-tx-vector.h"
#include "ht-capabilities.h"
#include "vht-capabilities.h"
@@ -864,18 +865,20 @@ public:
/**
* TracedCallback signature for power change events.
*
- * \param [in] power The new power.
+ * \param [in] oldPower The previous power (in dBm).
+ * \param [in] newPower The new power (in dBm).
* \param [in] address The remote station MAC address.
*/
- typedef void (*PowerChangeTracedCallback)(uint8_t power, Mac48Address remoteAddress);
+ typedef void (*PowerChangeTracedCallback)(double oldPower, double newPower, Mac48Address remoteAddress);
/**
* TracedCallback signature for rate change events.
*
- * \param [in] rate The new rate.
+ * \param [in] oldRate The previous data rate.
+ * \param [in] newRate The new data rate.
* \param [in] address The remote station MAC address.
*/
- typedef void (*RateChangeTracedCallback)(uint32_t rate, Mac48Address remoteAddress);
+ typedef void (*RateChangeTracedCallback)(DataRate oldRate, DataRate newRate, Mac48Address remoteAddress);
protected:
diff --git a/src/wifi/test/power-rate-adaptation-test.cc b/src/wifi/test/power-rate-adaptation-test.cc
index 1dc72712d..a84322256 100644
--- a/src/wifi/test/power-rate-adaptation-test.cc
+++ b/src/wifi/test/power-rate-adaptation-test.cc
@@ -24,6 +24,7 @@
#include "ns3/constant-position-mobility-model.h"
#include "ns3/simulator.h"
#include "ns3/test.h"
+#include "ns3/double.h"
using namespace ns3;
@@ -44,6 +45,8 @@ private:
void TestParf ();
/// Test aparf function
void TestAparf ();
+ /// Test rrpaa function
+ void TestRrpaa ();
/**
* Configure nde function
* \returns the node
@@ -566,12 +569,447 @@ PowerRateAdaptationTest::TestAparf ()
Simulator::Destroy ();
}
+void
+PowerRateAdaptationTest::TestRrpaa ()
+{
+ m_manager.SetTypeId ("ns3::RrpaaWifiManager");
+ Ptr node = ConfigureNode ();
+ Ptr dev = DynamicCast (node->GetDevice (0));
+ Ptr manager = dev->GetRemoteStationManager ();
+
+ /*
+ * Configure constants for rate and power control.
+ */
+ manager->SetAttribute ("Basic", BooleanValue (true));
+ manager->SetAttribute ("Alpha", DoubleValue (1.25));
+ manager->SetAttribute ("Beta", DoubleValue (2));
+ manager->SetAttribute ("Tau", DoubleValue (0.015));
+ /*
+ * Constants for the Probabilistic Decision Table.
+ * We set both to 1 to avoid random behaviour in tests.
+ */
+ manager->SetAttribute ("Gamma", DoubleValue (1));
+ manager->SetAttribute ("Delta", DoubleValue (1));
+
+ /*
+ * Create a dummy packet to simulate transmission.
+ */
+ Mac48Address remoteAddress = Mac48Address::Allocate ();
+ WifiMacHeader packetHeader;
+ packetHeader.SetTypeData ();
+ packetHeader.SetQosTid (0);
+ Ptr packet = Create (10);
+ WifiMode ackMode;
+
+ /*
+ * To initialize the manager we need to generate a transmission.
+ */
+ Ptr p = Create ();
+ dev->Send (p, remoteAddress, 1);
+
+ /**
+ * This will be the thresholds table.
+ * The parameters of the table are:
+ * - Estimation Window Size (EWND)
+ * - Maximum Tolerable Loss Probability Threshold (MTL)
+ * - Opportunistic Rate Increase (and Power Decrease) Probability Threshold (ORI)
+ *
+ * We also calculate the needed success and failures to generate
+ * a rate or power change:
+ * Rate Increase or Power Decrease limits (RI-PD)
+ * Rate Decrease or Power Increase limits (RD-PI)
+ * Power Decrease limits (PD)
+ *
+ * Mode EWND MTL ORI RI-PD RD-PI PD
+ * succ fails succ fails
+ * OfdmRate6Mbps 8 1 0.19861 7 8 2
+ * OfdmRate9Mbps 11 0.397219 0.14556 10 5 7 2
+ * OfdmRate12Mbps 15 0.291121 0.189753 13 5 11 3
+ * OfdmRate18Mbps 21 0.379507 0.13624 19 8 14 3
+ * OfdmRate24Mbps 27 0.27248 0.174216 23 8 20 5
+ * OfdmRate36Mbps 37 0.348432 0.120773 33 13 25 5
+ * OfdmRate48Mbps 45 0.241546 0.0523952 43 11 35 3
+ * OfdmRate54Mbps 50 0.10479 0 50 6 45 5
+ *
+ */
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * RRPAA initiates with minimal rate and maximal power.
+ */
+ WifiTxVector txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ WifiMode mode = txVector.GetMode ();
+ int power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 6000000, "RRPAA: Initial data rate wrong"); //802.11a minimal rate is 6Mbps
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Initial power level wrong");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * As RRPAA starts with the 6Mbps rate, 7 successful transmissions are needed for RRPAA to increase rate.
+ * 1/8 = 0.125
+ */
+
+ /**
+ * Test that 6 is not enough.
+ */
+ for (int i = 0; i < 6; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 6000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ /**
+ * Test that 7 is enough.
+ */
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 9000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * 5 failures are needed to make the rate decrease again.
+ * 5/11 = 0.45
+ */
+ for (int i = 0; i < 4; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 9000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 6000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /**
+ * Increase rate until maximal rate.
+ */
+
+ for (int i = 0; i < 7; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 9000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 10; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 12000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 13; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 18000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 19; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 24000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 23; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 33; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 48000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 43; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /**
+ * Now we need more successful transmissions to make power decrease.
+ * As we are at maximal rate, the power is decreased when it is sure that the failures
+ * will not generate a rate decrease.
+ */
+
+ for (int i = 0; i < 49; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /**
+ * As rate hasn't change the same amount of success are needed.
+ * After 16*45 successful transmissions power is decreased to zero.
+ */
+
+ for (int i = 0; i < 16 * 50; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 0, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /**
+ * After 6 failures the power should be increased.
+ */
+
+ for (int i = 0; i < 6; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 1, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 16*6 failed transmissions power is increase to 17.
+ */
+
+ for (int i = 0; i < 16 * 6; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 54000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * After 6 more failures the rate should be decreased.
+ */
+
+ for (int i = 0; i < 6; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 48000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ /*
+ * Now 11 failures are needed to decrease rate again.
+ */
+
+ for (int i = 0; i < 11; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * Test power decrement when loss probability is between MTL and ORI.
+ * As we are at rate 36 Mbps we need at least 25 successful transmissions
+ * and 5 failures.
+ */
+
+ for (int i = 0; i < 25; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 17, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 5; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 5; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 16, "RRPAA: Incorrect value of power level");
+
+ for (int i = 0; i < 25; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 15, "RRPAA: Incorrect value of power level");
+
+ //-----------------------------------------------------------------------------------------------------
+
+ /*
+ * Repeat the previous test until power 0 is reached.
+ */
+
+ for (int i = 0; i < 16; i++)
+ {
+ for (int i = 0; i < 25; i++)
+ {
+ manager->ReportDataOk (remoteAddress, &packetHeader, 0, ackMode, 0);
+ }
+
+ for (int i = 0; i < 5; i++)
+ {
+ manager->ReportDataFailed (remoteAddress,&packetHeader);
+ }
+ }
+
+ txVector = manager->GetDataTxVector (remoteAddress, &packetHeader, packet);
+ mode = txVector.GetMode ();
+ power = (int) txVector.GetTxPowerLevel ();
+
+ NS_TEST_ASSERT_MSG_EQ (mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1), 36000000, "RRPAA: Incorrect vale of data rate");
+ NS_TEST_ASSERT_MSG_EQ (power, 0, "RRPAA: Incorrect value of power level");
+
+ Simulator::Stop (Seconds (10.0));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+}
+
void
PowerRateAdaptationTest::DoRun (void)
{
TestParf ();
TestAparf ();
+ TestRrpaa ();
}
/**
diff --git a/src/wifi/wscript b/src/wifi/wscript
index 25c35f427..7542aa36c 100644
--- a/src/wifi/wscript
+++ b/src/wifi/wscript
@@ -69,6 +69,7 @@ def build(bld):
'model/wifi-tx-vector.cc',
'model/parf-wifi-manager.cc',
'model/aparf-wifi-manager.cc',
+ 'model/rrpaa-wifi-manager.cc',
'model/ampdu-subframe-header.cc',
'model/mpdu-aggregator.cc',
'model/mpdu-standard-aggregator.cc',
@@ -174,6 +175,7 @@ def build(bld):
'model/ht-capabilities.h',
'model/parf-wifi-manager.h',
'model/aparf-wifi-manager.h',
+ 'model/rrpaa-wifi-manager.h',
'model/wifi-tx-vector.h',
'model/ampdu-subframe-header.h',
'model/mpdu-aggregator.h',