From 1af7e9391b144ff83dcb40e764adb425f7e75fc5 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Thu, 3 Jun 2010 22:38:44 -0700 Subject: [PATCH] Fixed Bug 802 and Bug 919 --- src/devices/wifi/minstrel-wifi-manager.cc | 251 ++++++++++------------ src/devices/wifi/minstrel-wifi-manager.h | 48 +++++ test.py | 1 + 3 files changed, 160 insertions(+), 140 deletions(-) diff --git a/src/devices/wifi/minstrel-wifi-manager.cc b/src/devices/wifi/minstrel-wifi-manager.cc index 21fd7b433..42e2d7aec 100644 --- a/src/devices/wifi/minstrel-wifi-manager.cc +++ b/src/devices/wifi/minstrel-wifi-manager.cc @@ -44,54 +44,10 @@ NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager"); namespace ns3 { -/** - * A struct to contain all information related to a data rate - */ -struct RateInfo -{ - /** - * Perfect transmission time calculation, or frame calculation - * Given a bit rate and a packet length n bytes - */ - Time perfectTxTime; - - - uint32_t retryCount; ///< retry limit - uint32_t adjustedRetryCount; ///< adjust the retry limit for this rate - uint32_t numRateAttempt; ///< how many number of attempts so far - uint32_t numRateSuccess; ///< number of successful pkts - uint32_t prob; ///< (# pkts success )/(# total pkts) - - /** - * EWMA calculation - * ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100 - */ - uint32_t ewmaProb; - - uint32_t prevNumRateAttempt; ///< from last rate - uint32_t prevNumRateSuccess; ///< from last rate - uint64_t successHist; ///< aggregate of all successes - uint64_t attemptHist; ///< aggregate of all attempts - uint32_t throughput; ///< throughput of a rate -}; - -/** - * Data structure for a Minstrel Rate table - * A vector of a struct RateInfo - */ -typedef std::vector MinstrelRate; - -/** - * Data structure for a Sample Rate table - * A vector of a vector uint32_t - */ -typedef std::vector > SampleRate; struct MinstrelWifiRemoteStation : public WifiRemoteStation { Time m_nextStatsUpdate; ///< 10 times every second - MinstrelRate m_minstrelTable; ///< minstrel table - SampleRate m_sampleTable; ///< sample table /** * To keep track of the current position in the our random sample table @@ -164,7 +120,9 @@ MinstrelWifiManager::GetTypeId (void) } MinstrelWifiManager::MinstrelWifiManager () -{} +{ + m_nsupported = 0; +} MinstrelWifiManager::~MinstrelWifiManager () {} @@ -232,13 +190,14 @@ MinstrelWifiManager::DoCreateStation (void) const void MinstrelWifiManager::CheckInit(MinstrelWifiRemoteStation *station) { - if (!station->m_initialized) + if (!station->m_initialized && GetNSupported (station) > 1) { // 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_minstrelTable = MinstrelRate(GetNSupported (station)); - station->m_sampleTable = SampleRate(GetNSupported (station), std::vector (m_sampleCol)); + m_nsupported = GetNSupported (station); + m_minstrelTable = MinstrelRate(m_nsupported); + m_sampleTable = SampleRate(m_nsupported, std::vector (m_sampleCol)); InitSampleTable (station); RateInit (station); station->m_initialized = true; @@ -296,6 +255,10 @@ MinstrelWifiManager::DoReportDataFailed (WifiRemoteStation *st) */ CheckInit(station); + if (!station->m_initialized) + { + return; + } station->m_longRetry++; @@ -305,30 +268,30 @@ MinstrelWifiManager::DoReportDataFailed (WifiRemoteStation *st) if (!station->m_isSampling) { /// use best throughput rate - if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount) + if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount) { ; ///< there's still a few retries left } /// use second best throughput rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) { station->m_txrate = station->m_maxTpRate2; } /// use best probability rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) { station->m_txrate = station->m_maxProbRate; } /// use lowest base rate - else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) + else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) { station->m_txrate = 0; } @@ -341,30 +304,30 @@ MinstrelWifiManager::DoReportDataFailed (WifiRemoteStation *st) if (station->m_sampleRateSlower) { /// use best throughput rate - if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount) + if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount) { ; ///< there are a few retries left } /// use random rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) { station->m_txrate = station->m_sampleRate; } /// use max probability rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount )) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_sampleRate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount )) { station->m_txrate = station->m_maxProbRate; } /// use lowest base rate - else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) + else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_sampleRate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)) { station->m_txrate = 0; } @@ -374,30 +337,30 @@ MinstrelWifiManager::DoReportDataFailed (WifiRemoteStation *st) else { /// use random rate - if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount) + if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount) { ; ///< keep using it } /// use the best rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) { station->m_txrate = station->m_maxTpRate; } /// use the best probability rate - else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount + - station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) + else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount + + m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) { station->m_txrate = station->m_maxProbRate; } /// use the lowest base rate - else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + - station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount + - station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) + else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount + + m_minstrelTable[station->m_maxTpRate].adjustedRetryCount + + m_minstrelTable[station->m_sampleRate].adjustedRetryCount)) { station->m_txrate = 0; } @@ -415,16 +378,20 @@ MinstrelWifiManager::DoReportDataOk (WifiRemoteStation *st, station->m_sampleRateSlower=false; CheckInit (station); + if (!station->m_initialized) + { + return; + } - station->m_minstrelTable[station->m_txrate].numRateSuccess++; - station->m_minstrelTable[station->m_txrate].numRateAttempt++; + m_minstrelTable[station->m_txrate].numRateSuccess++; + m_minstrelTable[station->m_txrate].numRateAttempt++; UpdateRetry (station); - station->m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry; + m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry; station->m_packetCount++; - if (GetNSupported (station) >= 1) + if (m_nsupported >= 1) { station->m_txrate = FindRate (station); } @@ -441,10 +408,10 @@ MinstrelWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st) UpdateRetry (station); - station->m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry; + m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry; station->m_err++; - if (GetNSupported (station) >= 1) + if (m_nsupported >= 1) { station->m_txrate = FindRate (station); } @@ -468,7 +435,7 @@ MinstrelWifiManager::DoGetDataMode (WifiRemoteStation *st, CheckInit (station); /// start the rate at half way - station->m_txrate = GetNSupported (station) / 2; + station->m_txrate = m_nsupported / 2; } UpdateStats (station); return GetSupported (station, station->m_txrate); @@ -492,11 +459,11 @@ uint32_t MinstrelWifiManager::GetNextSample (MinstrelWifiRemoteStation *station) { uint32_t bitrate; - bitrate = station->m_sampleTable[station->m_index][station->m_col]; + bitrate = m_sampleTable[station->m_index][station->m_col]; station->m_index++; /// bookeeping for m_index and m_col variables - if (station->m_index > (GetNSupported (station) - 2)) + if (station->m_index > (m_nsupported - 2)) { station->m_index =0; station->m_col++; @@ -558,7 +525,7 @@ MinstrelWifiManager::FindRate (MinstrelWifiRemoteStation *station) } /// error check - if (idx >= GetNSupported (station) || idx < 0) + if (idx >= m_nsupported || idx < 0) { NS_LOG_DEBUG ("ALERT!!! ERROR"); } @@ -573,7 +540,7 @@ MinstrelWifiManager::FindRate (MinstrelWifiRemoteStation *station) /// is this rate slower than the current best rate station->m_sampleRateSlower = - (station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime); + (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[station->m_maxTpRate].perfectTxTime); /// using the best rate instead if (station->m_sampleRateSlower) @@ -604,6 +571,10 @@ MinstrelWifiManager::UpdateStats (MinstrelWifiRemoteStation *station) return; } + if (!station->m_initialized) + { + return; + } NS_LOG_DEBUG ("Updating stats="<m_nextStatsUpdate = Simulator::Now () + m_updateStats; @@ -611,11 +582,11 @@ MinstrelWifiManager::UpdateStats (MinstrelWifiRemoteStation *station) Time txTime; uint32_t tempProb; - for (uint32_t i =0; i < GetNSupported (station); i++) + for (uint32_t i =0; i < m_nsupported; i++) { /// calculate the perfect tx time for this rate - txTime = station->m_minstrelTable[i].perfectTxTime; + txTime = m_minstrelTable[i].perfectTxTime; /// just for initialization if (txTime.GetMicroSeconds () == 0) @@ -624,61 +595,61 @@ MinstrelWifiManager::UpdateStats (MinstrelWifiRemoteStation *station) } NS_LOG_DEBUG ("m_txrate=" << station->m_txrate << - "\t attempt=" << station->m_minstrelTable[i].numRateAttempt << - "\t success=" << station->m_minstrelTable[i].numRateSuccess); + "\t attempt=" << m_minstrelTable[i].numRateAttempt << + "\t success=" << m_minstrelTable[i].numRateSuccess); /// if we've attempted something - if (station->m_minstrelTable[i].numRateAttempt) + if (m_minstrelTable[i].numRateAttempt) { /** * calculate the probability of success * assume probability scales from 0 to 18000 */ - tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt; + tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt; /// bookeeping - station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess; - station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt; - station->m_minstrelTable[i].prob = tempProb; + m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess; + m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt; + m_minstrelTable[i].prob = tempProb; /// ewma probability (cast for gcc 3.4 compatibility) - tempProb = static_cast(((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) )/100); + tempProb = static_cast(((tempProb * (100 - m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_ewmaLevel) )/100); - station->m_minstrelTable[i].ewmaProb = tempProb; + m_minstrelTable[i].ewmaProb = tempProb; /// calculating throughput - station->m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds()); + m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds()); } /// bookeeping - station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt; - station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess; - station->m_minstrelTable[i].numRateSuccess = 0; - station->m_minstrelTable[i].numRateAttempt = 0; + m_minstrelTable[i].prevNumRateAttempt = m_minstrelTable[i].numRateAttempt; + m_minstrelTable[i].prevNumRateSuccess = m_minstrelTable[i].numRateSuccess; + m_minstrelTable[i].numRateSuccess = 0; + m_minstrelTable[i].numRateAttempt = 0; /// Sample less often below 10% and above 95% of success - if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800)) + if ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800)) { /** * retry count denotes the number of retries permitted for each rate * # retry_count/2 */ - station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount >> 1; - if (station->m_minstrelTable[i].adjustedRetryCount > 2) + m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1; + if (m_minstrelTable[i].adjustedRetryCount > 2) { - station->m_minstrelTable[i].adjustedRetryCount = 2 ; + m_minstrelTable[i].adjustedRetryCount = 2 ; } } else { - station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount; + m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount; } /// if it's 0 allow one retry limit - if (station->m_minstrelTable[i].adjustedRetryCount == 0) + if (m_minstrelTable[i].adjustedRetryCount == 0) { - station->m_minstrelTable[i].adjustedRetryCount = 1; + m_minstrelTable[i].adjustedRetryCount = 1; } } @@ -686,33 +657,33 @@ MinstrelWifiManager::UpdateStats (MinstrelWifiRemoteStation *station) uint32_t max_prob = 0, index_max_prob =0, max_tp =0, index_max_tp=0, index_max_tp2=0; /// go find max throughput, second maximum throughput, high probability succ - for (uint32_t i =0; i < GetNSupported (station); i++) + for (uint32_t i =0; i < m_nsupported; i++) { - NS_LOG_DEBUG ("throughput" << station->m_minstrelTable[i].throughput << - "\n ewma" << station->m_minstrelTable[i].ewmaProb); + NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput << + "\n ewma" << m_minstrelTable[i].ewmaProb); - if (max_tp < station->m_minstrelTable[i].throughput) + if (max_tp < m_minstrelTable[i].throughput) { index_max_tp = i; - max_tp = station->m_minstrelTable[i].throughput; + max_tp = m_minstrelTable[i].throughput; } - if (max_prob < station->m_minstrelTable[i].ewmaProb) + if (max_prob < m_minstrelTable[i].ewmaProb) { index_max_prob = i; - max_prob = station->m_minstrelTable[i].ewmaProb; + max_prob = m_minstrelTable[i].ewmaProb; } } max_tp = 0; /// find the second highest max - for (uint32_t i =0; i < GetNSupported (station); i++) + for (uint32_t i =0; i < m_nsupported; i++) { - if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput)) + if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput)) { index_max_tp2 = i; - max_tp = station->m_minstrelTable[i].throughput; + max_tp = m_minstrelTable[i].throughput; } } @@ -737,20 +708,20 @@ MinstrelWifiManager::RateInit (MinstrelWifiRemoteStation *station) { NS_LOG_DEBUG ("RateInit="<m_minstrelTable[i].numRateAttempt = 0; - station->m_minstrelTable[i].numRateSuccess = 0; - station->m_minstrelTable[i].prob = 0; - station->m_minstrelTable[i].ewmaProb = 0; - station->m_minstrelTable[i].prevNumRateAttempt = 0; - station->m_minstrelTable[i].prevNumRateSuccess = 0; - station->m_minstrelTable[i].successHist = 0; - station->m_minstrelTable[i].attemptHist = 0; - station->m_minstrelTable[i].throughput = 0; - station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i)); - station->m_minstrelTable[i].retryCount = 1; - station->m_minstrelTable[i].adjustedRetryCount = 1; + m_minstrelTable[i].numRateAttempt = 0; + m_minstrelTable[i].numRateSuccess = 0; + m_minstrelTable[i].prob = 0; + m_minstrelTable[i].ewmaProb = 0; + m_minstrelTable[i].prevNumRateAttempt = 0; + m_minstrelTable[i].prevNumRateSuccess = 0; + m_minstrelTable[i].successHist = 0; + m_minstrelTable[i].attemptHist = 0; + m_minstrelTable[i].throughput = 0; + m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i)); + m_minstrelTable[i].retryCount = 1; + m_minstrelTable[i].adjustedRetryCount = 1; } } @@ -762,7 +733,7 @@ MinstrelWifiManager::InitSampleTable (MinstrelWifiRemoteStation *station) station->m_col = station->m_index = 0; /// for off-seting to make rates fall between 0 and numrates - uint32_t numSampleRates = GetNSupported (station); + uint32_t numSampleRates = m_nsupported; uint32_t newIndex; for (uint32_t col = 0; col < m_sampleCol; col++) @@ -778,11 +749,11 @@ MinstrelWifiManager::InitSampleTable (MinstrelWifiRemoteStation *station) newIndex = (i + (uint32_t)uv.GetValue ()) % numSampleRates; /// this loop is used for filling in other uninitilized places - while (station->m_sampleTable[newIndex][col] != 0) + while (m_sampleTable[newIndex][col] != 0) { - newIndex = (newIndex + 1)%GetNSupported (station); + newIndex = (newIndex + 1) % m_nsupported; } - station->m_sampleTable[newIndex][col] = i; + m_sampleTable[newIndex][col] = i; } } @@ -793,12 +764,12 @@ MinstrelWifiManager::PrintSampleTable (MinstrelWifiRemoteStation *station) { NS_LOG_DEBUG ("PrintSampleTable="<m_sampleTable[i][j] << "\t"; + std::cout << m_sampleTable[i][j] << "\t"; } std::cout << std::endl; } @@ -809,9 +780,9 @@ MinstrelWifiManager::PrintTable (MinstrelWifiRemoteStation *station) { NS_LOG_DEBUG ("PrintTable="< MinstrelRate; + +/** + * Data structure for a Sample Rate table + * A vector of a vector uint32_t + */ +typedef std::vector > SampleRate; + + class MinstrelWifiManager : public WifiRemoteStationManager { @@ -101,6 +145,9 @@ private: typedef std::vector > TxTime; + MinstrelRate m_minstrelTable; ///< minstrel table + SampleRate m_sampleTable; ///< sample table + TxTime m_calcTxTime; ///< to hold all the calculated TxTime for all modes Time m_updateStats; ///< how frequent do we calculate the stats(1/10 seconds) @@ -109,6 +156,7 @@ private: uint32_t m_segmentSize; ///< largest allowable segment size uint32_t m_sampleCol; ///< number of sample columns uint32_t m_pktLen; ///< packet length used for calculate mode TxTime + uint32_t m_nsupported; ///< modes supported }; }// namespace ns3 diff --git a/test.py b/test.py index 910bc566d..cc8b93ff0 100755 --- a/test.py +++ b/test.py @@ -148,6 +148,7 @@ example_tests = [ ("wireless/multirate --totalTime=0.3s --rateManager=ns3::AmrrWifiManager", "True", "True"), ("wireless/multirate --totalTime=0.3s --rateManager=ns3::CaraWifiManager", "True", "True"), ("wireless/multirate --totalTime=0.3s --rateManager=ns3::IdealWifiManager", "True", "True"), + ("wireless/multirate --totalTime=0.3s --rateManager=ns3::MinstrelWifiManager", "True", "True"), ("wireless/multirate --totalTime=0.3s --rateManager=ns3::OnoeWifiManager", "True", "True"), ("wireless/multirate --totalTime=0.3s --rateManager=ns3::RraaWifiManager", "True", "True"), ("wireless/simple-wifi-frame-aggregation", "True", "True"),