wifi: add RRPAA wifi rate control (patch from Matias Richart)

This commit is contained in:
Sébastien Deronne
2017-02-15 23:44:05 +01:00
parent 39e95cdcb9
commit ba433f9a20
16 changed files with 1615 additions and 245 deletions

View File

@@ -67,6 +67,7 @@ us a note on ns-developers mailing list.</p>
<li>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.</li>
</ul>
</li>
<li> A new class were added for the RRPAA WiFi rate control mechanism.</li>
<li>Included carrier aggregation feature in LTE module</li>
<ul>
<li>LTE model is extended to support carrier aggregation feature according to 3GPP Release 10, for up to 5 component

View File

@@ -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

View File

@@ -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"),

View File

@@ -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<const Packet> packet);
void RxCallback (std::string path, Ptr<const Packet> packet, const Address &from);
void PowerCallback (std::string path, uint8_t power, Mac48Address dest);
void RateCallback (std::string path, uint32_t rate, Mac48Address dest);
void 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> node, Vector position);
void AdvancePosition (Ptr<Node> node, int stepsSize, int stepsTime);
Vector GetPosition (Ptr<Node> node);
@@ -116,13 +116,14 @@ public:
Gnuplot2dDataset GetDatafile ();
Gnuplot2dDataset GetPowerDatafile ();
private:
typedef std::vector<std::pair<Time,WifiMode> > TxTime;
void SetupPhy (Ptr<WifiPhy> phy);
Time GetCalcTxTime (WifiMode mode);
std::map<Mac48Address, double> actualPower;
std::map<Mac48Address, WifiMode> actualMode;
private:
typedef std::vector<std::pair<Time, DataRate> > TxTime;
void SetupPhy (Ptr<WifiPhy> phy);
Time GetCalcTxTime (DataRate rate);
std::map<Mac48Address, double> currentPower;
std::map<Mac48Address, DataRate> currentRate;
uint32_t m_bytesTotal;
double totalEnergy;
double totalTime;
@@ -139,15 +140,17 @@ NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
Ptr<WifiPhy> 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<NetDevice> staDevice = stas.Get (j);
Ptr<WifiNetDevice> wifiStaDevice = DynamicCast<WifiNetDevice> (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<WifiPhy> 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<const Packet> 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<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
//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");

View File

@@ -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<const Packet> packet);
void RxCallback (std::string path, Ptr<const Packet> packet, const Address &from);
void PowerCallback (std::string path, uint8_t power, Mac48Address dest);
void RateCallback (std::string path, uint32_t rate, Mac48Address dest);
void 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<std::pair<Time,WifiMode> > TxTime;
typedef std::vector<std::pair<Time, DataRate> > TxTime;
void SetupPhy (Ptr<WifiPhy> phy);
Time GetCalcTxTime (WifiMode mode);
Time GetCalcTxTime (DataRate rate);
std::map<Mac48Address, double> actualPower;
std::map<Mac48Address, WifiMode> actualMode;
std::map<Mac48Address, double> currentPower;
std::map<Mac48Address, DataRate> currentRate;
uint32_t m_bytesTotal;
double totalEnergy;
double totalTime;
@@ -128,15 +128,17 @@ NodeStatistics::NodeStatistics (NetDeviceContainer aps, NetDeviceContainer stas)
Ptr<WifiPhy> 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<NetDevice> staDevice = stas.Get (j);
Ptr<WifiNetDevice> wifiStaDevice = DynamicCast<WifiNetDevice> (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<WifiPhy> 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<const Packet> 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<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
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<FlowMonitor> 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");

View File

@@ -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 <typename T1, typename T2, typename T3, typename T4, typename T5>
class CheckerBase;
/** Callback checkers. */
template <typename T1, typename T2, typename T3, typename T4, typename T5>
class Checker;
template <typename T1, typename T2, typename T3, typename T4>
class Checker<T1, T2, T3, T4, empty>;
template <typename T1, typename T2, typename T3>
class Checker<T1, T2, T3, empty, empty>;
template <typename T1, typename T2>
class Checker<T1, T2, empty, empty, empty>;
@@ -111,13 +112,13 @@ Duplicates (void)
return dupes;
}
/**
* Container for duplicate types.
*/
std::set<std::string> g_dupes = Duplicates ();
/**
* Stringify the known TracedCallback type names.
*
@@ -125,16 +126,21 @@ std::set<std::string> g_dupes = Duplicates ();
* \param [in] N The number of arguments expected.
* \returns The \c TracedCallback type name.
*/
template <typename T> inline
std::string TypeName (int N) { return "unknown"; }
template <typename T>
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 <typename T1, typename T2, typename T3, typename T4, typename T5>
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 <typename T1, typename T2, typename T3, typename T4>
class TracedCbSink<T1, T2, T3, T4, empty>
{
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 <typename T1, typename T2, typename T3>
class TracedCbSink<T1, T2, T3, empty, empty>
{
public:
static void Sink (T1 a1, T2 a2, T3 a3) { SinkIt (3); }
static void Sink (T1 a1, T2 a2, T3 a3)
{
SinkIt (3);
}
};
template <typename T1, typename T2>
class TracedCbSink<T1, T2, empty, empty, empty>
{
public:
static void Sink (T1 a1, T2 a2) { SinkIt (2); }
static void Sink (T1 a1, T2 a2)
{
SinkIt (2);
}
};
template <typename T1>
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<T3>::BaseType m3;
typename TypeTraits<T4>::BaseType m4;
typename TypeTraits<T5>::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 <typename T1, typename T2, typename T3, typename T4, typename T5>
class TracedCallbackTypedefTestCase::Checker : public CheckerBase<T1, T2, T3, T4, T5>
{
TracedCallback<T1, T2, T3, T4, T5> m_cb;
public:
template <typename U>
void Invoke (void)
@@ -299,7 +323,7 @@ public:
const int N = 5;
U sink = TracedCbSink<T1, T2, T3, T4, T5>::Sink;
Callback<void, T1, T2, T3, T4, T5> cb = MakeCallback (sink);
std::cout << TypeName<U> (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<T1, T2, T3, T4, empty>
: public CheckerBase<T1, T2, T3, T4, empty>
{
TracedCallback<T1, T2, T3, T4> m_cb;
public:
template <typename U>
void Invoke (void)
@@ -320,20 +344,20 @@ public:
const int N = 4;
U sink = TracedCbSink<T1, T2, T3, T4, empty>::Sink;
Callback<void, T1, T2, T3, T4> cb = MakeCallback (sink);
std::cout << TypeName<U> (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2, this->m3, this->m4);
this->Cleanup (N);
}
}; // Checker <4>
template <typename T1, typename T2, typename T3>
class TracedCallbackTypedefTestCase::Checker<T1, T2, T3, empty, empty>
: public CheckerBase<T1, T2, T3, empty, empty>
{
TracedCallback<T1, T2, T3> m_cb;
public:
template <typename U>
void Invoke (void)
@@ -341,7 +365,7 @@ public:
const int N = 3;
U sink = TracedCbSink<T1, T2, T3, empty, empty>::Sink;
Callback<void, T1, T2, T3> cb = MakeCallback (sink);
std::cout << TypeName<U> (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2, this->m3);
@@ -354,7 +378,7 @@ class TracedCallbackTypedefTestCase::Checker<T1, T2, empty, empty, empty>
: public CheckerBase<T1, T2, empty, empty, empty>
{
TracedCallback<T1, T2> m_cb;
public:
template <typename U>
void Invoke (void)
@@ -362,7 +386,7 @@ public:
const int N = 2;
U sink = TracedCbSink<T1, T2, empty, empty, empty>::Sink;
Callback<void, T1, T2> cb = MakeCallback (sink);
std::cout << TypeName<U> (N) << " invoked ";
m_cb.ConnectWithoutContext (cb);
m_cb (this->m1, this->m2);
@@ -375,7 +399,7 @@ class TracedCallbackTypedefTestCase::Checker<T1, empty, empty, empty, empty>
: public CheckerBase<T1, empty, empty, empty, empty>
{
TracedCallback<T1> m_cb;
public:
template <typename U>
void Invoke (void)
@@ -383,7 +407,7 @@ public:
const int N = 1;
U sink = TracedCbSink<T1, empty, empty, empty, empty>::Sink;
Callback<void, T1> cb = MakeCallback (sink);
std::cout << TypeName<U> (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<U> (0) == TypeName<T1> (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<U> (0) == TypeName<T1> (0)) { \
std::cout << # U << " matches " << # T1 << std::endl; } \
else \
NS_TEST_ASSERT_MSG_EQ \
(TypeName<U> (0), TypeName<T1> (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<T1, T2, T3, T4, T5> > () -> Invoke<U> ()
CreateObject< Checker<T1, T2, T3, T4, T5> > ()->Invoke<U> ()
CHECK (dsr::DsrOptionSRHeader::TracedCallback,
const dsr::DsrOptionSRHeader &,
@@ -435,11 +459,11 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (Ipv4L3Protocol::TxRxTracedCallback,
Ptr<const Packet>, Ptr<Ipv4>, uint32_t,
empty, empty);
CHECK (Ipv6L3Protocol::DropTracedCallback,
const Ipv6Header &, Ptr<const Packet>,
Ipv6L3Protocol::DropReason, Ptr<Ipv6>, uint32_t
);
);
CHECK (Ipv6L3Protocol::SentTracedCallback,
const Ipv6Header &, Ptr<const Packet>, 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<SpectrumPhy>, Ptr<SpectrumPhy>, double,
empty, empty);
CHECK (SpectrumValue::TracedCallback,
Ptr<SpectrumValue>,
empty, empty, empty, empty);
@@ -601,11 +625,11 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (UanMac::PacketModeTracedCallback,
Ptr<const Packet>, UanTxMode,
empty, empty, empty);
CHECK (UanMacCw::QueueTracedCallback,
Ptr<const Packet>, uint16_t,
empty, empty, empty);
CHECK (UanMacRc::QueueTracedCallback,
Ptr<const Packet>, uint32_t,
empty, empty, empty);
@@ -613,14 +637,14 @@ TracedCallbackTypedefTestCase::DoRun (void)
CHECK (UanNetDevice::RxTxTracedCallback,
Ptr<const Packet>, UanAddress,
empty, empty, empty);
CHECK (UanPhy::TracedCallback,
Ptr<const Packet>, 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

View File

@@ -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

View File

@@ -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<uint8_t, Mac48Address> m_powerChange;
TracedCallback<double, double, Mac48Address> m_powerChange;
/**
* The trace source fired when the transmission rate change
* The trace source fired when the transmission rate changes.
*/
TracedCallback<uint32_t, Mac48Address> m_rateChange;
TracedCallback<DataRate, DataRate, Mac48Address> m_rateChange;
};
} //namespace ns3

View File

@@ -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

View File

@@ -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<uint8_t, Mac48Address> m_powerChange;
TracedCallback<double, double, Mac48Address> m_powerChange;
/**
* The trace source fired when the transmission rate changes.
*/
TracedCallback<uint32_t, Mac48Address> m_rateChange;
TracedCallback<DataRate, DataRate, Mac48Address> m_rateChange;
};
} //namespace ns3

View File

@@ -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 <mrichart@fing.edu.uy>
*/
#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 <cmath>
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<WifiRemoteStationManager> ()
.SetGroupName ("Wifi")
.AddConstructor<RrpaaWifiManager> ()
.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 <uint32_t> ())
.AddAttribute ("AckFrameLength",
"The ACK frame length (in bytes) used for calculating mode TxTime.",
UintegerValue (14),
MakeUintegerAccessor (&RrpaaWifiManager::m_ackLength),
MakeUintegerChecker <uint32_t> ())
.AddAttribute ("Alpha",
"Constant for calculating the MTL threshold.",
DoubleValue (1.25),
MakeDoubleAccessor (&RrpaaWifiManager::m_alpha),
MakeDoubleChecker<double> (1))
.AddAttribute ("Beta",
"Constant for calculating the ORI threshold.",
DoubleValue (2),
MakeDoubleAccessor (&RrpaaWifiManager::m_beta),
MakeDoubleChecker<double> (1))
.AddAttribute ("Tau",
"Constant for calculating the EWND size.",
DoubleValue (0.015),
MakeDoubleAccessor (&RrpaaWifiManager::m_tau),
MakeDoubleChecker<double> (0))
.AddAttribute ("Gamma",
"Constant for Probabilistic Decision Table decrements.",
DoubleValue (2),
MakeDoubleAccessor (&RrpaaWifiManager::m_gamma),
MakeDoubleChecker<double> (1))
.AddAttribute ("Delta",
"Constant for Probabilistic Decision Table increments.",
DoubleValue (1.0905),
MakeDoubleAccessor (&RrpaaWifiManager::m_delta),
MakeDoubleChecker<double> (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<UniformRandomVariable> ();
}
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<WifiPhy> 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<WifiMac> 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<double> (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<const Packet> 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

View File

@@ -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 <mrichart@fing.edu.uy>
*/
#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 <i>Rate, Power and Carrier-Sense
* Threshold Coordinated Management for High-Density IEEE 802.11 Networks</i>
* 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
* <i>Robust rate adaptation for 802.11 wireless networks</i> 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<std::pair<Thresholds,WifiMode> > RrpaaThresholdsTable;
/**
* List of probabilities.
*/
typedef std::vector<std::vector<double> > 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<WifiPhy> phy);
virtual void SetupMac (Ptr<WifiMac> 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<const Packet> 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<std::pair<Time,WifiMode> > 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<double, double, Mac48Address> m_powerChange;
/**
* The trace source fired when the transmission rate change
*/
TracedCallback<DataRate, DataRate, Mac48Address> m_rateChange;
Ptr<UniformRandomVariable> m_uniformRandomVariable; //!< Provides uniform random variables for probabilistic changes.
};
} //namespace ns3
#endif /* RRPAA__WIFI_MANAGER_H */

View File

@@ -1625,6 +1625,16 @@ public:
*/
std::vector<uint8_t> 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

View File

@@ -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:

View File

@@ -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> node = ConfigureNode ();
Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice> (node->GetDevice (0));
Ptr<WifiRemoteStationManager> 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> packet = Create<Packet> (10);
WifiMode ackMode;
/*
* To initialize the manager we need to generate a transmission.
*/
Ptr<Packet> p = Create<Packet> ();
dev->Send (p, remoteAddress, 1);
/**
* 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 ();
}
/**

View File

@@ -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',