A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
minstrel-wifi-manager.cc
Go to the documentation of this file.
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 #include "minstrel-wifi-manager.h"
32 #include "wifi-phy.h"
33 #include "ns3/simulator.h"
34 #include "ns3/log.h"
35 #include "ns3/uinteger.h"
36 #include "ns3/double.h"
37 #include "ns3/wifi-mac.h"
38 #include "ns3/assert.h"
39 #include <vector>
40 
41 #define Min(a,b) ((a < b) ? a : b)
42 
43 NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager");
44 
45 
46 namespace ns3 {
47 
48 
50 {
52 
59  uint32_t m_col, m_index;
60  uint32_t m_maxTpRate;
61  uint32_t m_maxTpRate2;
62  uint32_t m_maxProbRate;
63 
66 
67  bool m_isSampling;
68  uint32_t m_sampleRate;
70  uint32_t m_currentRate;
71 
72  uint32_t m_shortRetry;
73  uint32_t m_longRetry;
74  uint32_t m_retry;
75  uint32_t m_err;
76  uint32_t m_txrate;
77 
79 };
80 
82 
83 TypeId
85 {
86  static TypeId tid = TypeId ("ns3::MinstrelWifiManager")
88  .AddConstructor<MinstrelWifiManager> ()
89  .AddAttribute ("UpdateStatistics",
90  "The interval between updating statistics table ",
91  TimeValue (Seconds (0.1)),
92  MakeTimeAccessor (&MinstrelWifiManager::m_updateStats),
93  MakeTimeChecker ())
94  .AddAttribute ("LookAroundRate",
95  "the percentage to try other rates",
96  DoubleValue (10),
97  MakeDoubleAccessor (&MinstrelWifiManager::m_lookAroundRate),
98  MakeDoubleChecker<double> ())
99  .AddAttribute ("EWMA",
100  "EWMA level",
101  DoubleValue (75),
102  MakeDoubleAccessor (&MinstrelWifiManager::m_ewmaLevel),
103  MakeDoubleChecker<double> ())
104  .AddAttribute ("SegmentSize",
105  "The largest allowable segment size packet",
106  DoubleValue (6000),
107  MakeDoubleAccessor (&MinstrelWifiManager::m_segmentSize),
108  MakeDoubleChecker <double> ())
109  .AddAttribute ("SampleColumn",
110  "The number of columns used for sampling",
111  DoubleValue (10),
112  MakeDoubleAccessor (&MinstrelWifiManager::m_sampleCol),
113  MakeDoubleChecker <double> ())
114  .AddAttribute ("PacketLength",
115  "The packet length used for calculating mode TxTime",
116  DoubleValue (1200),
117  MakeDoubleAccessor (&MinstrelWifiManager::m_pktLen),
118  MakeDoubleChecker <double> ())
119  ;
120  return tid;
121 }
122 
124 {
125  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
126 
127  m_nsupported = 0;
128 }
129 
131 {
132 }
133 
134 void
136 {
137  uint32_t nModes = phy->GetNModes ();
138  for (uint32_t i = 0; i < nModes; i++)
139  {
140  WifiMode mode = phy->GetMode (i);
141  WifiTxVector txVector;
142  txVector.SetMode(mode);
144  }
146 }
147 
148 int64_t
150 {
151  NS_LOG_FUNCTION (this << stream);
153  return 1;
154 }
155 
156 Time
158 {
159 
160  for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
161  {
162  if (mode == i->second)
163  {
164  return i->first;
165  }
166  }
167  NS_ASSERT (false);
168  return Seconds (0);
169 }
170 
171 void
173 {
174  m_calcTxTime.push_back (std::make_pair (t, mode));
175 }
176 
179 {
181 
183  station->m_col = 0;
184  station->m_index = 0;
185  station->m_maxTpRate = 0;
186  station->m_maxTpRate2 = 0;
187  station->m_maxProbRate = 0;
188  station->m_packetCount = 0;
189  station->m_sampleCount = 0;
190  station->m_isSampling = false;
191  station->m_sampleRate = 0;
192  station->m_sampleRateSlower = false;
193  station->m_currentRate = 0;
194  station->m_shortRetry = 0;
195  station->m_longRetry = 0;
196  station->m_retry = 0;
197  station->m_err = 0;
198  station->m_txrate = 0;
199  station->m_initialized = false;
200 
201  return station;
202 }
203 
204 void
206 {
207  if (!station->m_initialized && GetNSupported (station) > 1)
208  {
209  // Note: we appear to be doing late initialization of the table
210  // to make sure that the set of supported rates has been initialized
211  // before we perform our own initialization.
212  m_nsupported = GetNSupported (station);
214  m_sampleTable = SampleRate (m_nsupported, std::vector<uint32_t> (m_sampleCol));
215  InitSampleTable (station);
216  RateInit (station);
217  station->m_initialized = true;
218  }
219 }
220 
221 void
223  double rxSnr, WifiMode txMode)
224 {
225  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelWifiRemoteStation *)st)->m_txrate);
226 }
227 
228 void
230 {
232  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
233 
234  station->m_shortRetry++;
235 }
236 
237 void
238 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
239 {
240  NS_LOG_DEBUG ("self=" << st << " rts ok");
241 }
242 
243 void
245 {
247  UpdateRetry (station);
248  station->m_err++;
249 }
250 
251 void
253 {
271  CheckInit (station);
272  if (!station->m_initialized)
273  {
274  return;
275  }
276 
277  station->m_longRetry++;
278 
279  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
280 
282  if (!station->m_isSampling)
283  {
285  if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount)
286  {
287  ;
288  }
289 
291  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
292  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
293  {
294  station->m_txrate = station->m_maxTpRate2;
295  }
296 
298  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
299  m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
300  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
301  {
302  station->m_txrate = station->m_maxProbRate;
303  }
304 
306  else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount +
307  m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
308  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
309  {
310  station->m_txrate = 0;
311  }
312  }
313 
315  else
316  {
318  if (station->m_sampleRateSlower)
319  {
321  if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount)
322  {
323  ;
324  }
325 
327  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
328  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
329  {
330  station->m_txrate = station->m_sampleRate;
331  }
332 
334  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
335  m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
336  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount ))
337  {
338  station->m_txrate = station->m_maxProbRate;
339  }
340 
342  else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount +
343  m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
344  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
345  {
346  station->m_txrate = 0;
347  }
348  }
349 
351  else
352  {
354  if (station->m_longRetry < m_minstrelTable[station->m_txrate].adjustedRetryCount)
355  {
356  ;
357  }
358 
360  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
361  m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
362  {
363  station->m_txrate = station->m_maxTpRate;
364  }
365 
367  else if (station->m_longRetry <= (m_minstrelTable[station->m_txrate].adjustedRetryCount +
368  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
369  m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
370  {
371  station->m_txrate = station->m_maxProbRate;
372  }
373 
375  else if (station->m_longRetry > (m_minstrelTable[station->m_txrate].adjustedRetryCount +
376  m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
377  m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
378  {
379  station->m_txrate = 0;
380  }
381  }
382  }
383 }
384 
385 void
387  double ackSnr, WifiMode ackMode, double dataSnr)
388 {
390 
391  station->m_isSampling = false;
392  station->m_sampleRateSlower = false;
393 
394  CheckInit (station);
395  if (!station->m_initialized)
396  {
397  return;
398  }
399 
400  m_minstrelTable[station->m_txrate].numRateSuccess++;
401  m_minstrelTable[station->m_txrate].numRateAttempt++;
402 
403  UpdateRetry (station);
404 
405  m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry;
406  station->m_packetCount++;
407 
408  if (m_nsupported >= 1)
409  {
410  station->m_txrate = FindRate (station);
411  }
412 }
413 
414 void
416 {
418  NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << station->m_txrate);
419 
420  station->m_isSampling = false;
421  station->m_sampleRateSlower = false;
422 
423  UpdateRetry (station);
424 
425  m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry;
426  station->m_err++;
427 
428  if (m_nsupported >= 1)
429  {
430  station->m_txrate = FindRate (station);
431  }
432 }
433 
434 void
436 {
437  station->m_retry = station->m_shortRetry + station->m_longRetry;
438  station->m_shortRetry = 0;
439  station->m_longRetry = 0;
440 }
441 
444  uint32_t size)
445 {
447  if (!station->m_initialized)
448  {
449  CheckInit (station);
450 
452  station->m_txrate = m_nsupported / 2;
453  }
454  UpdateStats (station);
456 }
457 
460 {
462  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
463 
465 }
466 
467 bool
469 {
470  return true;
471 }
472 uint32_t
474 {
475  uint32_t bitrate;
476  bitrate = m_sampleTable[station->m_index][station->m_col];
477  station->m_index++;
478 
480  if (station->m_index > (m_nsupported - 2))
481  {
482  station->m_index = 0;
483  station->m_col++;
484  if (station->m_col >= m_sampleCol)
485  {
486  station->m_col = 0;
487  }
488  }
489  return bitrate;
490 }
491 
492 uint32_t
494 {
495  NS_LOG_DEBUG ("FindRate " << "packet=" << station->m_packetCount );
496 
497  if ((station->m_sampleCount + station->m_packetCount) == 0)
498  {
499  return 0;
500  }
501 
502 
503  uint32_t idx;
504 
506  int coinFlip = m_uniformRandomVariable->GetInteger (0, 100) % 2;
507 
513  if ( (((100 * station->m_sampleCount) / (station->m_sampleCount + station->m_packetCount )) < m_lookAroundRate)
514  && (coinFlip == 1) )
515  {
516 
518  idx = GetNextSample (station);
519 
520 
525  if (idx != station->m_maxTpRate && idx != station->m_txrate)
526  {
527 
529  station->m_sampleCount++;
530 
532  station->m_isSampling = true;
533 
535  if (station->m_packetCount >= 10000)
536  {
537  station->m_sampleCount = 0;
538  station->m_packetCount = 0;
539  }
540 
542  if (idx >= m_nsupported)
543  {
544  NS_LOG_DEBUG ("ALERT!!! ERROR");
545  }
546 
548  station->m_sampleRate = idx;
549 
550  if (station->m_sampleRate == station->m_maxTpRate)
551  {
552  station->m_sampleRate = station->m_maxTpRate2;
553  }
554 
556  station->m_sampleRateSlower =
557  (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[station->m_maxTpRate].perfectTxTime);
558 
560  if (station->m_sampleRateSlower)
561  {
562  idx = station->m_maxTpRate;
563  }
564  }
565 
566  }
567 
569  else
570  {
571  idx = station->m_maxTpRate;
572  }
573 
574 
575  NS_LOG_DEBUG ("FindRate " << "sample rate=" << idx);
576 
577  return idx;
578 }
579 
580 void
582 {
583  if (Simulator::Now () < station->m_nextStatsUpdate)
584  {
585  return;
586  }
587 
588  if (!station->m_initialized)
589  {
590  return;
591  }
592  NS_LOG_DEBUG ("Updating stats=" << this);
593 
595 
596  Time txTime;
597  uint32_t tempProb;
598 
599  for (uint32_t i = 0; i < m_nsupported; i++)
600  {
601 
603  txTime = m_minstrelTable[i].perfectTxTime;
604 
606  if (txTime.GetMicroSeconds () == 0)
607  {
608  txTime = Seconds (1);
609  }
610 
611  NS_LOG_DEBUG ("m_txrate=" << station->m_txrate <<
612  "\t attempt=" << m_minstrelTable[i].numRateAttempt <<
613  "\t success=" << m_minstrelTable[i].numRateSuccess);
614 
616  if (m_minstrelTable[i].numRateAttempt)
617  {
622  tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt;
623 
625  m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess;
626  m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt;
627  m_minstrelTable[i].prob = tempProb;
628 
630  tempProb = static_cast<uint32_t> (((tempProb * (100 - m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100);
631 
632  m_minstrelTable[i].ewmaProb = tempProb;
633 
635  m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds ());
636 
637  }
638 
640  m_minstrelTable[i].prevNumRateAttempt = m_minstrelTable[i].numRateAttempt;
641  m_minstrelTable[i].prevNumRateSuccess = m_minstrelTable[i].numRateSuccess;
642  m_minstrelTable[i].numRateSuccess = 0;
643  m_minstrelTable[i].numRateAttempt = 0;
644 
646  if ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800))
647  {
652  m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1;
653  if (m_minstrelTable[i].adjustedRetryCount > 2)
654  {
655  m_minstrelTable[i].adjustedRetryCount = 2;
656  }
657  }
658  else
659  {
660  m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount;
661  }
662 
664  if (m_minstrelTable[i].adjustedRetryCount == 0)
665  {
666  m_minstrelTable[i].adjustedRetryCount = 1;
667  }
668  }
669 
670 
671  uint32_t max_prob = 0, index_max_prob = 0, max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
672 
674  for (uint32_t i = 0; i < m_nsupported; i++)
675  {
676  NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput <<
677  "\n ewma" << m_minstrelTable[i].ewmaProb);
678 
679  if (max_tp < m_minstrelTable[i].throughput)
680  {
681  index_max_tp = i;
682  max_tp = m_minstrelTable[i].throughput;
683  }
684 
685  if (max_prob < m_minstrelTable[i].ewmaProb)
686  {
687  index_max_prob = i;
688  max_prob = m_minstrelTable[i].ewmaProb;
689  }
690  }
691 
692 
693  max_tp = 0;
695  for (uint32_t i = 0; i < m_nsupported; i++)
696  {
697  if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput))
698  {
699  index_max_tp2 = i;
700  max_tp = m_minstrelTable[i].throughput;
701  }
702  }
703 
704  station->m_maxTpRate = index_max_tp;
705  station->m_maxTpRate2 = index_max_tp2;
706  station->m_maxProbRate = index_max_prob;
707  station->m_currentRate = index_max_tp;
708 
709  if (index_max_tp > station->m_txrate)
710  {
711  station->m_txrate = index_max_tp;
712  }
713 
714  NS_LOG_DEBUG ("max tp=" << index_max_tp << "\nmax tp2=" << index_max_tp2 << "\nmax prob=" << index_max_prob);
715 
717  RateInit (station);
718 }
719 
720 void
722 {
723  NS_LOG_DEBUG ("RateInit=" << station);
724 
725  for (uint32_t i = 0; i < m_nsupported; i++)
726  {
727  m_minstrelTable[i].numRateAttempt = 0;
728  m_minstrelTable[i].numRateSuccess = 0;
729  m_minstrelTable[i].prob = 0;
730  m_minstrelTable[i].ewmaProb = 0;
731  m_minstrelTable[i].prevNumRateAttempt = 0;
732  m_minstrelTable[i].prevNumRateSuccess = 0;
733  m_minstrelTable[i].successHist = 0;
734  m_minstrelTable[i].attemptHist = 0;
735  m_minstrelTable[i].throughput = 0;
736  m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
737  m_minstrelTable[i].retryCount = 1;
738  m_minstrelTable[i].adjustedRetryCount = 1;
739  }
740 }
741 
742 void
744 {
745  NS_LOG_DEBUG ("InitSampleTable=" << this);
746 
747  station->m_col = station->m_index = 0;
748 
750  uint32_t numSampleRates = m_nsupported;
751 
752  uint32_t newIndex;
753  for (uint32_t col = 0; col < m_sampleCol; col++)
754  {
755  for (uint32_t i = 0; i < numSampleRates; i++ )
756  {
757 
762  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
763  newIndex = (i + uv) % numSampleRates;
764 
766  while (m_sampleTable[newIndex][col] != 0)
767  {
768  newIndex = (newIndex + 1) % m_nsupported;
769  }
770  m_sampleTable[newIndex][col] = i;
771 
772  }
773  }
774 }
775 
776 void
778 {
779  NS_LOG_DEBUG ("PrintSampleTable=" << station);
780 
781  uint32_t numSampleRates = m_nsupported;
782  for (uint32_t i = 0; i < numSampleRates; i++)
783  {
784  for (uint32_t j = 0; j < m_sampleCol; j++)
785  {
786  std::cout << m_sampleTable[i][j] << "\t";
787  }
788  std::cout << std::endl;
789  }
790 }
791 
792 void
794 {
795  NS_LOG_DEBUG ("PrintTable=" << station);
796 
797  for (uint32_t i = 0; i < m_nsupported; i++)
798  {
799  std::cout << "index(" << i << ") = " << m_minstrelTable[i].perfectTxTime << "\n";
800  }
801 }
802 
803 } // namespace ns3
804 
805 
806 
807 
808