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  .AddConstructor<MinstrelWifiManager> ()
95  .AddAttribute ("UpdateStatistics",
96  "The interval between updating statistics table ",
97  TimeValue (Seconds (0.1)),
99  MakeTimeChecker ())
100  .AddAttribute ("LookAroundRate",
101  "the percentage to try other rates",
102  DoubleValue (10),
104  MakeDoubleChecker<double> ())
105  .AddAttribute ("EWMA",
106  "EWMA level",
107  DoubleValue (75),
109  MakeDoubleChecker<double> ())
110  .AddAttribute ("SampleColumn",
111  "The number of columns used for sampling",
112  DoubleValue (10),
114  MakeDoubleChecker <double> ())
115  .AddAttribute ("PacketLength",
116  "The packet length used for calculating mode TxTime",
117  DoubleValue (1200),
119  MakeDoubleChecker <double> ())
120  ;
121  return tid;
122 }
123 
125 {
126  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
127 
128  m_nsupported = 0;
129 }
130 
132 {
133 }
134 
135 void
137 {
138  NS_LOG_FUNCTION(this << phy);
139  uint32_t nModes = phy->GetNModes ();
140  for (uint32_t i = 0; i < nModes; i++)
141  {
142  WifiMode mode = phy->GetMode (i);
143  WifiTxVector txVector;
144  txVector.SetMode(mode);
145  AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, WIFI_PREAMBLE_LONG, phy->GetFrequency(), 0, 0));
146  }
148 }
149 
150 int64_t
152 {
153  NS_LOG_FUNCTION (this << stream);
155  return 1;
156 }
157 
158 Time
160 {
161 
162  for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
163  {
164  if (mode == i->second)
165  {
166  return i->first;
167  }
168  }
169  NS_ASSERT (false);
170  return Seconds (0);
171 }
172 
173 void
175 {
176  m_calcTxTime.push_back (std::make_pair (t, mode));
177 }
178 
181 {
183 
185  station->m_col = 0;
186  station->m_index = 0;
187  station->m_maxTpRate = 0;
188  station->m_maxTpRate2 = 0;
189  station->m_maxProbRate = 0;
190  station->m_packetCount = 0;
191  station->m_sampleCount = 0;
192  station->m_isSampling = false;
193  station->m_sampleRate = 0;
194  station->m_sampleRateSlower = false;
195  station->m_shortRetry = 0;
196  station->m_longRetry = 0;
197  station->m_retry = 0;
198  station->m_err = 0;
199  station->m_txrate = 0;
200  station->m_initialized = false;
201 
202  return station;
203 }
204 
205 void
207 {
208  if (!station->m_initialized && GetNSupported (station) > 1)
209  {
210  // Note: we appear to be doing late initialization of the table
211  // to make sure that the set of supported rates has been initialized
212  // before we perform our own initialization.
213  m_nsupported = GetNSupported (station);
215  station->m_sampleTable = SampleRate (m_nsupported, std::vector<uint32_t> (m_sampleCol));
216  InitSampleTable (station);
217  RateInit (station);
218  station->m_initialized = true;
219 
220  PrintTable (station);
221  PrintSampleTable (station);
222  }
223 }
224 
225 void
227  double rxSnr, WifiMode txMode)
228 {
229  NS_LOG_FUNCTION (this);
230 }
231 
232 void
234 {
236  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
237 
238  station->m_shortRetry++;
239 }
240 
241 void
242 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
243 {
244  NS_LOG_DEBUG ("self=" << st << " rts ok");
245 }
246 
247 void
249 {
251  UpdateRetry (station);
252  station->m_err++;
253 }
254 
255 void
257 {
275  CheckInit (station);
276  if (!station->m_initialized)
277  {
278  return;
279  }
280 
281  station->m_longRetry++;
282  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
283 
284  PrintTable (station);
285 
286  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
287 
289  if (!station->m_isSampling)
290  {
291  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);
293  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
294  {
295  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
296  station->m_txrate = station->m_maxTpRate;
297  }
298 
300  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
301  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
302  {
303  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
304  station->m_txrate = station->m_maxTpRate2;
305  }
306 
308  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
309  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
310  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
311  {
312  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
313  station->m_txrate = station->m_maxProbRate;
314  }
315 
317  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
318  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
319  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
320  {
321  NS_LOG_DEBUG (" More retries left for the base rate.");
322  station->m_txrate = 0;
323  }
324  }
325 
327  else
328  {
329  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);
331  if (station->m_sampleRateSlower)
332  {
333  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
335  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
336  {
337  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
338  station->m_txrate = station->m_maxTpRate;
339  }
340 
342  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
343  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
344  {
345  NS_LOG_DEBUG (" More retries left for the sampling rate.");
346  station->m_txrate = station->m_sampleRate;
347  }
348 
350  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
351  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
352  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
353  {
354  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
355  station->m_txrate = station->m_maxProbRate;
356  }
357 
359  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
360  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
361  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
362  {
363  NS_LOG_DEBUG (" More retries left for the base rate.");
364  station->m_txrate = 0;
365  }
366  }
367 
369  else
370  {
371  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
373  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
374  {
375  NS_LOG_DEBUG (" More retries left for the sampling rate.");
376  station->m_txrate = station->m_sampleRate;
377  }
378 
380  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
381  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
382  {
383  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
384  station->m_txrate = station->m_maxTpRate;
385  }
386 
388  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
389  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
390  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
391  {
392  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
393  station->m_txrate = station->m_maxProbRate;
394  }
395 
397  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
398  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
399  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
400  {
401  NS_LOG_DEBUG (" More retries left for the base rate.");
402  station->m_txrate = 0;
403  }
404  }
405  }
406 }
407 
408 void
410  double ackSnr, WifiMode ackMode, double dataSnr)
411 {
412  NS_LOG_FUNCTION (st << ackSnr << ackMode << dataSnr);
414 
415  station->m_isSampling = false;
416  station->m_sampleRateSlower = false;
417 
418  CheckInit (station);
419  if (!station->m_initialized)
420  {
421  return;
422  }
423  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).");
424 
425  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
426  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
427 
428  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).");
429 
430  UpdateRetry (station);
431 
432  station->m_packetCount++;
433 
434  if (m_nsupported >= 1)
435  {
436  station->m_txrate = FindRate (station);
437  }
438 }
439 
440 void
442 {
443  NS_LOG_FUNCTION (st);
445 
446  CheckInit (station);
447  if (!station->m_initialized)
448  {
449  return;
450  }
451 
452  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).");
453 
454  station->m_isSampling = false;
455  station->m_sampleRateSlower = false;
456 
457  UpdateRetry (station);
458 
459  station->m_err++;
460 
461  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).");
462 
463  if (m_nsupported >= 1)
464  {
465  station->m_txrate = FindRate (station);
466  }
467 }
468 
469 void
471 {
472  station->m_retry = station->m_shortRetry + station->m_longRetry;
473  station->m_shortRetry = 0;
474  station->m_longRetry = 0;
475 }
476 
479  uint32_t size)
480 {
482  if (!station->m_initialized)
483  {
484  CheckInit (station);
485 
487  station->m_txrate = m_nsupported / 2;
488  }
489  UpdateStats (station);
490  return WifiTxVector (GetSupported (station, station->m_txrate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas()), GetNess (station), GetStbc (station));
491 }
492 
495 {
497  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
498 
500 }
501 
502 bool
504 {
506 
507  CheckInit (station);
508  if (!station->m_initialized)
509  {
510  return normally;
511  }
512 
513  if (!station->m_isSampling)
514  {
515  if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
516  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
517  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
518  station->m_minstrelTable[0].adjustedRetryCount))
519  {
520  return false;
521  }
522  else
523  {
524  return true;
525  }
526  }
527  else
528  {
529  if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
530  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
531  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
532  station->m_minstrelTable[0].adjustedRetryCount))
533  {
534  return false;
535  }
536  else
537  {
538  return true;
539  }
540  }
541 }
542 
543 bool
545 {
546  return true;
547 }
548 uint32_t
550 {
551  uint32_t bitrate;
552  bitrate = station->m_sampleTable[station->m_index][station->m_col];
553  station->m_index++;
554 
556  if (station->m_index > (m_nsupported - 2))
557  {
558  station->m_index = 0;
559  station->m_col++;
560  if (station->m_col >= m_sampleCol)
561  {
562  station->m_col = 0;
563  }
564  }
565  return bitrate;
566 }
567 
568 uint32_t
570 {
571  NS_LOG_FUNCTION (this << station);
572 
573  if ((station->m_sampleCount + station->m_packetCount) == 0)
574  {
575  return 0;
576  }
577 
578 
579  uint32_t idx;
580 
582  int coinFlip = m_uniformRandomVariable->GetInteger (0, 100) % 2;
583 
589  if ( (((100 * station->m_sampleCount) / (station->m_sampleCount + station->m_packetCount )) < m_lookAroundRate)
590  && (coinFlip == 1) )
591  {
592  NS_LOG_DEBUG ("Using look around rate");
594  idx = GetNextSample (station);
595 
596 
601  if (idx != station->m_maxTpRate && idx != station->m_txrate)
602  {
603 
605  station->m_sampleCount++;
606 
608  station->m_isSampling = true;
609 
611  if (station->m_packetCount >= 10000)
612  {
613  station->m_sampleCount = 0;
614  station->m_packetCount = 0;
615  }
616 
618  if (idx >= m_nsupported)
619  {
620  NS_LOG_DEBUG ("ALERT!!! ERROR");
621  }
622 
624  station->m_sampleRate = idx;
625 
626  if (station->m_sampleRate == station->m_maxTpRate)
627  {
628  station->m_sampleRate = station->m_maxTpRate2;
629  }
630 
632  station->m_sampleRateSlower =
633  (station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime);
634 
636  if (station->m_sampleRateSlower)
637  {
638  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) << ")");
639  idx = station->m_maxTpRate;
640  }
641  }
642  }
643 
645  else
646  {
647  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
648  idx = station->m_maxTpRate;
649  }
650 
651 
652  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
653 
654  return idx;
655 }
656 
657 void
659 {
660  if (Simulator::Now () < station->m_nextStatsUpdate)
661  {
662  return;
663  }
664 
665  if (!station->m_initialized)
666  {
667  return;
668  }
669  NS_LOG_FUNCTION (this);
671  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
672  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
673 
674  Time txTime;
675  uint32_t tempProb;
676 
677  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
678  for (uint32_t i = 0; i < m_nsupported; i++)
679  {
680 
682  txTime = station->m_minstrelTable[i].perfectTxTime;
683 
685  if (txTime.GetMicroSeconds () == 0)
686  {
687  txTime = Seconds (1);
688  }
689 
690  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
691  "\t" << station->m_minstrelTable[i].numRateAttempt <<
692  "\t" << station->m_minstrelTable[i].numRateSuccess);
693 
695  if (station->m_minstrelTable[i].numRateAttempt)
696  {
701  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
702 
704  station->m_minstrelTable[i].prob = tempProb;
705 
707  tempProb = static_cast<uint32_t> (((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100);
708 
709  station->m_minstrelTable[i].ewmaProb = tempProb;
710 
712  station->m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds ());
713 
714  }
715 
717  station->m_minstrelTable[i].numRateSuccess = 0;
718  station->m_minstrelTable[i].numRateAttempt = 0;
719 
721  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
722  {
730  if (station->m_minstrelTable[i].retryCount > 2)
731  {
732  station->m_minstrelTable[i].adjustedRetryCount = 2;
733  }
734  else
735  {
736  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
737  }
738  }
739  else
740  {
741  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
742  }
743 
745  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
746  {
747  station->m_minstrelTable[i].adjustedRetryCount = 1;
748  }
749  }
750  NS_LOG_DEBUG ("Attempt/success resetted to 0");
751 
752 
753  uint32_t max_prob = 0, index_max_prob = 0, max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
754 
756  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
757  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
758  for (uint32_t i = 0; i < m_nsupported; i++)
759  {
760  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
761  "\t" << station->m_minstrelTable[i].throughput <<
762  "\t" << station->m_minstrelTable[i].ewmaProb);
763 
764  if (max_tp < station->m_minstrelTable[i].throughput)
765  {
766  index_max_tp = i;
767  max_tp = station->m_minstrelTable[i].throughput;
768  }
769 
770  if (max_prob < station->m_minstrelTable[i].ewmaProb)
771  {
772  index_max_prob = i;
773  max_prob = station->m_minstrelTable[i].ewmaProb;
774  }
775  }
776 
777 
778  max_tp = 0;
780  for (uint32_t i = 0; i < m_nsupported; i++)
781  {
782  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
783  {
784  index_max_tp2 = i;
785  max_tp = station->m_minstrelTable[i].throughput;
786  }
787  }
788 
789  station->m_maxTpRate = index_max_tp;
790  station->m_maxTpRate2 = index_max_tp2;
791  station->m_maxProbRate = index_max_prob;
792 
793  if (index_max_tp > station->m_txrate)
794  {
795  station->m_txrate = index_max_tp;
796  }
797 
798  NS_LOG_DEBUG ("max throughput=" << index_max_tp << "(" << GetSupported (station, index_max_tp) <<
799  ")\tsecond max throughput=" << index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
800  ")\tmax prob=" << index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
801 }
802 
803 void
805 {
806  NS_LOG_FUNCTION (station);
807 
808  for (uint32_t i = 0; i < m_nsupported; i++)
809  {
810  NS_LOG_DEBUG ("Initializing rate index " << i << " " << GetSupported (station, i));
811  station->m_minstrelTable[i].numRateAttempt = 0;
812  station->m_minstrelTable[i].numRateSuccess = 0;
813  station->m_minstrelTable[i].prob = 0;
814  station->m_minstrelTable[i].ewmaProb = 0;
815  station->m_minstrelTable[i].throughput = 0;
816  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
817  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
818  station->m_minstrelTable[i].retryCount = 1;
819  station->m_minstrelTable[i].adjustedRetryCount = 1;
820  // Emulating minstrel.c::ath_rate_ctl_reset
821  // We only check from 2 to 10 retries. This guarantee that
822  // at least one retry is permitter.
823  Time totalTxTimeWithGivenRetries = Seconds (0.0); // tx_time in minstrel.c
824  NS_LOG_DEBUG (" Calculating the number of retries");
825  for (uint32_t retries = 2; retries < 11; retries++)
826  {
827  NS_LOG_DEBUG (" Checking " << retries << " retries");
828  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
829  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
830  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
831  {
832  break;
833  }
834  station->m_minstrelTable[i].retryCount = retries;
835  station->m_minstrelTable[i].adjustedRetryCount = retries;
836  }
837  }
838 }
839 
840 Time
841 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
842 {
843  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
844  // See rc80211_minstrel.c
845 
846  //First transmission (DATA + ACK timeout)
847  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
848 
849  uint32_t cwMax = 1023;
850  uint32_t cw = 31;
851  for (uint32_t retry = 0; retry < longRetries; retry++)
852  {
853  // Add one re-transmission (DATA + ACK timeout)
854  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
855 
856  // Add average back off (half the current contention window)
857  tt += NanoSeconds ((cw / 2) * GetMac ()->GetSlot ());
858 
859  // Update contention window
860  cw = std::min (cwMax, (cw + 1) * 2);
861  }
862 
863  return tt;
864 }
865 
866 void
868 {
869  NS_LOG_DEBUG ("InitSampleTable=" << this);
870 
871  station->m_col = station->m_index = 0;
872 
874  uint32_t numSampleRates = m_nsupported;
875 
876  uint32_t newIndex;
877  for (uint32_t col = 0; col < m_sampleCol; col++)
878  {
879  for (uint32_t i = 0; i < numSampleRates; i++ )
880  {
881 
886  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
887  newIndex = (i + uv) % numSampleRates;
888 
890  while (station->m_sampleTable[newIndex][col] != 0)
891  {
892  newIndex = (newIndex + 1) % m_nsupported;
893  }
894  station->m_sampleTable[newIndex][col] = i;
895 
896  }
897  }
898 }
899 
900 void
902 {
903  NS_LOG_DEBUG ("PrintSampleTable=" << station);
904 
905  uint32_t numSampleRates = m_nsupported;
906  std::stringstream table;
907  for (uint32_t i = 0; i < numSampleRates; i++)
908  {
909  for (uint32_t j = 0; j < m_sampleCol; j++)
910  {
911  table << station->m_sampleTable[i][j] << "\t";
912  }
913  table << std::endl;
914  }
915  NS_LOG_DEBUG (table.str());
916 }
917 
918 void
920 {
921  NS_LOG_DEBUG ("PrintTable=" << station);
922 
923  for (uint32_t i = 0; i < m_nsupported; i++)
924  {
925  NS_LOG_DEBUG (i << " (" << GetSupported (station, i) << "): " << station->m_minstrelTable[i].perfectTxTime << ", retryCount = " << station->m_minstrelTable[i].retryCount << ", adjustedRetryCount = " << station->m_minstrelTable[i].adjustedRetryCount);
926  }
927 }
928 
929 } // namespace ns3
930 
931 
932 
933 
934 
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:95
#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:61
#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:867
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:439
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:191
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:335
int m_sampleCount
how many packets we have sample so far
AttributeValue implementation for Time.
Definition: nstime.h:921
SampleRate m_sampleTable
sample table
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:883
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:576
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:922
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:859
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:51
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:631
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