src/devices/wifi/minstrel-wifi-manager.cc
author Duy Nguyen <duy@soe.ucsc.edu>
Thu Aug 13 08:45:47 2009 +0200 (2009-08-13)
changeset 4703 e1259e2fdaad
child 4725 4e068296f09f
permissions -rw-r--r--
add an implementation of the minstrel rate control algorithm
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2009 Duy Nguyen 
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Duy Nguyen <duy@soe.ucsc.edu>
    19  * 
    20  * Some Comments: 
    21  * 
    22  * 1) Segment Size is declared for completeness but not used  because it has 
    23  *    to do more with the requirement of the specific hardware.
    24  *
    25  * 2) By default, Minstrel applies the multi-rate retry(the core of Minstrel 
    26  *    algorithm). Otherwise, please use ConstantRateWifiManager instead.
    27  *
    28  * http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel
    29  */
    30 
    31 
    32 
    33 #include "minstrel-wifi-manager.h"
    34 #include "wifi-phy.h"
    35 #include "ns3/random-variable.h"
    36 #include "ns3/simulator.h"
    37 #include "ns3/log.h"
    38 #include "ns3/uinteger.h"
    39 #include "ns3/double.h"
    40 #include "ns3/wifi-mac.h"
    41 #include "ns3/assert.h"
    42 #include <vector>
    43 
    44 NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager");
    45 
    46 
    47 namespace ns3 {
    48 
    49 NS_OBJECT_ENSURE_REGISTERED (MinstrelWifiManager);
    50 
    51 TypeId
    52 MinstrelWifiManager::GetTypeId (void)
    53 {
    54   static TypeId tid = TypeId ("ns3::MinstrelWifiManager")
    55     .SetParent<WifiRemoteStationManager> ()
    56     .AddConstructor<MinstrelWifiManager> ()
    57     .AddAttribute ("UpdateStatistics",
    58                    "The interval between updating statistics table ",
    59                    TimeValue (Seconds (0.1)),
    60                    MakeTimeAccessor (&MinstrelWifiManager::m_updateStats),
    61                    MakeTimeChecker ())
    62     .AddAttribute ("LookAroundRate", 
    63                    "the percentage to try other rates",
    64                    DoubleValue (10),
    65                    MakeDoubleAccessor (&MinstrelWifiManager::m_lookAroundRate),
    66                    MakeDoubleChecker<double> ())
    67     .AddAttribute ("EWMA", 
    68                    "EWMA level",
    69                    DoubleValue (75),
    70                    MakeDoubleAccessor (&MinstrelWifiManager::m_ewmaLevel),
    71                    MakeDoubleChecker<double> ())
    72     .AddAttribute ("SegmentSize",
    73                    "The largest allowable segment size packet",
    74                    DoubleValue (6000),
    75                    MakeDoubleAccessor (&MinstrelWifiManager::m_segmentSize),
    76                    MakeDoubleChecker <double> ())
    77     .AddAttribute ("SampleColumn",
    78                    "The number of columns used for sampling",
    79                    DoubleValue (10),
    80                    MakeDoubleAccessor (&MinstrelWifiManager::m_sampleCol),
    81                    MakeDoubleChecker <double> ())
    82     .AddAttribute ("PacketLength",
    83                    "The packet length used for calculating mode TxTime",
    84                    DoubleValue (1200),
    85                    MakeDoubleAccessor (&MinstrelWifiManager::m_pktLen),
    86                    MakeDoubleChecker <double> ())
    87     ;
    88   return tid;
    89 }
    90 
    91 MinstrelWifiManager::MinstrelWifiManager ()
    92 {}
    93 
    94 MinstrelWifiManager::~MinstrelWifiManager ()
    95 {}
    96 
    97 void
    98 MinstrelWifiManager::SetupPhy (Ptr<WifiPhy> phy)
    99 {
   100   uint32_t nModes = phy->GetNModes ();
   101   for (uint32_t i = 0; i < nModes; i++)
   102     {
   103       WifiMode mode = phy->GetMode (i);
   104       AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, mode, WIFI_PREAMBLE_LONG));
   105     }
   106   WifiRemoteStationManager::SetupPhy (phy);
   107 }
   108 
   109 WifiRemoteStation *
   110 MinstrelWifiManager::CreateStation (void)
   111 {
   112   return new MinstrelWifiRemoteStation (this);
   113 }
   114 
   115 Time
   116 MinstrelWifiManager::GetCalcTxTime (WifiMode mode) const
   117 {
   118 
   119   for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
   120     {
   121       if (mode == i->second)
   122         {
   123           return i->first;
   124         }
   125     }
   126   NS_ASSERT (false);
   127   return Seconds (0);
   128 }
   129 
   130 void
   131 MinstrelWifiManager::AddCalcTxTime (WifiMode mode, Time t)
   132 {
   133   m_calcTxTime.push_back (std::make_pair (t, mode));
   134 }
   135 
   136 MinstrelWifiRemoteStation::MinstrelWifiRemoteStation (Ptr<MinstrelWifiManager> stations)
   137   :m_stations (stations),
   138   m_nextStatsUpdate (Simulator::Now () + stations->m_updateStats),
   139   m_col (0), 
   140   m_index (0), 
   141   m_maxTpRate (0), 
   142   m_maxTpRate2 (0), 
   143   m_maxProbRate (0),
   144   m_packetCount (0), 
   145   m_sampleCount (0), 
   146   m_isSampling (false), 
   147   m_sampleRate (0), 
   148   m_sampleRateSlower (false),
   149   m_currentRate (0),
   150   m_shortRetry (0),
   151   m_longRetry (0),
   152   m_retry (0),
   153   m_err (0),
   154   m_txrate (0),
   155   m_initialized (false)
   156 {}
   157 
   158 MinstrelWifiRemoteStation::~MinstrelWifiRemoteStation ()
   159 {}
   160 
   161 void 
   162 MinstrelWifiRemoteStation::CheckInit(void)
   163 {
   164   if (!m_initialized)
   165     {
   166       m_minstrelTable  =  MinstrelRate(GetNSupportedModes ());
   167       m_sampleTable = SampleRate(GetNSupportedModes (), std::vector<uint32_t> (m_stations->m_sampleCol));
   168       InitSampleTable ();
   169       RateInit ();
   170       m_initialized = true;
   171     }
   172 }
   173 
   174 void
   175 MinstrelWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
   176 {
   177   NS_LOG_DEBUG("DoReportRxOk m_txrate=" << m_txrate);
   178 }
   179 
   180 void
   181 MinstrelWifiRemoteStation::DoReportRtsFailed (void)
   182 {
   183   NS_LOG_DEBUG("DoReportRtsFailed m_txrate=" << m_txrate);
   184 
   185   m_shortRetry++;
   186 }
   187 
   188 void
   189 MinstrelWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
   190 {
   191   NS_LOG_DEBUG ("self="<<this<<" rts ok");
   192 }
   193 
   194 void
   195 MinstrelWifiRemoteStation::DoReportFinalRtsFailed (void)
   196 {
   197   UpdateRetry ();
   198   m_err++;
   199 }
   200 
   201 void
   202 MinstrelWifiRemoteStation::DoReportDataFailed (void)
   203 {
   204   CheckInit();
   205 
   206   m_longRetry++;
   207 
   208   NS_LOG_DEBUG ("DoReportDataFailed " << this << "\t rate " << m_txrate << "\tlongRetry \t" << m_longRetry);
   209 
   210   /// for normal rate, we're not currently sampling random rates
   211   if (!m_isSampling)
   212     {
   213       /// use best throughput rate
   214       if( m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
   215         {
   216           ;  ///<  there's still a few retries left
   217         }
   218 
   219       /// use second best throughput rate
   220       else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
   221                m_minstrelTable[m_maxTpRate].adjustedRetryCount))
   222         {
   223           m_txrate = m_maxTpRate2;
   224         }
   225 
   226       /// use best probability rate
   227       else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
   228                m_minstrelTable[m_maxTpRate2].adjustedRetryCount + 
   229                m_minstrelTable[m_maxTpRate].adjustedRetryCount))
   230         {
   231           m_txrate = m_maxProbRate;
   232         }
   233 
   234       /// use lowest base rate	
   235       else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +  
   236                m_minstrelTable[m_maxTpRate2].adjustedRetryCount + 
   237                m_minstrelTable[m_maxTpRate].adjustedRetryCount))
   238         {
   239           m_txrate = 0;
   240         }
   241     }
   242 
   243   /// for look-around rate, we're currently sampling random rates
   244   else
   245     {
   246       /// current sampling rate is slower than the current best rate
   247       if (m_sampleRateSlower)
   248         {
   249           /// use best throughput rate
   250           if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
   251             {
   252               ;	///<  there are a few retries left
   253             }
   254 
   255           ///	use random rate
   256           else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount + 
   257                    m_minstrelTable[m_maxTpRate].adjustedRetryCount))
   258             {
   259               m_txrate = m_sampleRate;
   260             }
   261 
   262           /// use max probability rate
   263           else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
   264                    m_minstrelTable[m_sampleRate].adjustedRetryCount + 
   265                    m_minstrelTable[m_maxTpRate].adjustedRetryCount ))
   266             {
   267               m_txrate = m_maxProbRate;
   268             }
   269 
   270           /// use lowest base rate
   271           else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +  
   272                    m_minstrelTable[m_sampleRate].adjustedRetryCount + 
   273                    m_minstrelTable[m_maxTpRate].adjustedRetryCount)) 
   274             {
   275               m_txrate = 0;
   276             }
   277         }
   278 
   279         /// current sampling rate is better than current best rate 
   280         else
   281           {
   282             /// use random rate
   283             if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
   284               {
   285                 ;  ///< keep using it
   286               }
   287 
   288             /// use the best rate
   289             else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + 
   290                      m_minstrelTable[m_sampleRate].adjustedRetryCount)
   291               {
   292                 m_txrate = m_maxTpRate;
   293               }
   294 
   295             /// use the best probability rate
   296             else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + 
   297                      m_minstrelTable[m_maxTpRate].adjustedRetryCount +  
   298                      m_minstrelTable[m_sampleRate].adjustedRetryCount)
   299               {
   300                 m_txrate = m_maxProbRate;
   301               }
   302 
   303             /// use the lowest base rate
   304             else if (m_longRetry > m_minstrelTable[m_txrate].adjustedRetryCount + 
   305                      m_minstrelTable[m_maxTpRate].adjustedRetryCount +  
   306                      m_minstrelTable[m_sampleRate].adjustedRetryCount) 
   307               {
   308                 m_txrate = 0;
   309               }
   310           }
   311     }
   312 }
   313 
   314 void
   315 MinstrelWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
   316 {
   317   m_isSampling = false;
   318   m_sampleRateSlower=false;
   319 
   320   CheckInit ();
   321 
   322   m_minstrelTable[m_txrate].numRateSuccess++;
   323   m_minstrelTable[m_txrate].numRateAttempt++;
   324 	
   325   UpdateRetry ();
   326 
   327   m_minstrelTable[m_txrate].numRateAttempt += m_retry;
   328   m_packetCount++;
   329 
   330   if (GetNSupportedModes () >= 1)
   331     {
   332       m_txrate = FindRate ();
   333     }
   334 }
   335 
   336 void
   337 MinstrelWifiRemoteStation::DoReportFinalDataFailed (void)
   338 {
   339   NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << m_txrate);
   340 
   341   m_isSampling = false;
   342   m_sampleRateSlower=false;
   343 
   344   UpdateRetry ();
   345 
   346   m_minstrelTable[m_txrate].numRateAttempt += m_retry;
   347   m_err++;
   348 
   349   if (GetNSupportedModes () >= 1)
   350     {
   351       m_txrate = FindRate ();
   352     }
   353 }
   354 
   355 void
   356 MinstrelWifiRemoteStation::UpdateRetry (void)
   357 {
   358   m_retry = m_shortRetry + m_longRetry;
   359   m_shortRetry = 0;
   360   m_longRetry = 0;
   361 }
   362 
   363 Ptr<WifiRemoteStationManager>
   364 MinstrelWifiRemoteStation::GetManager (void) const
   365 {
   366   return m_stations;
   367 }
   368 
   369 WifiMode
   370 MinstrelWifiRemoteStation::DoGetDataMode (uint32_t size)
   371 {
   372   UpdateStats ();
   373   if (!m_initialized)
   374     {
   375       CheckInit ();
   376 
   377       /// start the rate at half way
   378       m_txrate = GetNSupportedModes () / 2;
   379     }
   380   return GetSupportedMode (m_txrate);
   381 }
   382 
   383 WifiMode
   384 MinstrelWifiRemoteStation::DoGetRtsMode (void)
   385 {
   386   NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << m_txrate);
   387 
   388   UpdateStats ();
   389   return GetSupportedMode (0);
   390 }
   391 
   392 uint32_t 
   393 MinstrelWifiRemoteStation::GetNextSample ()
   394 {
   395   uint32_t bitrate;
   396   bitrate = m_sampleTable[m_index][m_col];
   397   m_index++;
   398 
   399   /// bookeeping for m_index and m_col variables
   400   if (m_index > (GetNSupportedModes () -2)) 
   401     {
   402       m_index =0;
   403       m_col++;
   404       if (m_col >= m_stations->m_sampleCol)
   405         {
   406           m_col = 0;
   407         }
   408     }
   409   return bitrate;
   410 }
   411 
   412 uint32_t
   413 MinstrelWifiRemoteStation::FindRate ()
   414 {
   415   NS_LOG_DEBUG ("FindRate " << "packet=" << m_packetCount );
   416 
   417   if ((m_sampleCount + m_packetCount) == 0)
   418     {
   419       return 0;
   420     }
   421 
   422 
   423   uint32_t idx;
   424 
   425   /// for determining when to try a sample rate 
   426   UniformVariable coinFlip (0, 100);
   427 
   428   /**
   429    * if we are below the target of look around rate percentage, look around
   430    * note: do it randomly by flipping a coin instead sampling 
   431    * all at once until it reaches the look around rate
   432    */
   433   if ( (((100* m_sampleCount) / (m_sampleCount + m_packetCount )) < m_stations->m_lookAroundRate) &&
   434      ((int)coinFlip.GetValue ()) % 2 == 1 )
   435     {
   436 
   437       /// now go through the table and find an index rate
   438       idx = GetNextSample	();
   439 			
   440 			
   441       /**
   442        * This if condition is used to make sure that we don't need to use
   443        * the sample rate it is the same as our current rate
   444        */
   445       if (idx != m_maxTpRate && idx != m_txrate) 
   446         {
   447 		
   448           /// start sample count
   449           m_sampleCount++;
   450 
   451           /// set flag that we are currently sampling
   452           m_isSampling = true;
   453 
   454           /// bookeeping for resetting stuff
   455           if (m_packetCount >= 10000) 
   456             {
   457               m_sampleCount = 0;
   458               m_packetCount = 0;
   459             }
   460 
   461           /// error check
   462           if (idx >= GetNSupportedModes	() || idx < 0 )
   463             {
   464               NS_LOG_DEBUG ("ALERT!!! ERROR");
   465             }
   466 
   467           /// set the rate that we're currently sampling
   468           m_sampleRate = idx;
   469 
   470           if (m_sampleRate == m_maxTpRate)
   471             {
   472               m_sampleRate = m_maxTpRate2;
   473             }
   474 
   475           /// is this rate slower than the current best rate
   476           m_sampleRateSlower = (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[m_maxTpRate].perfectTxTime);
   477 
   478           /// using the best rate instead
   479           if (m_sampleRateSlower)
   480             {
   481               idx =  m_maxTpRate;
   482             }
   483         }
   484 			
   485     } 
   486 
   487   ///	continue using the best rate
   488   else
   489     {
   490       idx = m_maxTpRate; 
   491     }
   492 
   493 
   494   NS_LOG_DEBUG ("FindRate " << "sample rate=" << idx);
   495 
   496   return idx;
   497 }
   498 
   499 void
   500 MinstrelWifiRemoteStation::UpdateStats ()
   501 {
   502   if (Simulator::Now () <  m_nextStatsUpdate)
   503     {
   504       return;
   505     }
   506 
   507   NS_LOG_DEBUG ("Updating stats="<<this);
   508 
   509   m_nextStatsUpdate = Simulator::Now () + m_stations->m_updateStats;
   510 
   511   Time txTime;
   512   uint32_t tempProb;
   513 
   514   for (uint32_t i =0; i < GetNSupportedModes (); i++)
   515     {        
   516 
   517       /// calculate the perfect tx time for this rate
   518       txTime = m_minstrelTable[i].perfectTxTime;       
   519 
   520       /// just for initialization
   521       if (txTime.GetMicroSeconds () == 0)
   522         {
   523           txTime = Seconds (1);
   524         }
   525 
   526       NS_LOG_DEBUG ("m_txrate=" << m_txrate << "\t attempt=" << m_minstrelTable[i].numRateAttempt << "\t success=" << m_minstrelTable[i].numRateSuccess);
   527 
   528       /// if we've attempted something
   529       if (m_minstrelTable[i].numRateAttempt)
   530         {
   531           /**
   532            * calculate the probability of success
   533            * assume probability scales from 0 to 18000
   534            */
   535           tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt;
   536 
   537           /// bookeeping
   538           m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess;
   539           m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt;
   540           m_minstrelTable[i].prob = tempProb;
   541 
   542           /// ewma probability
   543           tempProb = ((tempProb * (100 - m_stations->m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_stations->m_ewmaLevel) )/100;
   544 
   545           m_minstrelTable[i].ewmaProb = tempProb;
   546 
   547           /// calculating throughput
   548           m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds());
   549 
   550         }
   551 
   552       /// bookeeping
   553       m_minstrelTable[i].prevNumRateAttempt= m_minstrelTable[i].numRateAttempt;
   554       m_minstrelTable[i].prevNumRateSuccess = m_minstrelTable[i].numRateSuccess;
   555       m_minstrelTable[i].numRateSuccess = 0;
   556       m_minstrelTable[i].numRateAttempt = 0;
   557 
   558       /// Sample less often below 10% and  above 95% of success
   559       if ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800)) 
   560         {
   561           /**
   562            * retry count denotes the number of retries permitted for each rate
   563            * # retry_count/2
   564            */
   565           m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1;
   566           if (m_minstrelTable[i].adjustedRetryCount > 2)
   567             {
   568               m_minstrelTable[i].adjustedRetryCount = 2 ;
   569             }
   570         }
   571       else
   572         {
   573           m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount;
   574         }
   575 
   576       /// if it's 0 allow one retry limit
   577       if (m_minstrelTable[i].adjustedRetryCount == 0)
   578         {
   579           m_minstrelTable[i].adjustedRetryCount = 1;
   580         }
   581     }
   582 
   583 
   584   uint32_t max_prob = 0, index_max_prob =0, max_tp =0, index_max_tp=0, index_max_tp2=0;
   585 
   586   /// go find max throughput, second maximum throughput, high probability succ
   587   for (uint32_t i =0; i < GetNSupportedModes (); i++) 
   588     {
   589       NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput << "\n ewma" << m_minstrelTable[i].ewmaProb);
   590 
   591       if (max_tp < m_minstrelTable[i].throughput) 
   592         {
   593           index_max_tp = i;
   594           max_tp = m_minstrelTable[i].throughput;
   595         }
   596 
   597       if (max_prob < m_minstrelTable[i].ewmaProb) 
   598         {
   599           index_max_prob = i;
   600           max_prob = m_minstrelTable[i].ewmaProb;
   601         }
   602     }
   603 
   604 
   605   max_tp = 0;
   606   /// find the second highest max
   607   for (uint32_t i =0; i < GetNSupportedModes (); i++) 
   608     {
   609       if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput))
   610         {
   611           index_max_tp2 = i;
   612           max_tp = m_minstrelTable[i].throughput;
   613         }
   614     }
   615 
   616   m_maxTpRate = index_max_tp;
   617   m_maxTpRate2 = index_max_tp2;
   618   m_maxProbRate = index_max_prob;
   619   m_currentRate = index_max_tp;
   620 
   621   if (index_max_tp > m_txrate)
   622     {
   623       m_txrate= index_max_tp;
   624     }
   625 
   626   NS_LOG_DEBUG ("max tp="<< index_max_tp << "\nmax tp2="<< index_max_tp2<< "\nmax prob="<< index_max_prob);
   627 
   628   /// reset it
   629   RateInit ();
   630 }
   631 
   632 void
   633 MinstrelWifiRemoteStation::RateInit ()
   634 {
   635   NS_LOG_DEBUG ("RateInit="<<this);
   636 
   637   for (uint32_t i = 0; i < GetNSupportedModes (); i++)
   638     {
   639       m_minstrelTable[i].numRateAttempt = 0;
   640       m_minstrelTable[i].numRateSuccess = 0;
   641       m_minstrelTable[i].prob = 0;
   642       m_minstrelTable[i].ewmaProb = 0;
   643       m_minstrelTable[i].prevNumRateAttempt = 0;
   644       m_minstrelTable[i].prevNumRateSuccess = 0;
   645       m_minstrelTable[i].successHist = 0;
   646       m_minstrelTable[i].attemptHist = 0;
   647       m_minstrelTable[i].throughput = 0;
   648       m_minstrelTable[i].perfectTxTime = m_stations->GetCalcTxTime (GetSupportedMode (i));
   649       m_minstrelTable[i].retryCount =1;
   650       m_minstrelTable[i].adjustedRetryCount =1;
   651     }
   652 }
   653 
   654 void
   655 MinstrelWifiRemoteStation::InitSampleTable ()
   656 {
   657   NS_LOG_DEBUG ("InitSampleTable="<<this);
   658 	
   659   m_col = m_index = 0;
   660 
   661   /// for off-seting to make rates fall between 0 and numrates 
   662   uint32_t numSampleRates= GetNSupportedModes () - 1;
   663 
   664   uint32_t newIndex;
   665   for (uint32_t col = 0; col < m_stations->m_sampleCol; col++)
   666     {
   667       for (uint32_t i = 0; i < numSampleRates; i++ )
   668         {
   669 
   670           /**
   671            * The next two lines basically tries to generate a random number
   672            * between 0 and the number of available rates 
   673            */
   674           UniformVariable uv (0, numSampleRates);
   675           newIndex = (i + (uint32_t)uv.GetValue	()) % numSampleRates;	
   676 
   677           /// this loop is used for filling in other uninitilized places
   678           while	(m_sampleTable[newIndex][col] != 0)
   679             {
   680               newIndex = (newIndex + 1)%GetNSupportedModes ();
   681             }
   682           m_sampleTable[newIndex][col] = i+1;
   683 
   684         }
   685     }
   686 }
   687 
   688 void
   689 MinstrelWifiRemoteStation::PrintSampleTable ()
   690 {
   691   NS_LOG_DEBUG ("PrintSampleTable="<<this );
   692 
   693   uint32_t numSampleRates= GetNSupportedModes ();
   694   for (uint32_t i=0; i < numSampleRates; i++)
   695     {
   696       for (uint32_t j=0; j < m_stations->m_sampleCol; j++)
   697         {
   698           std::cout << m_sampleTable[i][j] << "\t";
   699         }
   700       std::cout << std::endl;
   701     }
   702 }
   703 	
   704 void
   705 MinstrelWifiRemoteStation::PrintTable ()
   706 {
   707   NS_LOG_DEBUG ("PrintTable="<<this);
   708 
   709   for (uint32_t i=0; i < GetNSupportedModes (); i++)
   710     {
   711       std::cout << "index(" << i << ") = " << m_minstrelTable[i].perfectTxTime<< "\n";
   712     }
   713 }
   714 
   715 } //namespace ns3
   716 
   717 
   718 
   719 
   720