A Discrete-Event Network Simulator
API
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 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager");
46 
54 {
56 
63  uint32_t m_col, m_index;
64  uint32_t m_maxTpRate;
65  uint32_t m_maxTpRate2;
66  uint32_t m_maxProbRate;
67 
70 
71  bool m_isSampling;
72  uint32_t m_sampleRate;
74 
75  uint32_t m_shortRetry;
76  uint32_t m_longRetry;
77  uint32_t m_retry;
78  uint32_t m_err;
79  uint32_t m_txrate;
80 
82 
85 };
86 
88 
89 TypeId
91 {
92  static TypeId tid = TypeId ("ns3::MinstrelWifiManager")
94  .SetGroupName ("Wifi")
95  .AddConstructor<MinstrelWifiManager> ()
96  .AddAttribute ("UpdateStatistics",
97  "The interval between updating statistics table ",
98  TimeValue (Seconds (0.1)),
100  MakeTimeChecker ())
101  .AddAttribute ("LookAroundRate",
102  "the percentage to try other rates",
103  DoubleValue (10),
105  MakeDoubleChecker<double> ())
106  .AddAttribute ("EWMA",
107  "EWMA level",
108  DoubleValue (75),
110  MakeDoubleChecker<double> ())
111  .AddAttribute ("SampleColumn",
112  "The number of columns used for sampling",
113  DoubleValue (10),
115  MakeDoubleChecker <double> ())
116  .AddAttribute ("PacketLength",
117  "The packet length used for calculating mode TxTime",
118  DoubleValue (1200),
120  MakeDoubleChecker <double> ())
121  ;
122  return tid;
123 }
124 
126 {
127  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
128 
129  m_nsupported = 0;
130 }
131 
133 {
134 }
135 
136 void
138 {
139  NS_LOG_FUNCTION(this << phy);
140  uint32_t nModes = phy->GetNModes ();
141  for (uint32_t i = 0; i < nModes; i++)
142  {
143  WifiMode mode = phy->GetMode (i);
144  WifiTxVector txVector;
145  txVector.SetMode(mode);
146  AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, WIFI_PREAMBLE_LONG, phy->GetFrequency(), 0, 0));
147  }
149 }
150 
151 int64_t
153 {
154  NS_LOG_FUNCTION (this << stream);
156  return 1;
157 }
158 
159 Time
161 {
162 
163  for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
164  {
165  if (mode == i->second)
166  {
167  return i->first;
168  }
169  }
170  NS_ASSERT (false);
171  return Seconds (0);
172 }
173 
174 void
176 {
177  m_calcTxTime.push_back (std::make_pair (t, mode));
178 }
179 
182 {
184 
186  station->m_col = 0;
187  station->m_index = 0;
188  station->m_maxTpRate = 0;
189  station->m_maxTpRate2 = 0;
190  station->m_maxProbRate = 0;
191  station->m_packetCount = 0;
192  station->m_sampleCount = 0;
193  station->m_isSampling = false;
194  station->m_sampleRate = 0;
195  station->m_sampleRateSlower = false;
196  station->m_shortRetry = 0;
197  station->m_longRetry = 0;
198  station->m_retry = 0;
199  station->m_err = 0;
200  station->m_txrate = 0;
201  station->m_initialized = false;
202 
203  return station;
204 }
205 
206 void
208 {
209  if (!station->m_initialized && GetNSupported (station) > 1)
210  {
211  // Note: we appear to be doing late initialization of the table
212  // to make sure that the set of supported rates has been initialized
213  // before we perform our own initialization.
214  m_nsupported = GetNSupported (station);
216  station->m_sampleTable = SampleRate (m_nsupported, std::vector<uint32_t> (m_sampleCol));
217  InitSampleTable (station);
218  RateInit (station);
219  station->m_initialized = true;
220 
221  PrintTable (station);
222  PrintSampleTable (station);
223  }
224 }
225 
226 void
228  double rxSnr, WifiMode txMode)
229 {
230  NS_LOG_FUNCTION (this);
231 }
232 
233 void
235 {
237  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
238 
239  station->m_shortRetry++;
240 }
241 
242 void
243 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
244 {
245  NS_LOG_DEBUG ("self=" << st << " rts ok");
246 }
247 
248 void
250 {
252  UpdateRetry (station);
253  station->m_err++;
254 }
255 
256 void
258 {
276  CheckInit (station);
277  if (!station->m_initialized)
278  {
279  return;
280  }
281 
282  station->m_longRetry++;
283  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
284 
285  PrintTable (station);
286 
287  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
288 
290  if (!station->m_isSampling)
291  {
292  NS_LOG_DEBUG ("Failed with normal rate: current=" << station->m_txrate << ", sample=" << station->m_sampleRate << ", maxTp=" << station->m_maxTpRate << ", maxTp2=" << station->m_maxTpRate2 << ", maxProb=" << station->m_maxProbRate);
294  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
295  {
296  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
297  station->m_txrate = station->m_maxTpRate;
298  }
299 
301  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
302  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
303  {
304  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
305  station->m_txrate = station->m_maxTpRate2;
306  }
307 
309  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
310  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
311  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
312  {
313  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
314  station->m_txrate = station->m_maxProbRate;
315  }
316 
318  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
319  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
320  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
321  {
322  NS_LOG_DEBUG (" More retries left for the base rate.");
323  station->m_txrate = 0;
324  }
325  }
326 
328  else
329  {
330  NS_LOG_DEBUG ("Failed with look around rate: current=" << station->m_txrate << ", sample=" << station->m_sampleRate << ", maxTp=" << station->m_maxTpRate << ", maxTp2=" << station->m_maxTpRate2 << ", maxProb=" << station->m_maxProbRate);
332  if (station->m_sampleRateSlower)
333  {
334  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
336  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
337  {
338  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
339  station->m_txrate = station->m_maxTpRate;
340  }
341 
343  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
344  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
345  {
346  NS_LOG_DEBUG (" More retries left for the sampling rate.");
347  station->m_txrate = station->m_sampleRate;
348  }
349 
351  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
352  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
353  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
354  {
355  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
356  station->m_txrate = station->m_maxProbRate;
357  }
358 
360  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
361  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
362  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
363  {
364  NS_LOG_DEBUG (" More retries left for the base rate.");
365  station->m_txrate = 0;
366  }
367  }
368 
370  else
371  {
372  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
374  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
375  {
376  NS_LOG_DEBUG (" More retries left for the sampling rate.");
377  station->m_txrate = station->m_sampleRate;
378  }
379 
381  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
382  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
383  {
384  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
385  station->m_txrate = station->m_maxTpRate;
386  }
387 
389  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
390  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
391  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
392  {
393  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
394  station->m_txrate = station->m_maxProbRate;
395  }
396 
398  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
399  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
400  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
401  {
402  NS_LOG_DEBUG (" More retries left for the base rate.");
403  station->m_txrate = 0;
404  }
405  }
406  }
407 }
408 
409 void
411  double ackSnr, WifiMode ackMode, double dataSnr)
412 {
413  NS_LOG_FUNCTION (st << ackSnr << ackMode << dataSnr);
415 
416  station->m_isSampling = false;
417  station->m_sampleRateSlower = false;
418 
419  CheckInit (station);
420  if (!station->m_initialized)
421  {
422  return;
423  }
424  NS_LOG_DEBUG ("DoReportDataOk m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (before update).");
425 
426  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
427  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
428 
429  NS_LOG_DEBUG ("DoReportDataOk m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (after update).");
430 
431  UpdateRetry (station);
432 
433  station->m_packetCount++;
434 
435  if (m_nsupported >= 1)
436  {
437  station->m_txrate = FindRate (station);
438  }
439 }
440 
441 void
443 {
444  NS_LOG_FUNCTION (st);
446 
447  CheckInit (station);
448  if (!station->m_initialized)
449  {
450  return;
451  }
452 
453  NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (before update).");
454 
455  station->m_isSampling = false;
456  station->m_sampleRateSlower = false;
457 
458  UpdateRetry (station);
459 
460  station->m_err++;
461 
462  NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (after update).");
463 
464  if (m_nsupported >= 1)
465  {
466  station->m_txrate = FindRate (station);
467  }
468 }
469 
470 void
472 {
473  station->m_retry = station->m_shortRetry + station->m_longRetry;
474  station->m_shortRetry = 0;
475  station->m_longRetry = 0;
476 }
477 
480  uint32_t size)
481 {
483  if (!station->m_initialized)
484  {
485  CheckInit (station);
486 
488  station->m_txrate = m_nsupported / 2;
489  }
490  UpdateStats (station);
491  return WifiTxVector (GetSupported (station, station->m_txrate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas()), GetNess (station), GetStbc (station));
492 }
493 
496 {
498  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
499 
501 }
502 
503 bool
505 {
507 
508  CheckInit (station);
509  if (!station->m_initialized)
510  {
511  return normally;
512  }
513 
514  if (!station->m_isSampling)
515  {
516  if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
517  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
518  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
519  station->m_minstrelTable[0].adjustedRetryCount))
520  {
521  return false;
522  }
523  else
524  {
525  return true;
526  }
527  }
528  else
529  {
530  if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
531  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
532  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
533  station->m_minstrelTable[0].adjustedRetryCount))
534  {
535  return false;
536  }
537  else
538  {
539  return true;
540  }
541  }
542 }
543 
544 bool
546 {
547  return true;
548 }
549 uint32_t
551 {
552  uint32_t bitrate;
553  bitrate = station->m_sampleTable[station->m_index][station->m_col];
554  station->m_index++;
555 
557  if (station->m_index > (m_nsupported - 2))
558  {
559  station->m_index = 0;
560  station->m_col++;
561  if (station->m_col >= m_sampleCol)
562  {
563  station->m_col = 0;
564  }
565  }
566  return bitrate;
567 }
568 
569 uint32_t
571 {
572  NS_LOG_FUNCTION (this << station);
573 
574  if ((station->m_sampleCount + station->m_packetCount) == 0)
575  {
576  return 0;
577  }
578 
579 
580  uint32_t idx;
581 
583  int coinFlip = m_uniformRandomVariable->GetInteger (0, 100) % 2;
584 
590  if ( (((100 * station->m_sampleCount) / (station->m_sampleCount + station->m_packetCount )) < m_lookAroundRate)
591  && (coinFlip == 1) )
592  {
593  NS_LOG_DEBUG ("Using look around rate");
595  idx = GetNextSample (station);
596 
597 
602  if (idx != station->m_maxTpRate && idx != station->m_txrate)
603  {
604 
606  station->m_sampleCount++;
607 
609  station->m_isSampling = true;
610 
612  if (station->m_packetCount >= 10000)
613  {
614  station->m_sampleCount = 0;
615  station->m_packetCount = 0;
616  }
617 
619  if (idx >= m_nsupported)
620  {
621  NS_LOG_DEBUG ("ALERT!!! ERROR");
622  }
623 
625  station->m_sampleRate = idx;
626 
627  if (station->m_sampleRate == station->m_maxTpRate)
628  {
629  station->m_sampleRate = station->m_maxTpRate2;
630  }
631 
633  station->m_sampleRateSlower =
634  (station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime);
635 
637  if (station->m_sampleRateSlower)
638  {
639  NS_LOG_DEBUG ("The next look around rate is slower than the maximum throughput rate, continue with the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
640  idx = station->m_maxTpRate;
641  }
642  }
643  }
644 
646  else
647  {
648  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
649  idx = station->m_maxTpRate;
650  }
651 
652 
653  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
654 
655  return idx;
656 }
657 
658 void
660 {
661  if (Simulator::Now () < station->m_nextStatsUpdate)
662  {
663  return;
664  }
665 
666  if (!station->m_initialized)
667  {
668  return;
669  }
670  NS_LOG_FUNCTION (this);
672  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
673  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
674 
675  Time txTime;
676  uint32_t tempProb;
677 
678  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
679  for (uint32_t i = 0; i < m_nsupported; i++)
680  {
681 
683  txTime = station->m_minstrelTable[i].perfectTxTime;
684 
686  if (txTime.GetMicroSeconds () == 0)
687  {
688  txTime = Seconds (1);
689  }
690 
691  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
692  "\t" << station->m_minstrelTable[i].numRateAttempt <<
693  "\t" << station->m_minstrelTable[i].numRateSuccess);
694 
696  if (station->m_minstrelTable[i].numRateAttempt)
697  {
702  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
703 
705  station->m_minstrelTable[i].prob = tempProb;
706 
708  tempProb = static_cast<uint32_t> (((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100);
709 
710  station->m_minstrelTable[i].ewmaProb = tempProb;
711 
713  station->m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds ());
714 
715  }
716 
718  station->m_minstrelTable[i].numRateSuccess = 0;
719  station->m_minstrelTable[i].numRateAttempt = 0;
720 
722  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
723  {
731  if (station->m_minstrelTable[i].retryCount > 2)
732  {
733  station->m_minstrelTable[i].adjustedRetryCount = 2;
734  }
735  else
736  {
737  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
738  }
739  }
740  else
741  {
742  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
743  }
744 
746  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
747  {
748  station->m_minstrelTable[i].adjustedRetryCount = 1;
749  }
750  }
751  NS_LOG_DEBUG ("Attempt/success resetted to 0");
752 
753 
754  uint32_t max_prob = 0, index_max_prob = 0, max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
755 
757  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
758  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
759  for (uint32_t i = 0; i < m_nsupported; i++)
760  {
761  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
762  "\t" << station->m_minstrelTable[i].throughput <<
763  "\t" << station->m_minstrelTable[i].ewmaProb);
764 
765  if (max_tp < station->m_minstrelTable[i].throughput)
766  {
767  index_max_tp = i;
768  max_tp = station->m_minstrelTable[i].throughput;
769  }
770 
771  if (max_prob < station->m_minstrelTable[i].ewmaProb)
772  {
773  index_max_prob = i;
774  max_prob = station->m_minstrelTable[i].ewmaProb;
775  }
776  }
777 
778 
779  max_tp = 0;
781  for (uint32_t i = 0; i < m_nsupported; i++)
782  {
783  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
784  {
785  index_max_tp2 = i;
786  max_tp = station->m_minstrelTable[i].throughput;
787  }
788  }
789 
790  station->m_maxTpRate = index_max_tp;
791  station->m_maxTpRate2 = index_max_tp2;
792  station->m_maxProbRate = index_max_prob;
793 
794  if (index_max_tp > station->m_txrate)
795  {
796  station->m_txrate = index_max_tp;
797  }
798 
799  NS_LOG_DEBUG ("max throughput=" << index_max_tp << "(" << GetSupported (station, index_max_tp) <<
800  ")\tsecond max throughput=" << index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
801  ")\tmax prob=" << index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
802 }
803 
804 void
806 {
807  NS_LOG_FUNCTION (station);
808 
809  for (uint32_t i = 0; i < m_nsupported; i++)
810  {
811  NS_LOG_DEBUG ("Initializing rate index " << i << " " << GetSupported (station, i));
812  station->m_minstrelTable[i].numRateAttempt = 0;
813  station->m_minstrelTable[i].numRateSuccess = 0;
814  station->m_minstrelTable[i].prob = 0;
815  station->m_minstrelTable[i].ewmaProb = 0;
816  station->m_minstrelTable[i].throughput = 0;
817  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
818  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
819  station->m_minstrelTable[i].retryCount = 1;
820  station->m_minstrelTable[i].adjustedRetryCount = 1;
821  // Emulating minstrel.c::ath_rate_ctl_reset
822  // We only check from 2 to 10 retries. This guarantee that
823  // at least one retry is permitter.
824  Time totalTxTimeWithGivenRetries = Seconds (0.0); // tx_time in minstrel.c
825  NS_LOG_DEBUG (" Calculating the number of retries");
826  for (uint32_t retries = 2; retries < 11; retries++)
827  {
828  NS_LOG_DEBUG (" Checking " << retries << " retries");
829  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
830  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
831  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
832  {
833  break;
834  }
835  station->m_minstrelTable[i].retryCount = retries;
836  station->m_minstrelTable[i].adjustedRetryCount = retries;
837  }
838  }
839 }
840 
841 Time
842 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
843 {
844  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
845  // See rc80211_minstrel.c
846 
847  //First transmission (DATA + ACK timeout)
848  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
849 
850  uint32_t cwMax = 1023;
851  uint32_t cw = 31;
852  for (uint32_t retry = 0; retry < longRetries; retry++)
853  {
854  // Add one re-transmission (DATA + ACK timeout)
855  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
856 
857  // Add average back off (half the current contention window)
858  tt += NanoSeconds ((cw / 2) * GetMac ()->GetSlot ());
859 
860  // Update contention window
861  cw = std::min (cwMax, (cw + 1) * 2);
862  }
863 
864  return tt;
865 }
866 
867 void
869 {
870  NS_LOG_DEBUG ("InitSampleTable=" << this);
871 
872  station->m_col = station->m_index = 0;
873 
875  uint32_t numSampleRates = m_nsupported;
876 
877  uint32_t newIndex;
878  for (uint32_t col = 0; col < m_sampleCol; col++)
879  {
880  for (uint32_t i = 0; i < numSampleRates; i++ )
881  {
882 
887  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
888  newIndex = (i + uv) % numSampleRates;
889 
891  while (station->m_sampleTable[newIndex][col] != 0)
892  {
893  newIndex = (newIndex + 1) % m_nsupported;
894  }
895  station->m_sampleTable[newIndex][col] = i;
896 
897  }
898  }
899 }
900 
901 void
903 {
904  NS_LOG_DEBUG ("PrintSampleTable=" << station);
905 
906  uint32_t numSampleRates = m_nsupported;
907  std::stringstream table;
908  for (uint32_t i = 0; i < numSampleRates; i++)
909  {
910  for (uint32_t j = 0; j < m_sampleCol; j++)
911  {
912  table << station->m_sampleTable[i][j] << "\t";
913  }
914  table << std::endl;
915  }
916  NS_LOG_DEBUG (table.str());
917 }
918 
919 void
921 {
922  NS_LOG_DEBUG ("PrintTable=" << station);
923 
924  for (uint32_t i = 0; i < m_nsupported; i++)
925  {
926  NS_LOG_DEBUG (i << " (" << GetSupported (station, i) << "): " << station->m_minstrelTable[i].perfectTxTime << ", retryCount = " << station->m_minstrelTable[i].retryCount << ", adjustedRetryCount = " << station->m_minstrelTable[i].adjustedRetryCount);
927  }
928 }
929 
930 } // namespace ns3
931 
932 
933 
934 
935 
uint32_t m_nsupported
modes supported
void CheckInit(MinstrelWifiRemoteStation *station)
check for initializations
void PrintTable(MinstrelWifiRemoteStation *station)
printing Minstrel Table
uint32_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
virtual uint32_t GetFrequency(void) const =0
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint32_t GetInteger(uint32_t min, uint32_t max)
Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
Implementation of Minstrel Rate Control AlgorithmPorting Minstrel from Madwifi and Linux Kernel http:...
virtual uint32_t GetNModes(void) const =0
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
virtual void DoReportFinalDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
hold per-remote-station state for Minstrel Wifi manager.
Time m_updateStats
how frequent do we calculate the stats (1/10 seconds)
void UpdateStats(MinstrelWifiRemoteStation *station)
updating the Minstrel Table every 1/10 seconds
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t m_sampleRate
current sample rate
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:874
uint32_t GetNextSample(MinstrelWifiRemoteStation *station)
getting the next sample from Sample Table
virtual bool DoNeedDataRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally)
uint32_t m_txrate
current transmit rate
MinstrelRate m_minstrelTable
minstrel table
virtual void SetupPhy(Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:93
uint32_t GetNumberOfReceiveAntennas(const WifiRemoteStation *station) const
Return the number of receive antenna the station has.
WifiMode GetSupported(const WifiRemoteStation *station, uint32_t i) const
Return whether mode associated with the specified station at the specified index. ...
uint32_t FindRate(MinstrelWifiRemoteStation *station)
find a rate to use from Minstrel Table
uint32_t m_pktLen
packet length used for calculate mode TxTime
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
virtual void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr)
This method is a pure virtual method that must be implemented by the sub-class.
virtual void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode)
This method is a pure virtual method that must be implemented by the sub-class.
bool GetStbc(const WifiRemoteStation *station) const
Return whether the given station supports space-time block coding (STBC).
uint32_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:197
bool m_isSampling
a flag to indicate we are currently sampling
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:342
int m_sampleCount
how many packets we have sample so far
AttributeValue implementation for Time.
Definition: nstime.h:928
SampleRate m_sampleTable
sample table
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:890
void PrintSampleTable(MinstrelWifiRemoteStation *station)
printing Sample Table
virtual void SetupPhy(Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
double m_ewmaLevel
exponential weighted moving average
virtual WifiRemoteStation * DoCreateStation(void) const
virtual WifiTxVector DoGetDataTxVector(WifiRemoteStation *station, uint32_t size)
void AddCalcTxTime(WifiMode mode, Time t)
Add transmission time for the given mode to an internal list.
Time CalculateTxDuration(uint32_t size, WifiTxVector txvector, enum WifiPreamble preamble, double frequency, uint8_t packetType, uint8_t incFlag)
Definition: wifi-phy.cc:577
virtual void DoReportFinalRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
hold a list of per-remote-station state.
virtual WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)
uint32_t m_longRetry
long retries such as data packets
uint32_t GetNess(const WifiRemoteStation *station) const
bool m_initialized
for initializing tables
TxTime m_calcTxTime
to hold all the calculated TxTime for all modes
virtual bool IsLowLatency(void) const
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_maxTpRate2
second highest throughput rate
virtual WifiMode GetMode(uint32_t mode) const =0
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:929
bool GetShortGuardInterval(const WifiRemoteStation *station) const
Return whether the given station supports short guard interval.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
uint32_t m_retry
total retries short + long
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void UpdateRetry(MinstrelWifiRemoteStation *station)
update the number of retries and reset accordingly
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
double m_lookAroundRate
the % to try other rates than our current rate
void InitSampleTable(MinstrelWifiRemoteStation *station)
initialize Sample Table
uint32_t m_maxProbRate
rate with highest prob of success
uint32_t GetLongRetryCount(const WifiRemoteStation *station) const
Return the long retry limit of the given station.
virtual void DoReportRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
uint32_t m_maxTpRate
the current throughput rate
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:866
Time GetCalcTxTime(WifiMode mode) const
for estimating the TxTime of a packet with a given mode
virtual void DoReportDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
std::vector< struct RateInfo > MinstrelRate
Data structure for a Minstrel Rate table A vector of a struct RateInfo.
uint32_t GetShortRetryCount(const WifiRemoteStation *station) const
Return the short retry limit of the given station.
uint32_t m_sampleCol
number of sample columns
uint32_t m_shortRetry
short retries such as control packts
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
bool m_sampleRateSlower
a flag to indicate sample rate is slower
int m_packetCount
total number of packets as of now
virtual void DoReportRtsOk(WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr)
This method is a pure virtual method that must be implemented by the sub-class.
a unique identifier for an interface.
Definition: type-id.h:57
Time CalculateTimeUnicastPacket(Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
Estimate the time to transmit the given packet with the given number of retries.
void RateInit(MinstrelWifiRemoteStation *station)
initialize Minstrel Table
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
std::vector< std::vector< uint32_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint32_t.
hold per-remote-station state.
Ptr< WifiMac > GetMac(void) const
Return the WifiMac.
Time m_nextStatsUpdate
10 times every second