From c6614ad0003ade1aa892d448d5e82982b6bfa56c Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Tue, 4 Jul 2017 20:52:51 +0200 Subject: [PATCH] wifi: (fixes #2733) Support NSS > 1 in ideal wifi manager --- RELEASE_NOTES | 1 + src/wifi/examples/wifi-manager-example.cc | 12 ++++ src/wifi/model/ideal-wifi-manager.cc | 74 +++++++++++------------ 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index e7f853ca6..6ef5725d1 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -104,6 +104,7 @@ Bugs fixed - Bug 2673 - run-time channel switch does not update WiFi spectrum model - Bug 2717 - Fix mask generation for Ipv4RoutingTableEntry::CreateDefaultRoute - Bug 2722 - 802.11g sends DSSS spectrum signals using CreateOfdmTxPowerSpectralDensity +- Bug 2733 - Ideal wifi manager cannot handle NSS higher than 1 - Bug 2741 - IPv4 fragmentation fails when last fragment have to be re-fragmented. - Bug 2744 - 802.11n/ac with RTS/CTS is crashing for a large number of nodes - Bug 2757 - 802.11n/ac/ax maximum TXOP is not properly enforced diff --git a/src/wifi/examples/wifi-manager-example.cc b/src/wifi/examples/wifi-manager-example.cc index ae9db9050..1cdc7c9fe 100644 --- a/src/wifi/examples/wifi-manager-example.cc +++ b/src/wifi/examples/wifi-manager-example.cc @@ -182,6 +182,18 @@ int main (int argc, char *argv[]) cmd.AddValue ("infrastructure", "Use infrastructure instead of adhoc", infrastructure); cmd.Parse (argc,argv); + // Print out some explanation of what this program does + std::cout << std::endl << "This program demonstrates and plots the operation of different " << std::endl; + std::cout << "Wi-Fi rate controls on different station configurations," << std::endl; + std::cout << "by stepping down the received signal strength across a wide range" << std::endl; + std::cout << "and observing the adjustment of the rate." << std::endl; + std::cout << "Run 'wifi-manager-example --PrintHelp' to show program options."<< std::endl << std::endl; + + if (infrastructure == false) + { + NS_ABORT_MSG_IF (serverNss != clientNss, "In ad hoc mode, we assume sender and receiver are similarly configured"); + } + if (standard == "802.11b") { NS_ABORT_MSG_IF (serverChannelWidth != 22 && serverChannelWidth != 22, "Invalid channel width for standard " << standard); diff --git a/src/wifi/model/ideal-wifi-manager.cc b/src/wifi/model/ideal-wifi-manager.cc index c15acda69..bf444f152 100644 --- a/src/wifi/model/ideal-wifi-manager.cc +++ b/src/wifi/model/ideal-wifi-manager.cc @@ -38,6 +38,9 @@ struct IdealWifiRemoteStation : public WifiRemoteStation WifiMode m_lastMode; //!< Mode most recently used to the remote station }; +// To avoid using the cache before a valid value has been cached +static const double CACHE_INITIAL_VALUE = -100; + NS_OBJECT_ENSURE_REGISTERED (IdealWifiManager); NS_LOG_COMPONENT_DEFINE ("IdealWifiManager"); @@ -148,8 +151,7 @@ IdealWifiManager::DoInitialize () { guardInterval = GetPhy ()->GetGuardInterval ().GetNanoSeconds (); } - uint8_t maxNss = GetPhy ()->GetMaxSupportedTxSpatialStreams (); - for (uint8_t i = 1; i <= maxNss; i++) + for (uint8_t i = 1; i <= GetPhy ()->GetMaxSupportedTxSpatialStreams (); i++) { NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () << " channel width " << (uint16_t) j << @@ -204,7 +206,7 @@ IdealWifiManager::DoCreateStation (void) const NS_LOG_FUNCTION (this); IdealWifiRemoteStation *station = new IdealWifiRemoteStation (); station->m_lastSnrObserved = 0.0; - station->m_lastSnrCached = 0.0; + station->m_lastSnrCached = CACHE_INITIAL_VALUE; station->m_lastMode = GetDefaultMode (); station->m_nss = 1; return station; @@ -280,17 +282,17 @@ 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 + //highest data rate for which the snr threshold is smaller than m_lastSnr //to ensure correct packet delivery. - double maxThreshold = 0.0; WifiMode maxMode = GetDefaultMode (); WifiTxVector txVector; WifiMode mode; + uint64_t bestRate = 0; uint8_t selectedNss = 1; uint16_t guardInterval; uint8_t channelWidth = std::min (GetChannelWidth (station), GetPhy ()->GetChannelWidth ()); txVector.SetChannelWidth (channelWidth); - if (station->m_lastSnrObserved == station->m_lastSnrCached) + if (station->m_lastSnrCached != CACHE_INITIAL_VALUE && station->m_lastSnrObserved == station->m_lastSnrCached) { // SNR has not changed, so skip the search and use the last // mode selected @@ -298,7 +300,8 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) selectedNss = station->m_nss; NS_LOG_DEBUG ("Using cached mode = " << maxMode.GetUniqueName () << " last snr observed " << station->m_lastSnrObserved << - " cached " << station->m_lastSnrCached); + " cached " << station->m_lastSnrCached << + " nss " << (uint16_t) selectedNss); } else { @@ -326,7 +329,8 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) // Derive NSS from the MCS index. There is a different mode for each possible NSS value. uint8_t nss = (mode.GetMcsValue () / 8) + 1; txVector.SetNss (nss); - if (WifiPhy::IsValidTxVector (txVector) == false) + if (WifiPhy::IsValidTxVector (txVector) == false || + nss > GetNumberOfSupportedStreams (st)) { NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << " nss " << (uint16_t) nss << " width " << @@ -334,18 +338,20 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) continue; } double threshold = GetSnrThreshold (txVector); - NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << - " threshold " << threshold << " maxThreshold " << - maxThreshold << " last snr observed " << + uint64_t dataRate = mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), nss); + NS_LOG_DEBUG ("Testing mode " << mode.GetUniqueName () << + " data rate " << dataRate << + " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved << " cached " << station->m_lastSnrCached); - if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) + if (dataRate > bestRate && threshold < station->m_lastSnrObserved) { NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << + " data rate " << dataRate << " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved); - maxThreshold = threshold; + bestRate = dataRate; maxMode = mode; selectedNss = nss; } @@ -364,14 +370,8 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) { continue; } - uint8_t maxNss = GetPhy ()->GetMaxSupportedTxSpatialStreams (); - for (uint8_t nss = 1; nss <= maxNss; nss++) + for (uint8_t nss = 1; nss <= GetNumberOfSupportedStreams (station); nss++) { - // If the peer does not support more streams, stop searching. - if (GetNumberOfSupportedStreams (station) < nss) - { - break; - } txVector.SetNss (nss); if (WifiPhy::IsValidTxVector (txVector) == false) { @@ -381,18 +381,20 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) continue; } double threshold = GetSnrThreshold (txVector); + uint64_t dataRate = mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), nss); NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << - " threshold " << threshold << " maxThreshold " << - maxThreshold << " last snr observed " << + " data rate " << dataRate << + " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved << " cached " << station->m_lastSnrCached); - if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) + if (dataRate > bestRate && threshold < station->m_lastSnrObserved) { NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << + " data rate " << dataRate << " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved); - maxThreshold = threshold; + bestRate = dataRate; maxMode = mode; selectedNss = nss; } @@ -407,14 +409,8 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) { continue; } - uint8_t maxNss = GetPhy ()->GetMaxSupportedTxSpatialStreams (); - for (uint8_t nss = 1; nss <= maxNss; nss++) + for (uint8_t nss = 1; nss <= GetNumberOfSupportedStreams (station); nss++) { - // If the peer does not support more streams, stop searching. - if (GetNumberOfSupportedStreams (station) < nss) - { - break; - } txVector.SetNss (nss); if (WifiPhy::IsValidTxVector (txVector) == false) { @@ -424,18 +420,20 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) continue; } double threshold = GetSnrThreshold (txVector); + uint64_t dataRate = mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), nss); NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << - " threshold " << threshold << " maxThreshold " << - maxThreshold << " last snr observed " << + " data rate " << dataRate << + " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved << " cached " << station->m_lastSnrCached); - if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) + if (dataRate > bestRate && threshold < station->m_lastSnrObserved) { NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << + " data rate " << dataRate << " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved); - maxThreshold = threshold; + bestRate = dataRate; maxMode = mode; selectedNss = nss; } @@ -454,17 +452,19 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) txVector.SetNss (selectedNss); txVector.SetChannelWidth (GetChannelWidthForMode (mode)); double threshold = GetSnrThreshold (txVector); + uint64_t dataRate = mode.GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), txVector.GetNss ()); NS_LOG_DEBUG ("mode = " << mode.GetUniqueName () << " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved); - if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) + if (dataRate > bestRate && threshold < station->m_lastSnrObserved) { NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << + " data rate " << dataRate << " threshold " << threshold << " last snr observed " << station->m_lastSnrObserved); - maxThreshold = threshold; + bestRate = dataRate; maxMode = mode; } }