wifi (partial fix #1797) Update IdealWifiManager for HT/VHT

This commit is contained in:
Tom Henderson
2016-03-09 22:58:13 -08:00
parent 4c553b83d1
commit 2abd888157
2 changed files with 266 additions and 73 deletions

View File

@@ -22,10 +22,9 @@
#include "wifi-phy.h"
#include "ns3/assert.h"
#include "ns3/double.h"
#include "ns3/log.h"
#include <cmath>
#define Min(a,b) ((a < b) ? a : b)
namespace ns3 {
/**
@@ -36,11 +35,16 @@ namespace ns3 {
*/
struct IdealWifiRemoteStation : public WifiRemoteStation
{
double m_lastSnr; //!< SNR of last packet sent to the remote station
double m_lastSnrObserved; //!< SNR of most recently reported packet sent to the remote station
double m_lastSnrCached; //!< SNR most recently used to select a rate
double m_nss; //!< SNR most recently used to select a rate
WifiMode m_lastMode; //!< Mode most recently used to the remote station
};
NS_OBJECT_ENSURE_REGISTERED (IdealWifiManager);
NS_LOG_COMPONENT_DEFINE ("IdealWifiManager");
TypeId
IdealWifiManager::GetTypeId (void)
{
@@ -50,14 +54,19 @@ IdealWifiManager::GetTypeId (void)
.AddConstructor<IdealWifiManager> ()
.AddAttribute ("BerThreshold",
"The maximum Bit Error Rate acceptable at any transmission mode",
DoubleValue (10e-6),
DoubleValue (1e-5),
MakeDoubleAccessor (&IdealWifiManager::m_ber),
MakeDoubleChecker<double> ())
.AddTraceSource ("Rate",
"Traced value for rate changes (b/s)",
MakeTraceSourceAccessor (&IdealWifiManager::m_currentRate),
"ns3::TracedValueCallback::Uint64")
;
return tid;
}
IdealWifiManager::IdealWifiManager ()
: m_currentRate (0)
{
}
@@ -68,23 +77,92 @@ IdealWifiManager::~IdealWifiManager ()
void
IdealWifiManager::SetupPhy (Ptr<WifiPhy> phy)
{
uint32_t nModes = phy->GetNModes ();
for (uint32_t i = 0; i < nModes; i++)
{
WifiMode mode = phy->GetMode (i);
WifiTxVector txVector (mode, 0, 0, false, 1, 1, 20, false, false);
AddModeSnrThreshold (mode, phy->CalculateSnr (txVector, m_ber));
}
NS_LOG_FUNCTION (this << phy);
WifiRemoteStationManager::SetupPhy (phy);
}
double
IdealWifiManager::GetSnrThreshold (WifiMode mode) const
uint32_t
IdealWifiManager::GetChannelWidthForMode (WifiMode mode) const
{
NS_ASSERT (mode.GetModulationClass () != WIFI_MOD_CLASS_HT);
NS_ASSERT (mode.GetModulationClass () != WIFI_MOD_CLASS_VHT);
if (mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS ||
mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)
{
return 22;
}
else
{
return 20;
}
}
void
IdealWifiManager::DoInitialize ()
{
NS_LOG_FUNCTION (this);
WifiMode mode;
WifiTxVector txVector;
uint8_t nss = 1;
uint32_t nModes = GetPhy ()->GetNModes ();
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ());
for (uint32_t i = 0; i < nModes; i++)
{
mode = GetPhy ()->GetMode (i);
txVector.SetChannelWidth (GetChannelWidthForMode (mode));
txVector.SetNss (nss);
txVector.SetMode (mode);
NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () <<
" channel width " << txVector.GetChannelWidth () <<
" nss " << (uint16_t) nss <<
" short GI " << GetPhy ()->GetGuardInterval ());
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber));
}
// Add all Ht and Vht MCSes
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ());
if (HasVhtSupported () == true || HasHtSupported () == true )
{
nModes = GetPhy ()->GetNMcs ();
for (uint32_t i = 0; i < nModes; i++)
{
mode = GetPhy ()->GetMcs (i);
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
{
//derive NSS from the Mcs index
nss = (mode.GetMcsValue () / 8) + 1;
}
else
{
nss = GetPhy ()->GetSupportedTxSpatialStreams ();
}
NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () <<
" channel width " << GetPhy ()->GetChannelWidth () <<
" nss " << (uint16_t) nss <<
" short GI " << GetPhy ()->GetGuardInterval ());
NS_LOG_DEBUG ("In SetupPhy, adding mode = " << mode.GetUniqueName ());
txVector.SetNss (nss);
txVector.SetMode (mode);
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber));
}
}
}
double
IdealWifiManager::GetSnrThreshold (WifiTxVector txVector) const
{
NS_LOG_FUNCTION (this << txVector.GetMode().GetUniqueName ());
for (Thresholds::const_iterator i = m_thresholds.begin (); i != m_thresholds.end (); i++)
{
if (mode == i->second)
NS_LOG_DEBUG ("Checking " << i->second.GetMode ().GetUniqueName () <<
" nss " << (uint16_t) i->second.GetNss () <<
" width " << i->second.GetChannelWidth ());
NS_LOG_DEBUG ("against TxVector " << txVector.GetMode ().GetUniqueName () <<
" nss " << (uint16_t) txVector.GetNss () <<
" width " << txVector.GetChannelWidth ());
if (txVector.GetMode () == i->second.GetMode () &&
txVector.GetNss () == i->second.GetNss () &&
txVector.IsShortGuardInterval () == i->second.IsShortGuardInterval () &&
txVector.GetChannelWidth () == i->second.GetChannelWidth ())
{
return i->first;
}
@@ -94,16 +172,21 @@ IdealWifiManager::GetSnrThreshold (WifiMode mode) const
}
void
IdealWifiManager::AddModeSnrThreshold (WifiMode mode, double snr)
IdealWifiManager::AddSnrThreshold (WifiTxVector txVector, double snr)
{
m_thresholds.push_back (std::make_pair (snr,mode));
NS_LOG_FUNCTION (this << txVector.GetMode ().GetUniqueName () << snr);
m_thresholds.push_back (std::make_pair (snr, txVector));
}
WifiRemoteStation *
IdealWifiManager::DoCreateStation (void) const
{
NS_LOG_FUNCTION (this);
IdealWifiRemoteStation *station = new IdealWifiRemoteStation ();
station->m_lastSnr = 0.0;
station->m_lastSnrObserved = 0.0;
station->m_lastSnrCached = 0.0;
station->m_lastMode = GetDefaultMode ();
station->m_nss = 1;
return station;
}
@@ -128,18 +211,39 @@ void
IdealWifiManager::DoReportRtsOk (WifiRemoteStation *st,
double ctsSnr, WifiMode ctsMode, double rtsSnr)
{
NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode.GetUniqueName () << rtsSnr);
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
station->m_lastSnr = rtsSnr;
station->m_lastSnrObserved = rtsSnr;
}
void
IdealWifiManager::DoReportDataOk (WifiRemoteStation *st,
double ackSnr, WifiMode ackMode, double dataSnr)
{
NS_LOG_FUNCTION (this << st << ackSnr << ackMode.GetUniqueName () << dataSnr);
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
station->m_lastSnr = dataSnr;
if (dataSnr == 0)
{
NS_LOG_WARN ("DataSnr reported to be zero; not saving this report.");
return;
}
station->m_lastSnrObserved = dataSnr;
}
void
IdealWifiManager::DoReportAmpduTxStatus (WifiRemoteStation *st, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus, double rxSnr, double dataSnr)
{
NS_LOG_FUNCTION (this << st << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr);
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
if (dataSnr == 0)
{
NS_LOG_WARN ("DataSnr reported to be zero; not saving this report.");
return;
}
station->m_lastSnrObserved = dataSnr;
}
void
IdealWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
{
@@ -153,76 +257,152 @@ IdealWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
WifiTxVector
IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st)
{
NS_LOG_FUNCTION (this << st);
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
//We search within the Supported rate set the mode with the
//highest snr threshold possible which is smaller than m_lastSnr
//to ensure correct packet delivery.
double maxThreshold = 0.0;
WifiMode maxMode = GetDefaultMode ();
for (uint32_t i = 0; i < GetNSupported (station); i++)
std::vector<WifiTxVector> candidateTxVectors;
WifiTxVector txVector;
WifiMode mode;
uint8_t nss = 1;
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ());
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ());
if (station->m_lastSnrObserved == station->m_lastSnrCached)
{
WifiMode mode = GetSupported (station, i);
double threshold = GetSnrThreshold (mode);
if (threshold > maxThreshold
&& threshold < station->m_lastSnr)
// SNR has not changed, so skip the search and use the last
// mode selected
maxMode = station->m_lastMode;
nss = station->m_nss;
NS_LOG_DEBUG ("Using cached mode = " << maxMode.GetUniqueName () <<
" last snr observed " << station->m_lastSnrObserved <<
" cached " << station->m_lastSnrCached);
}
else
{
if (HasVhtSupported () == true || HasHtSupported () == true)
{
maxThreshold = threshold;
maxMode = mode;
for (uint32_t i = 0; i < GetNMcsSupported (station); i++)
{
mode = GetMcsSupported (station, i);
txVector.SetMode (mode);
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
{
//derive NSS from the Mcs index
nss = (mode.GetMcsValue () / 8) + 1;
}
else
{
nss = GetPhy ()->GetSupportedTxSpatialStreams ();
}
txVector.SetNss (nss);
if (WifiPhy::IsValidTxVector (txVector) == false)
{
NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () <<
" nss " << nss << " width " <<
txVector.GetChannelWidth());
continue;
}
double threshold = GetSnrThreshold (txVector);
// If the node and peer are both VHT capable, only search VHT modes
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT && HasVhtSupported () && GetVhtSupported (st))
{
continue;
}
// If the node and peer are not both VHT capable, only search HT modes
if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT && (!HasVhtSupported () || !GetVhtSupported (st)))
{
continue;
}
NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () <<
" threshold " << threshold << " maxThreshold " <<
maxThreshold << " last snr observed " <<
station->m_lastSnrObserved << " cached " <<
station->m_lastSnrCached);
if (threshold > maxThreshold && threshold < station->m_lastSnrObserved)
{
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () <<
" threshold " << threshold <<
" last snr observed " <<
station->m_lastSnrObserved);
maxThreshold = threshold;
maxMode = mode;
}
}
}
else
{
// Non-HT selection
nss = 1;
for (uint32_t i = 0; i < GetNSupported (station); i++)
{
mode = GetSupported (station, i);
txVector.SetMode (mode);
txVector.SetNss (nss);
txVector.SetChannelWidth (GetChannelWidthForMode (mode));
double threshold = GetSnrThreshold (txVector);
NS_LOG_DEBUG ("mode = " << mode.GetUniqueName () <<
" threshold " << threshold <<
" last snr observed " <<
station->m_lastSnrObserved);
if (threshold > maxThreshold && threshold < station->m_lastSnrObserved)
{
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () <<
" threshold " << threshold <<
" last snr observed " <<
station->m_lastSnrObserved);
maxThreshold = threshold;
maxMode = mode;
}
}
}
NS_LOG_DEBUG ("Updating cached values for station to " << maxMode.GetUniqueName () << " snr " << station->m_lastSnrObserved);
station->m_lastSnrCached = station->m_lastSnrObserved;
station->m_lastMode = maxMode;
station->m_nss = nss;
}
uint32_t channelWidth = GetChannelWidth (station);
if (channelWidth > 20 && channelWidth != 22)
NS_LOG_DEBUG ("Found maxMode: " << maxMode << " channelWidth: " << channelWidth);
if (m_currentRate != maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss))
{
//avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
channelWidth = 20;
NS_LOG_DEBUG ("New datarate: " << maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss));
m_currentRate = maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss);
}
return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, nss, 0, channelWidth, GetAggregation (station), false);
}
WifiTxVector
IdealWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
{
NS_LOG_FUNCTION (this << st);
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
//We search within the Basic rate set the mode with the highest
//snr threshold possible which is smaller than m_lastSnr to
//ensure correct packet delivery.
double maxThreshold = 0.0;
WifiTxVector txVector;
WifiMode mode;
uint8_t nss = 1;
WifiMode maxMode = GetDefaultMode ();
if (GetUseNonErpProtection () == false)
//avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
// RTS is sent in a non-HT frame; RTS with (V)HT is not yet supported
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ());
for (uint32_t i = 0; i < GetNBasicModes (); i++)
{
for (uint32_t i = 0; i < GetNBasicModes (); i++)
mode = GetBasicMode (i);
txVector.SetMode (mode);
txVector.SetNss (nss);
txVector.SetChannelWidth (GetChannelWidthForMode (mode));
double threshold = GetSnrThreshold (txVector);
if (threshold > maxThreshold && threshold < station->m_lastSnrObserved)
{
WifiMode mode = GetBasicMode (i);
double threshold = GetSnrThreshold (mode);
if (threshold > maxThreshold
&& threshold < station->m_lastSnr)
{
maxThreshold = threshold;
maxMode = mode;
}
maxThreshold = threshold;
maxMode = mode;
}
}
else
{
for (uint32_t i = 0; i < GetNNonErpBasicModes (); i++)
{
WifiMode mode = GetNonErpBasicMode (i);
double threshold = GetSnrThreshold (mode);
if (threshold > maxThreshold
&& threshold < station->m_lastSnr)
{
maxThreshold = threshold;
maxMode = mode;
}
}
}
uint32_t channelWidth = GetChannelWidth (station);
if (channelWidth > 20 && channelWidth != 22)
{
//avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
channelWidth = 20;
}
return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, nss, 0, GetChannelWidthForMode (maxMode), GetAggregation (station), false);
}
bool

View File

@@ -23,6 +23,7 @@
#include <stdint.h>
#include <vector>
#include "ns3/traced-value.h"
#include "wifi-mode.h"
#include "wifi-remote-station-manager.h"
@@ -55,6 +56,7 @@ public:
private:
//overriden from base class
virtual void DoInitialize (void);
virtual WifiRemoteStation* DoCreateStation (void) const;
virtual void DoReportRxOk (WifiRemoteStation *station,
double rxSnr, WifiMode txMode);
@@ -64,6 +66,7 @@ private:
double ctsSnr, WifiMode ctsMode, double rtsSnr);
virtual void DoReportDataOk (WifiRemoteStation *station,
double ackSnr, WifiMode ackMode, double dataSnr);
virtual void DoReportAmpduTxStatus (WifiRemoteStation *station, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus, double rxSnr, double dataSnr);
virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
virtual WifiTxVector DoGetDataTxVector (WifiRemoteStation *station);
@@ -72,29 +75,39 @@ private:
/**
* Return the minimum SNR needed to successfully transmit
* data with this mode at the specified BER.
* data with this WifiTxVector at the specified BER.
*
* \param mode WifiMode
* \param txVector WifiTxVector (containing valid mode, width, and nss)
*
* \return the minimum SNR for the given mode
* \return the minimum SNR for the given WifiTxVector
*/
double GetSnrThreshold (WifiMode mode) const;
double GetSnrThreshold (WifiTxVector txVector) const;
/**
* Adds a pair of WifiMode and the minimum SNR for that given mode
* Adds a pair of WifiTxVector and the minimum SNR for that given vector
* to the list.
*
* \param mode WifiMode
* \param snr the minimum SNR for the given mode
* \param txVector the WifiTxVector storing mode, channel width, and nss
* \param snr the minimum SNR for the given txVector
*/
void AddModeSnrThreshold (WifiMode mode, double snr);
void AddSnrThreshold (WifiTxVector txVector, double snr);
/**
* A vector of <snr, mode> pair that holds the minimum SNR for different mode
* Convenience function for selecting a channel width for legacy mode
* \param non-(V)HT WifiMode
* \return the channel width (MHz) for the selected mode
*/
typedef std::vector<std::pair<double,WifiMode> > Thresholds;
uint32_t GetChannelWidthForMode (WifiMode mode) const;
/**
* A vector of <snr, WifiTxVector> pair holding the minimum SNR for the
* WifiTxVector
*/
typedef std::vector<std::pair<double, WifiTxVector> > Thresholds;
double m_ber; //!< The maximum Bit Error Rate acceptable at any transmission mode
Thresholds m_thresholds; //!< List of WifiMode and the minimum SNR pair
Thresholds m_thresholds; //!< List of WifiTxVector and the minimum SNR pair
TracedValue<uint64_t> m_currentRate; //!< Trace rate changes
};
} //namespace ns3