From 2abd8881570481a3bbc45b5de29c41fcee1b3bcb Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 9 Mar 2016 22:58:13 -0800 Subject: [PATCH] wifi (partial fix #1797) Update IdealWifiManager for HT/VHT --- src/wifi/model/ideal-wifi-manager.cc | 304 +++++++++++++++++++++------ src/wifi/model/ideal-wifi-manager.h | 35 ++- 2 files changed, 266 insertions(+), 73 deletions(-) diff --git a/src/wifi/model/ideal-wifi-manager.cc b/src/wifi/model/ideal-wifi-manager.cc index 255673ab2..60a4771ed 100644 --- a/src/wifi/model/ideal-wifi-manager.cc +++ b/src/wifi/model/ideal-wifi-manager.cc @@ -22,10 +22,9 @@ #include "wifi-phy.h" #include "ns3/assert.h" #include "ns3/double.h" +#include "ns3/log.h" #include -#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 () .AddAttribute ("BerThreshold", "The maximum Bit Error Rate acceptable at any transmission mode", - DoubleValue (10e-6), + DoubleValue (1e-5), MakeDoubleAccessor (&IdealWifiManager::m_ber), MakeDoubleChecker ()) + .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 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 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 diff --git a/src/wifi/model/ideal-wifi-manager.h b/src/wifi/model/ideal-wifi-manager.h index 5bebdd281..f3fff694e 100644 --- a/src/wifi/model/ideal-wifi-manager.h +++ b/src/wifi/model/ideal-wifi-manager.h @@ -23,6 +23,7 @@ #include #include +#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 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 > Thresholds; + uint32_t GetChannelWidthForMode (WifiMode mode) const; + + /** + * A vector of pair holding the minimum SNR for the + * WifiTxVector + */ + typedef std::vector > 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 m_currentRate; //!< Trace rate changes }; } //namespace ns3