# HG changeset patch # User Tom Henderson # Date 1461358875 25200 # Fri Apr 22 14:01:15 2016 -0700 # Node ID 8a21f6e3bf751cadfc7bc5b718c951cb36ae1cb4 # Parent 67a0fea6a7ccfcea50b885bc5632569768228633 wifi: (fixes #2385) Avoid invalid WifiTxVector in IdealWifiManager diff -r 67a0fea6a7cc -r 8a21f6e3bf75 src/wifi/model/ideal-wifi-manager.cc --- a/src/wifi/model/ideal-wifi-manager.cc Fri Apr 22 02:27:25 2016 +0200 +++ b/src/wifi/model/ideal-wifi-manager.cc Fri Apr 22 14:01:15 2016 -0700 @@ -37,7 +37,7 @@ { 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 + double m_nss; //!< spatial stream recently used to remote station WifiMode m_lastMode; //!< Mode most recently used to the remote station }; @@ -118,7 +118,7 @@ " short GI " << GetPhy ()->GetGuardInterval ()); AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); } - // Add all Ht and Vht MCSes + // Add all supported Ht and Vht MCSes txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); if (HasVhtSupported () == true || HasHtSupported () == true ) { @@ -126,23 +126,36 @@ for (uint32_t i = 0; i < nModes; i++) { mode = GetPhy ()->GetMcs (i); - if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + txVector.SetMode (mode); + for (uint8_t j = 1; j <= GetPhy ()->GetSupportedTxSpatialStreams (); j++) { - //derive NSS from the Mcs index - nss = (mode.GetMcsValue () / 8) + 1; + if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + //derive NSS from the Mcs index + nss = (mode.GetMcsValue () / 8) + 1; + if (nss != j) + { + continue; + } + } + else + { + nss = j; + } + txVector.SetNss (nss); + if (IsSupportedTxVector (txVector) && WifiPhy::IsValidTxVector (txVector)) + { + NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () << + " channel width " << GetPhy ()->GetChannelWidth () << + " nss " << (uint16_t) nss << + " short GI " << GetPhy ()->GetGuardInterval ()); + AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); + } + else + { + NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << " as unsupported"); + } } - 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)); } } } @@ -264,6 +277,7 @@ //to ensure correct packet delivery. double maxThreshold = 0.0; WifiMode maxMode = GetDefaultMode (); + uint8_t maxNss = 1; std::vector candidateTxVectors; WifiTxVector txVector; WifiMode mode; @@ -275,7 +289,7 @@ // SNR has not changed, so skip the search and use the last // mode selected maxMode = station->m_lastMode; - nss = station->m_nss; + maxNss = station->m_nss; NS_LOG_DEBUG ("Using cached mode = " << maxMode.GetUniqueName () << " last snr observed " << station->m_lastSnrObserved << " cached " << station->m_lastSnrCached); @@ -298,10 +312,10 @@ nss = GetPhy ()->GetSupportedTxSpatialStreams (); } txVector.SetNss (nss); - if (WifiPhy::IsValidTxVector (txVector) == false) + if (WifiPhy::IsValidTxVector (txVector) == false || IsSupportedTxVector (txVector) == false) { NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << - " nss " << nss << " width " << + " nss " << (uint16_t) nss << " width " << txVector.GetChannelWidth()); continue; } @@ -329,6 +343,7 @@ station->m_lastSnrObserved); maxThreshold = threshold; maxMode = mode; + maxNss = nss; } } } @@ -355,22 +370,23 @@ station->m_lastSnrObserved); maxThreshold = threshold; maxMode = mode; + maxNss = nss; } } } - NS_LOG_DEBUG ("Updating cached values for station to " << maxMode.GetUniqueName () << " snr " << station->m_lastSnrObserved); + NS_LOG_DEBUG ("Updating cached values for station to " << maxMode.GetUniqueName () << " snr " << station->m_lastSnrObserved << " nss " << uint16_t (maxNss)); station->m_lastSnrCached = station->m_lastSnrObserved; station->m_lastMode = maxMode; - station->m_nss = nss; + station->m_nss = maxNss; } uint32_t channelWidth = GetChannelWidth (station); NS_LOG_DEBUG ("Found maxMode: " << maxMode << " channelWidth: " << channelWidth); - if (m_currentRate != maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss)) + if (m_currentRate != maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), maxNss)) { - NS_LOG_DEBUG ("New datarate: " << maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss)); - m_currentRate = maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss); + NS_LOG_DEBUG ("New datarate: " << maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), maxNss)); + m_currentRate = maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), maxNss); } - return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, nss, 0, channelWidth, GetAggregation (station), false); + return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, maxNss, 0, channelWidth, GetAggregation (station), false); } WifiTxVector @@ -411,4 +427,14 @@ return true; } +bool +IdealWifiManager::IsSupportedTxVector (const WifiTxVector txVector) const +{ + if (txVector.GetNss () > GetPhy ()->GetSupportedTxSpatialStreams ()) + { + return false; + } + return true; +} + } //namespace ns3 diff -r 67a0fea6a7cc -r 8a21f6e3bf75 src/wifi/model/ideal-wifi-manager.h --- a/src/wifi/model/ideal-wifi-manager.h Fri Apr 22 02:27:25 2016 +0200 +++ b/src/wifi/model/ideal-wifi-manager.h Fri Apr 22 14:01:15 2016 -0700 @@ -74,6 +74,21 @@ virtual bool IsLowLatency (void) const; /** + * Return true or false depending on whether the txVector is supported + * for transmitting. The list of supported modes stored in the + * WifiPhy may be larger than the list of usable modes for sending data + * because the number of transmit antennas and receive antennas may + * be unequal. + * + * Note that WifiPhy has a similar IsValidTxVector() that may be used + * to check whether the standard allows the combination of channel width, + * NSS, and MCS. + * + * \param txVector the txVector to check + * \return true if the station can transmit using this txVector + */ + bool IsSupportedTxVector (const WifiTxVector txVector) const; + /** * Return the minimum SNR needed to successfully transmit * data with this WifiTxVector at the specified BER. *