From 63802def2019d95920b4990b32788ccce449bd99 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Thu, 13 Aug 2009 08:45:47 +0200 Subject: [PATCH] add an implementation of the minstrel rate control algorithm --- src/devices/wifi/minstrel-wifi-manager.cc | 720 ++++++++++++++++++++++ src/devices/wifi/minstrel-wifi-manager.h | 255 ++++++++ src/devices/wifi/wscript | 2 + 3 files changed, 977 insertions(+) create mode 100644 src/devices/wifi/minstrel-wifi-manager.cc create mode 100644 src/devices/wifi/minstrel-wifi-manager.h diff --git a/src/devices/wifi/minstrel-wifi-manager.cc b/src/devices/wifi/minstrel-wifi-manager.cc new file mode 100644 index 000000000..5dd91ef69 --- /dev/null +++ b/src/devices/wifi/minstrel-wifi-manager.cc @@ -0,0 +1,720 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 Duy Nguyen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Duy Nguyen + * + * Some Comments: + * + * 1) Segment Size is declared for completeness but not used because it has + * to do more with the requirement of the specific hardware. + * + * 2) By default, Minstrel applies the multi-rate retry(the core of Minstrel + * algorithm). Otherwise, please use ConstantRateWifiManager instead. + * + * http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel + */ + + + +#include "minstrel-wifi-manager.h" +#include "wifi-phy.h" +#include "ns3/random-variable.h" +#include "ns3/simulator.h" +#include "ns3/log.h" +#include "ns3/uinteger.h" +#include "ns3/double.h" +#include "ns3/wifi-mac.h" +#include "ns3/assert.h" +#include + +NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager"); + + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (MinstrelWifiManager); + +TypeId +MinstrelWifiManager::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::MinstrelWifiManager") + .SetParent () + .AddConstructor () + .AddAttribute ("UpdateStatistics", + "The interval between updating statistics table ", + TimeValue (Seconds (0.1)), + MakeTimeAccessor (&MinstrelWifiManager::m_updateStats), + MakeTimeChecker ()) + .AddAttribute ("LookAroundRate", + "the percentage to try other rates", + DoubleValue (10), + MakeDoubleAccessor (&MinstrelWifiManager::m_lookAroundRate), + MakeDoubleChecker ()) + .AddAttribute ("EWMA", + "EWMA level", + DoubleValue (75), + MakeDoubleAccessor (&MinstrelWifiManager::m_ewmaLevel), + MakeDoubleChecker ()) + .AddAttribute ("SegmentSize", + "The largest allowable segment size packet", + DoubleValue (6000), + MakeDoubleAccessor (&MinstrelWifiManager::m_segmentSize), + MakeDoubleChecker ()) + .AddAttribute ("SampleColumn", + "The number of columns used for sampling", + DoubleValue (10), + MakeDoubleAccessor (&MinstrelWifiManager::m_sampleCol), + MakeDoubleChecker ()) + .AddAttribute ("PacketLength", + "The packet length used for calculating mode TxTime", + DoubleValue (1200), + MakeDoubleAccessor (&MinstrelWifiManager::m_pktLen), + MakeDoubleChecker ()) + ; + return tid; +} + +MinstrelWifiManager::MinstrelWifiManager () +{} + +MinstrelWifiManager::~MinstrelWifiManager () +{} + +void +MinstrelWifiManager::SetupPhy (Ptr phy) +{ + uint32_t nModes = phy->GetNModes (); + for (uint32_t i = 0; i < nModes; i++) + { + WifiMode mode = phy->GetMode (i); + AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, mode, WIFI_PREAMBLE_LONG)); + } + WifiRemoteStationManager::SetupPhy (phy); +} + +WifiRemoteStation * +MinstrelWifiManager::CreateStation (void) +{ + return new MinstrelWifiRemoteStation (this); +} + +Time +MinstrelWifiManager::GetCalcTxTime (WifiMode mode) const +{ + + for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++) + { + if (mode == i->second) + { + return i->first; + } + } + NS_ASSERT (false); + return Seconds (0); +} + +void +MinstrelWifiManager::AddCalcTxTime (WifiMode mode, Time t) +{ + m_calcTxTime.push_back (std::make_pair (t, mode)); +} + +MinstrelWifiRemoteStation::MinstrelWifiRemoteStation (Ptr stations) + :m_stations (stations), + m_nextStatsUpdate (Simulator::Now () + stations->m_updateStats), + m_col (0), + m_index (0), + m_maxTpRate (0), + m_maxTpRate2 (0), + m_maxProbRate (0), + m_packetCount (0), + m_sampleCount (0), + m_isSampling (false), + m_sampleRate (0), + m_sampleRateSlower (false), + m_currentRate (0), + m_shortRetry (0), + m_longRetry (0), + m_retry (0), + m_err (0), + m_txrate (0), + m_initialized (false) +{} + +MinstrelWifiRemoteStation::~MinstrelWifiRemoteStation () +{} + +void +MinstrelWifiRemoteStation::CheckInit(void) +{ + if (!m_initialized) + { + m_minstrelTable = MinstrelRate(GetNSupportedModes ()); + m_sampleTable = SampleRate(GetNSupportedModes (), std::vector (m_stations->m_sampleCol)); + InitSampleTable (); + RateInit (); + m_initialized = true; + } +} + +void +MinstrelWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode) +{ + NS_LOG_DEBUG("DoReportRxOk m_txrate=" << m_txrate); +} + +void +MinstrelWifiRemoteStation::DoReportRtsFailed (void) +{ + NS_LOG_DEBUG("DoReportRtsFailed m_txrate=" << m_txrate); + + m_shortRetry++; +} + +void +MinstrelWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) +{ + NS_LOG_DEBUG ("self="< (m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate2].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount)) + { + m_txrate = 0; + } + } + + /// for look-around rate, we're currently sampling random rates + else + { + /// current sampling rate is slower than the current best rate + if (m_sampleRateSlower) + { + /// use best throughput rate + if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount) + { + ; ///< there are a few retries left + } + + /// use random rate + else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount)) + { + m_txrate = m_sampleRate; + } + + /// use max probability rate + else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_sampleRate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount )) + { + m_txrate = m_maxProbRate; + } + + /// use lowest base rate + else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_sampleRate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount)) + { + m_txrate = 0; + } + } + + /// current sampling rate is better than current best rate + else + { + /// use random rate + if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount) + { + ; ///< keep using it + } + + /// use the best rate + else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_sampleRate].adjustedRetryCount) + { + m_txrate = m_maxTpRate; + } + + /// use the best probability rate + else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount + + m_minstrelTable[m_sampleRate].adjustedRetryCount) + { + m_txrate = m_maxProbRate; + } + + /// use the lowest base rate + else if (m_longRetry > m_minstrelTable[m_txrate].adjustedRetryCount + + m_minstrelTable[m_maxTpRate].adjustedRetryCount + + m_minstrelTable[m_sampleRate].adjustedRetryCount) + { + m_txrate = 0; + } + } + } +} + +void +MinstrelWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr) +{ + m_isSampling = false; + m_sampleRateSlower=false; + + CheckInit (); + + m_minstrelTable[m_txrate].numRateSuccess++; + m_minstrelTable[m_txrate].numRateAttempt++; + + UpdateRetry (); + + m_minstrelTable[m_txrate].numRateAttempt += m_retry; + m_packetCount++; + + if (GetNSupportedModes () >= 1) + { + m_txrate = FindRate (); + } +} + +void +MinstrelWifiRemoteStation::DoReportFinalDataFailed (void) +{ + NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << m_txrate); + + m_isSampling = false; + m_sampleRateSlower=false; + + UpdateRetry (); + + m_minstrelTable[m_txrate].numRateAttempt += m_retry; + m_err++; + + if (GetNSupportedModes () >= 1) + { + m_txrate = FindRate (); + } +} + +void +MinstrelWifiRemoteStation::UpdateRetry (void) +{ + m_retry = m_shortRetry + m_longRetry; + m_shortRetry = 0; + m_longRetry = 0; +} + +Ptr +MinstrelWifiRemoteStation::GetManager (void) const +{ + return m_stations; +} + +WifiMode +MinstrelWifiRemoteStation::DoGetDataMode (uint32_t size) +{ + UpdateStats (); + if (!m_initialized) + { + CheckInit (); + + /// start the rate at half way + m_txrate = GetNSupportedModes () / 2; + } + return GetSupportedMode (m_txrate); +} + +WifiMode +MinstrelWifiRemoteStation::DoGetRtsMode (void) +{ + NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << m_txrate); + + UpdateStats (); + return GetSupportedMode (0); +} + +uint32_t +MinstrelWifiRemoteStation::GetNextSample () +{ + uint32_t bitrate; + bitrate = m_sampleTable[m_index][m_col]; + m_index++; + + /// bookeeping for m_index and m_col variables + if (m_index > (GetNSupportedModes () -2)) + { + m_index =0; + m_col++; + if (m_col >= m_stations->m_sampleCol) + { + m_col = 0; + } + } + return bitrate; +} + +uint32_t +MinstrelWifiRemoteStation::FindRate () +{ + NS_LOG_DEBUG ("FindRate " << "packet=" << m_packetCount ); + + if ((m_sampleCount + m_packetCount) == 0) + { + return 0; + } + + + uint32_t idx; + + /// for determining when to try a sample rate + UniformVariable coinFlip (0, 100); + + /** + * if we are below the target of look around rate percentage, look around + * note: do it randomly by flipping a coin instead sampling + * all at once until it reaches the look around rate + */ + if ( (((100* m_sampleCount) / (m_sampleCount + m_packetCount )) < m_stations->m_lookAroundRate) && + ((int)coinFlip.GetValue ()) % 2 == 1 ) + { + + /// now go through the table and find an index rate + idx = GetNextSample (); + + + /** + * This if condition is used to make sure that we don't need to use + * the sample rate it is the same as our current rate + */ + if (idx != m_maxTpRate && idx != m_txrate) + { + + /// start sample count + m_sampleCount++; + + /// set flag that we are currently sampling + m_isSampling = true; + + /// bookeeping for resetting stuff + if (m_packetCount >= 10000) + { + m_sampleCount = 0; + m_packetCount = 0; + } + + /// error check + if (idx >= GetNSupportedModes () || idx < 0 ) + { + NS_LOG_DEBUG ("ALERT!!! ERROR"); + } + + /// set the rate that we're currently sampling + m_sampleRate = idx; + + if (m_sampleRate == m_maxTpRate) + { + m_sampleRate = m_maxTpRate2; + } + + /// is this rate slower than the current best rate + m_sampleRateSlower = (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[m_maxTpRate].perfectTxTime); + + /// using the best rate instead + if (m_sampleRateSlower) + { + idx = m_maxTpRate; + } + } + + } + + /// continue using the best rate + else + { + idx = m_maxTpRate; + } + + + NS_LOG_DEBUG ("FindRate " << "sample rate=" << idx); + + return idx; +} + +void +MinstrelWifiRemoteStation::UpdateStats () +{ + if (Simulator::Now () < m_nextStatsUpdate) + { + return; + } + + NS_LOG_DEBUG ("Updating stats="<m_updateStats; + + Time txTime; + uint32_t tempProb; + + for (uint32_t i =0; i < GetNSupportedModes (); i++) + { + + /// calculate the perfect tx time for this rate + txTime = m_minstrelTable[i].perfectTxTime; + + /// just for initialization + if (txTime.GetMicroSeconds () == 0) + { + txTime = Seconds (1); + } + + NS_LOG_DEBUG ("m_txrate=" << m_txrate << "\t attempt=" << m_minstrelTable[i].numRateAttempt << "\t success=" << m_minstrelTable[i].numRateSuccess); + + /// if we've attempted something + if (m_minstrelTable[i].numRateAttempt) + { + /** + * calculate the probability of success + * assume probability scales from 0 to 18000 + */ + tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt; + + /// bookeeping + m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess; + m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt; + m_minstrelTable[i].prob = tempProb; + + /// ewma probability + tempProb = ((tempProb * (100 - m_stations->m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_stations->m_ewmaLevel) )/100; + + m_minstrelTable[i].ewmaProb = tempProb; + + /// calculating throughput + m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds()); + + } + + /// bookeeping + 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 ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800)) + { + /** + * retry count denotes the number of retries permitted for each rate + * # retry_count/2 + */ + m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1; + if (m_minstrelTable[i].adjustedRetryCount > 2) + { + m_minstrelTable[i].adjustedRetryCount = 2 ; + } + } + else + { + m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount; + } + + /// if it's 0 allow one retry limit + if (m_minstrelTable[i].adjustedRetryCount == 0) + { + m_minstrelTable[i].adjustedRetryCount = 1; + } + } + + + 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 < GetNSupportedModes (); i++) + { + NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput << "\n ewma" << m_minstrelTable[i].ewmaProb); + + if (max_tp < m_minstrelTable[i].throughput) + { + index_max_tp = i; + max_tp = m_minstrelTable[i].throughput; + } + + if (max_prob < m_minstrelTable[i].ewmaProb) + { + index_max_prob = i; + max_prob = m_minstrelTable[i].ewmaProb; + } + } + + + max_tp = 0; + /// find the second highest max + for (uint32_t i =0; i < GetNSupportedModes (); i++) + { + if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput)) + { + index_max_tp2 = i; + max_tp = m_minstrelTable[i].throughput; + } + } + + m_maxTpRate = index_max_tp; + m_maxTpRate2 = index_max_tp2; + m_maxProbRate = index_max_prob; + m_currentRate = index_max_tp; + + if (index_max_tp > m_txrate) + { + m_txrate= index_max_tp; + } + + NS_LOG_DEBUG ("max tp="<< index_max_tp << "\nmax tp2="<< index_max_tp2<< "\nmax prob="<< index_max_prob); + + /// reset it + RateInit (); +} + +void +MinstrelWifiRemoteStation::RateInit () +{ + NS_LOG_DEBUG ("RateInit="<GetCalcTxTime (GetSupportedMode (i)); + m_minstrelTable[i].retryCount =1; + m_minstrelTable[i].adjustedRetryCount =1; + } +} + +void +MinstrelWifiRemoteStation::InitSampleTable () +{ + NS_LOG_DEBUG ("InitSampleTable="<m_sampleCol; col++) + { + for (uint32_t i = 0; i < numSampleRates; i++ ) + { + + /** + * The next two lines basically tries to generate a random number + * between 0 and the number of available rates + */ + UniformVariable uv (0, numSampleRates); + newIndex = (i + (uint32_t)uv.GetValue ()) % numSampleRates; + + /// this loop is used for filling in other uninitilized places + while (m_sampleTable[newIndex][col] != 0) + { + newIndex = (newIndex + 1)%GetNSupportedModes (); + } + m_sampleTable[newIndex][col] = i+1; + + } + } +} + +void +MinstrelWifiRemoteStation::PrintSampleTable () +{ + NS_LOG_DEBUG ("PrintSampleTable="<m_sampleCol; j++) + { + std::cout << m_sampleTable[i][j] << "\t"; + } + std::cout << std::endl; + } +} + +void +MinstrelWifiRemoteStation::PrintTable () +{ + NS_LOG_DEBUG ("PrintTable="< + */ + + + +#ifndef MINSTREL_WIFI_MANAGER_H +#define MINSTREL_WIFI_MANAGER_H + +#include "wifi-remote-station-manager.h" +#include "wifi-mode.h" +#include "ns3/nstime.h" +#include + + + +/** + * \author Duy Nguyen + * \brief Implementation of Minstrel Rate Control Algorithm + * + * Porting Minstrel from Madwifi and Linux Kernel + * http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel + */ + + +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; + + +class MinstrelWifiManager : public WifiRemoteStationManager +{ + +public: + static TypeId GetTypeId (void); + MinstrelWifiManager (); + virtual ~MinstrelWifiManager(); + + virtual void SetupPhy (Ptr phy); + + /// for estimating the TxTime of a packet with a given mode + Time GetCalcTxTime (WifiMode mode) const; + void AddCalcTxTime (WifiMode mode, Time t); + +private: + friend class MinstrelWifiRemoteStation; + virtual class WifiRemoteStation *CreateStation (void); + + typedef std::vector > TxTime; + + 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) + double m_lookAroundRate; ///< the % to try other rates than our current rate + double m_ewmaLevel; ///< exponential weighted moving average + 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 + +}; + +class MinstrelWifiRemoteStation : public WifiRemoteStation +{ +public: + MinstrelWifiRemoteStation (Ptr stations); + + virtual ~MinstrelWifiRemoteStation (); + +protected: + + /** + * when packet is successfully received + * see wifi-remote-station-manager.h for more documentation + */ + virtual void DoReportRxOk (double rxSnr, WifiMode txMode); + + /// when RTS timeout expires + virtual void DoReportRtsFailed (void); + + + /** + * + * Retry Chain table is implemented here + * + * Try | LOOKAROUND RATE | NORMAL RATE + * | random < best | random > best | + * -------------------------------------------------------------- + * 1 | Best throughput | Random rate | Best throughput + * 2 | Random rate | Best throughput | Next best throughput + * 3 | Best probability | Best probability | Best probability + * 4 | Lowest Baserate | Lowest baserate | Lowest baserate + * + * Note: For clarity, multiple blocks of if's and else's are used + * After a failing 7 times, DoReportFinalDataFailed will be called + */ + virtual void DoReportDataFailed (void); + + /// when receive a CTS, associated with an RTS + virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr); + + /// when an ACK, associated with a data pkt, is received + virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr); + + /// after calling ReportRtsFailed if NeedRtsRetransmission returns false + virtual void DoReportFinalRtsFailed (void); + + /// after calling ReportDataFailed if NeedDataRetransmission returns false + virtual void DoReportFinalDataFailed (void); + + +private: + virtual Ptr GetManager (void) const; + + /** + * returns the transmission mode for sending this packet + * this function gets called when node is getting ready to send DATA + * see wifi-remote-station-manager.h for more documentation + */ + virtual WifiMode DoGetDataMode (uint32_t size); + + /// returns the transmission mode for sending RTS packet + virtual WifiMode DoGetRtsMode (void); + + /// update the number of retries and reset accordingly + void UpdateRetry (void); + + /// getting the next sample from Sample Table + uint32_t GetNextSample (void); + + /// find a rate to use from Minstrel Table + uint32_t FindRate (void); + + /// updating the Minstrel Table every 1/10 seconds + void UpdateStats (void); + + /// initialize Minstrel Table + void RateInit (void); + + /// initialize Sample Table + void InitSampleTable (void); + + /// printing Sample Table + void PrintSampleTable (void); + + /// printing Minstrel Table + void PrintTable (void); + + /** + * \param packet lenghth + * \param current WifiMode + * \returns calcuated transmit duration + */ + Time CalcRatePacket (uint32_t, WifiMode); + + void CheckInit(void); ///< check for initializations + + Ptr m_stations; + + 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 + * going row by row from 1st column until the 10th column(Minstrel defines 10) + * then we wrap back to the row 1 col 1. + * note: there are many other ways to do this. + */ + uint32_t m_col, m_index; + + uint32_t m_maxTpRate; ///< the current throughput rate + uint32_t m_maxTpRate2; ///< second highest throughput rate + uint32_t m_maxProbRate; ///< rate with highest prob of success + + int m_packetCount; ///< total number of packets as of now + int m_sampleCount; ///< how many packets we have sample so far + + bool m_isSampling; ///< a flag to indicate we are currently sampling + uint32_t m_sampleRate; ///< current sample rate + bool m_sampleRateSlower; ///< a flag to indicate sample rate is slower + uint32_t m_currentRate; ///< current rate we are using + + uint32_t m_shortRetry; ///< short retries such as control packts + uint32_t m_longRetry; ///< long retries such as data packets + uint32_t m_retry; ///< total retries short + long + uint32_t m_err; ///< retry errors + uint32_t m_txrate; ///< current transmit rate + + bool m_initialized; ///< for initializing tables + + +}; + +}// namespace ns3 + +#endif /* MINSTREL_WIFI_MANAGER_H */ diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index 82e0195d4..e265afaf6 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -63,6 +63,7 @@ def build(bld): 'msdu-aggregator.cc', 'amsdu-subframe-header.cc', 'msdu-standard-aggregator.cc', + 'minstrel-wifi-manager.cc', ] headers = bld.new_task_gen('ns3header') headers.module = 'wifi' @@ -113,6 +114,7 @@ def build(bld): 'dcf-manager.h', 'mac-rx-middle.h', 'mac-low.h', + 'minstrel-wifi-manager.h' ] if bld.env['ENABLE_GSL']: