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  * Authors: Duy Nguyen <duy@soe.ucsc.edu>
19  * Matías Richart <mrichart@fing.edu.uy>
20  *
21  * Some Comments:
22  *
23  * 1) Segment Size is declared for completeness but not used because it has
24  * to do more with the requirement of the specific hardware.
25  *
26  * 2) By default, Minstrel applies the multi-rate retry (the core of Minstrel
27  * algorithm). Otherwise, please use ConstantRateWifiManager instead.
28  *
29  * http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel
30  */
31 
32 #include <iomanip>
33 #include "ns3/packet.h"
34 #include "ns3/random-variable-stream.h"
35 #include "ns3/simulator.h"
36 #include "ns3/log.h"
37 #include "minstrel-wifi-manager.h"
38 #include "wifi-mac.h"
39 #include "wifi-phy.h"
40 
41 #define Min(a,b) ((a < b) ? a : b)
42 
43 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager");
46 
47 NS_OBJECT_ENSURE_REGISTERED (MinstrelWifiManager);
48 
49 TypeId
51 {
52  static TypeId tid = TypeId ("ns3::MinstrelWifiManager")
54  .SetGroupName ("Wifi")
55  .AddConstructor<MinstrelWifiManager> ()
56  .AddAttribute ("UpdateStatistics",
57  "The interval between updating statistics table ",
58  TimeValue (Seconds (0.1)),
60  MakeTimeChecker ())
61  .AddAttribute ("LookAroundRate",
62  "the percentage to try other rates",
63  UintegerValue (10),
65  MakeUintegerChecker<uint8_t> ())
66  .AddAttribute ("EWMA",
67  "EWMA level",
68  UintegerValue (75),
70  MakeUintegerChecker<uint8_t> ())
71  .AddAttribute ("SampleColumn",
72  "The number of columns used for sampling",
73  UintegerValue (10),
75  MakeUintegerChecker <uint8_t> ())
76  .AddAttribute ("PacketLength",
77  "The packet length used for calculating mode TxTime",
78  UintegerValue (1200),
80  MakeUintegerChecker <uint32_t> ())
81  .AddAttribute ("PrintStats",
82  "Print statistics table",
83  BooleanValue (false),
86  .AddAttribute ("PrintSamples",
87  "Print samples table",
88  BooleanValue (false),
91  .AddTraceSource ("Rate",
92  "Traced value for rate changes (b/s)",
94  "ns3::TracedValueCallback::Uint64")
95  ;
96  return tid;
97 }
98 
101  m_currentRate (0)
102 {
103  NS_LOG_FUNCTION (this);
104  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
105 }
106 
108 {
109  NS_LOG_FUNCTION (this);
110 }
111 
112 void
114 {
115  NS_LOG_FUNCTION (this << phy);
116  uint8_t nModes = phy->GetNModes ();
117  for (uint8_t i = 0; i < nModes; i++)
118  {
119  WifiMode mode = phy->GetMode (i);
120  WifiTxVector txVector;
121  txVector.SetMode (mode);
123  AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, phy->GetFrequency ()));
124  }
126 }
127 
128 void
130 {
131  NS_LOG_FUNCTION (this << mac);
133 }
134 
135 void
137 {
138  NS_LOG_FUNCTION (this);
139  if (GetHtSupported ())
140  {
141  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
142  }
143  if (GetVhtSupported ())
144  {
145  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
146  }
147  if (GetHeSupported ())
148  {
149  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
150  }
151 }
152 
153 int64_t
155 {
156  NS_LOG_FUNCTION (this << stream);
158  return 1;
159 }
160 
161 Time
163 {
164  NS_LOG_FUNCTION (this << mode);
165  auto it = m_calcTxTime.find (mode);
166  NS_ASSERT (it != m_calcTxTime.end ());
167  return it->second;
168 }
169 
170 void
172 {
173  NS_LOG_FUNCTION (this << mode << t);
174  m_calcTxTime.insert (std::make_pair (mode, t));
175 }
176 
179 {
180  NS_LOG_FUNCTION (this);
182 
184  station->m_col = 0;
185  station->m_index = 0;
186  station->m_maxTpRate = 0;
187  station->m_maxTpRate2 = 0;
188  station->m_maxProbRate = 0;
189  station->m_nModes = 0;
190  station->m_totalPacketsCount = 0;
191  station->m_samplePacketsCount = 0;
192  station->m_isSampling = false;
193  station->m_sampleRate = 0;
194  station->m_sampleDeferred = false;
195  station->m_shortRetry = 0;
196  station->m_longRetry = 0;
197  station->m_retry = 0;
198  station->m_txrate = 0;
199  station->m_initialized = false;
200 
201  return station;
202 }
203 
204 void
206 {
207  NS_LOG_FUNCTION (this << station);
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  station->m_nModes = GetNSupported (station);
214  station->m_minstrelTable = MinstrelRate (station->m_nModes);
215  station->m_sampleTable = SampleRate (station->m_nModes, std::vector<uint8_t> (m_sampleCol));
216  InitSampleTable (station);
217  RateInit (station);
218  station->m_initialized = true;
219  std::ostringstream tmp;
220  tmp << "minstrel-stats-" << station->m_state->m_address << ".txt";
221  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
222  }
223 }
224 
240 void
242 {
243  NS_LOG_FUNCTION (this << station);
244  station->m_longRetry++;
245  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
246 
247  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
248 
249  //for normal rate, we're not currently sampling random rates
250  if (!station->m_isSampling)
251  {
252  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);
253  //use best throughput rate
254  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
255  {
256  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
257  station->m_txrate = station->m_maxTpRate;
258  }
259 
260  //use second best throughput rate
261  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
262  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
263  {
264  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
265  station->m_txrate = station->m_maxTpRate2;
266  }
267 
268  //use best probability rate
269  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
270  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
271  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
272  {
273  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
274  station->m_txrate = station->m_maxProbRate;
275  }
276 
277  //use lowest base rate
278  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
279  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
280  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
281  {
282  NS_LOG_DEBUG (" More retries left for the base rate.");
283  station->m_txrate = 0;
284  }
285  }
286 
287  //for look-around rate, we're currently sampling random rates
288  else
289  {
290  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);
291  //current sampling rate is slower than the current best rate
292  if (station->m_sampleDeferred)
293  {
294  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
295  //use best throughput rate
296  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
297  {
298  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
299  station->m_txrate = station->m_maxTpRate;
300  }
301 
302  //use random rate
303  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
304  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
305  {
306  NS_LOG_DEBUG (" More retries left for the sampling rate.");
307  station->m_txrate = station->m_sampleRate;
308  }
309 
310  //use max probability rate
311  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
312  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
313  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
314  {
315  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
316  station->m_txrate = station->m_maxProbRate;
317  }
318 
319  //use lowest base rate
320  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
321  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
322  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
323  {
324  NS_LOG_DEBUG (" More retries left for the base rate.");
325  station->m_txrate = 0;
326  }
327  }
328  //current sampling rate is better than current best rate
329  else
330  {
331  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
332  //use random rate
333  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
334  {
335  NS_LOG_DEBUG (" More retries left for the sampling rate.");
336  station->m_txrate = station->m_sampleRate;
337  }
338 
339  //use the best throughput rate
340  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
341  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
342  {
343  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
344  station->m_txrate = station->m_maxTpRate;
345  }
346 
347  //use the best probability rate
348  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
349  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
350  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
351  {
352  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
353  station->m_txrate = station->m_maxProbRate;
354  }
355 
356  //use the lowest base rate
357  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
358  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
359  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
360  {
361  NS_LOG_DEBUG (" More retries left for the base rate.");
362  station->m_txrate = 0;
363  }
364  }
365  }
366 }
367 
370 {
371  NS_LOG_FUNCTION (this << station);
372  uint16_t channelWidth = GetChannelWidth (station);
373  if (channelWidth > 20 && channelWidth != 22)
374  {
375  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
376  channelWidth = 20;
377  }
378  if (!station->m_initialized)
379  {
380  CheckInit (station);
381  }
382  WifiMode mode = GetSupported (station, station->m_txrate);
383  if (m_currentRate != mode.GetDataRate (channelWidth) && !station->m_isSampling)
384  {
385  NS_LOG_DEBUG ("New datarate: " << mode.GetDataRate (channelWidth));
386  m_currentRate = mode.GetDataRate (channelWidth);
387  }
388  return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode.GetModulationClass (), GetShortPreambleEnabled (), UseGreenfieldForDestination (GetAddress (station))), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
389 }
390 
393 {
394  NS_LOG_FUNCTION (this << station);
395  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
396  uint16_t channelWidth = GetChannelWidth (station);
397  if (channelWidth > 20 && channelWidth != 22)
398  {
399  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
400  channelWidth = 20;
401  }
402  WifiTxVector rtsTxVector;
403  WifiMode mode;
404  if (GetUseNonErpProtection () == false)
405  {
406  mode = GetSupported (station, 0);
407  }
408  else
409  {
410  mode = GetNonErpSupported (station, 0);
411  }
412  rtsTxVector = WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode.GetModulationClass (), GetShortPreambleEnabled (), UseGreenfieldForDestination (GetAddress (station))), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
413  return rtsTxVector;
414 }
415 
416 uint32_t
418 {
419  if (!station->m_isSampling)
420  {
421  return station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
422  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
423  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
424  station->m_minstrelTable[0].adjustedRetryCount;
425  }
426  else
427  {
428  return station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
429  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
430  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
431  station->m_minstrelTable[0].adjustedRetryCount;
432  }
433 }
434 
435 uint16_t
437 {
438  NS_LOG_FUNCTION (this << station);
439 
440  if (station->m_totalPacketsCount == 0)
441  {
442  return 0;
443  }
444 
445  uint16_t idx = 0;
446  NS_LOG_DEBUG ("Total: " << station->m_totalPacketsCount << " Sample: " << station->m_samplePacketsCount << " Deferred: " << station->m_numSamplesDeferred);
447 
448  int delta = (station->m_totalPacketsCount * m_lookAroundRate / 100) - (station->m_samplePacketsCount + station->m_numSamplesDeferred / 2);
449 
450  NS_LOG_DEBUG ("Decide sampling. Delta: " << delta << " lookAroundRatio: " << m_lookAroundRate);
451 
452  /* delta < 0: no sampling required */
453  if (delta >= 0)
454  {
455  NS_LOG_DEBUG ("Search next sampling rate");
456  uint8_t ratesSupported = station->m_nModes;
457  if (delta > ratesSupported * 2)
458  {
459  /* From Linux implementation:
460  * With multi-rate retry, not every planned sample
461  * attempt actually gets used, due to the way the retry
462  * chain is set up - [max_tp,sample,prob,lowest] for
463  * sample_rate < max_tp.
464  *
465  * If there's too much sampling backlog and the link
466  * starts getting worse, minstrel would start bursting
467  * out lots of sampling frames, which would result
468  * in a large throughput loss. */
469  station->m_samplePacketsCount += (delta - ratesSupported * 2);
470  }
471 
472  //now go through the table and find an index rate
473  idx = GetNextSample (station);
474 
475  NS_LOG_DEBUG ("Sample rate = " << idx << "(" << GetSupported (station, idx) << ")");
476 
477  //error check
478  if (idx >= station->m_nModes)
479  {
480  NS_LOG_DEBUG ("ALERT!!! ERROR");
481  }
482 
483  //set the rate that we're currently sampling
484  station->m_sampleRate = idx;
485 
486  /* From Linux implementation:
487  * Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
488  * rate sampling method should be used.
489  * Respect such rates that are not sampled for 20 iterations.
490  */
491  if ((station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime)
492  && (station->m_minstrelTable[idx].numSamplesSkipped < 20))
493  {
494  // If the rate is slower and we have sample it enough, defer to second stage
495  station->m_sampleDeferred = true;
496  station->m_numSamplesDeferred++;
497 
498  //set flag that we are currently sampling
499  station->m_isSampling = true;
500  }
501  else
502  {
503  // if samplieLimit is zero, then don't sample this rate
504  if (!station->m_minstrelTable[idx].sampleLimit)
505  {
506  idx = station->m_maxTpRate;
507  station->m_isSampling = false;
508  }
509  else
510  {
511  //set flag that we are currently sampling
512  station->m_isSampling = true;
513  if (station->m_minstrelTable[idx].sampleLimit > 0)
514  {
515  station->m_minstrelTable[idx].sampleLimit--;
516  }
517  }
518  }
519 
520  //using the best rate instead
521  if (station->m_sampleDeferred)
522  {
523  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) << ")");
524  idx = station->m_maxTpRate;
525  }
526  }
527  //continue using the best rate
528  else
529  {
530  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
531  idx = station->m_maxTpRate;
532  }
533 
534  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
535 
536  return idx;
537 }
538 
539 void
541 {
542  NS_LOG_FUNCTION (this << station);
543  if (Simulator::Now () < station->m_nextStatsUpdate)
544  {
545  return;
546  }
547 
548  if (!station->m_initialized)
549  {
550  return;
551  }
552  NS_LOG_FUNCTION (this);
554  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
555  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
556 
557  Time txTime;
558  uint32_t tempProb;
559 
560  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
561  for (uint8_t i = 0; i < station->m_nModes; i++)
562  {
563 
564  //calculate the perfect tx time for this rate
565  txTime = station->m_minstrelTable[i].perfectTxTime;
566 
567  //just for initialization
568  if (txTime.GetMicroSeconds () == 0)
569  {
570  txTime = Seconds (1);
571  }
572 
573  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
574  "\t" << station->m_minstrelTable[i].numRateAttempt <<
575  "\t" << station->m_minstrelTable[i].numRateSuccess);
576 
577  //if we've attempted something
578  if (station->m_minstrelTable[i].numRateAttempt)
579  {
580  station->m_minstrelTable[i].numSamplesSkipped = 0;
585  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
586 
587  //bookkeeping
588  station->m_minstrelTable[i].prob = tempProb;
589 
590  if (station->m_minstrelTable[i].successHist == 0)
591  {
592  station->m_minstrelTable[i].ewmaProb = tempProb;
593  }
594  else
595  {
596  //ewma probability (cast for gcc 3.4 compatibility)
597  tempProb = ((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100;
598 
599  station->m_minstrelTable[i].ewmaProb = tempProb;
600  }
601 
602  //calculating throughput
603  station->m_minstrelTable[i].throughput = tempProb * static_cast<uint32_t> ((1000000 / txTime.GetMicroSeconds ()));
604  }
605  else
606  {
607  station->m_minstrelTable[i].numSamplesSkipped++;
608  }
609 
610  //bookkeeping
611  station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess;
612  station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt;
613  station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess;
614  station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt;
615  station->m_minstrelTable[i].numRateSuccess = 0;
616  station->m_minstrelTable[i].numRateAttempt = 0;
617 
618  //Sample less often below 10% and above 95% of success
619  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
620  {
628  if (station->m_minstrelTable[i].retryCount > 2)
629  {
630  station->m_minstrelTable[i].adjustedRetryCount = 2;
631  }
632  station->m_minstrelTable[i].sampleLimit = 4;
633  }
634  else
635  {
636  // no sampling limit.
637  station->m_minstrelTable[i].sampleLimit = -1;
638  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
639  }
640 
641  //if it's 0 allow two retries.
642  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
643  {
644  station->m_minstrelTable[i].adjustedRetryCount = 2;
645  }
646  }
647 
648  NS_LOG_DEBUG ("Attempt/success reset to 0");
649 
650  uint32_t max_tp = 0;
651  uint8_t index_max_tp = 0, index_max_tp2 = 0;
652 
653  //go find max throughput, second maximum throughput, high probability succ
654  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
655  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
656  for (uint8_t i = 0; i < station->m_nModes; i++)
657  {
658  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
659  "\t" << station->m_minstrelTable[i].throughput <<
660  "\t" << station->m_minstrelTable[i].ewmaProb);
661 
662  if (max_tp < station->m_minstrelTable[i].throughput)
663  {
664  index_max_tp = i;
665  max_tp = station->m_minstrelTable[i].throughput;
666  }
667  }
668 
669  max_tp = 0;
670  //find the second highest max
671  for (uint8_t i = 0; i < station->m_nModes; i++)
672  {
673  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
674  {
675  index_max_tp2 = i;
676  max_tp = station->m_minstrelTable[i].throughput;
677  }
678  }
679 
680  uint32_t max_prob = 0;
681  uint8_t index_max_prob = 0;
682  for (uint8_t i = 0; i < station->m_nModes; i++)
683  {
684  if ((station->m_minstrelTable[i].ewmaProb >= 95 * 180) && (station->m_minstrelTable[i].throughput >= station->m_minstrelTable[index_max_prob].throughput))
685  {
686  index_max_prob = i;
687  max_prob = station->m_minstrelTable[i].ewmaProb;
688  }
689  else if (station->m_minstrelTable[i].ewmaProb >= max_prob)
690  {
691  index_max_prob = i;
692  max_prob = station->m_minstrelTable[i].ewmaProb;
693  }
694  }
695 
696  station->m_maxTpRate = index_max_tp;
697  station->m_maxTpRate2 = index_max_tp2;
698  station->m_maxProbRate = index_max_prob;
699 
700  if (index_max_tp > station->m_txrate)
701  {
702  station->m_txrate = index_max_tp;
703  }
704 
705  NS_LOG_DEBUG ("max throughput=" << +index_max_tp << "(" << GetSupported (station, index_max_tp) <<
706  ")\tsecond max throughput=" << +index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
707  ")\tmax prob=" << +index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
708  if (m_printStats)
709  {
710  PrintTable (station);
711  }
712  if (m_printSamples)
713  {
714  PrintSampleTable (station);
715  }
716 }
717 
718 void
720 {
721  NS_LOG_FUNCTION (this << st << rxSnr << txMode);
722  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelWifiRemoteStation *)st)->m_txrate);
723 }
724 
725 void
727 {
728  NS_LOG_FUNCTION (this << st);
730  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
731  station->m_shortRetry++;
732 }
733 
734 void
735 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
736 {
737  NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode << rtsSnr);
738 }
739 
740 void
742 {
743  NS_LOG_FUNCTION (this << st);
745  UpdateRetry (station);
746 }
747 
748 void
750 {
751  NS_LOG_FUNCTION (this << st);
753  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
754  CheckInit (station);
755  if (!station->m_initialized)
756  {
757  return;
758  }
759 
760  UpdateRate (station);
761 }
762 
763 void
765  double ackSnr, WifiMode ackMode, double dataSnr)
766 {
767  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
769 
770  CheckInit (station);
771  if (!station->m_initialized)
772  {
773  return;
774  }
775 
776  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).");
777 
778  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
779  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
780 
781  UpdatePacketCounters (station);
782 
783  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).");
784 
785  UpdateRetry (station);
786  UpdateStats (station);
787 
788  if (station->m_nModes >= 1)
789  {
790  station->m_txrate = FindRate (station);
791  }
792  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
793 }
794 
795 void
797 {
798  NS_LOG_FUNCTION (this << st);
800 
801  CheckInit (station);
802  if (!station->m_initialized)
803  {
804  return;
805  }
806 
807  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).");
808 
809  UpdatePacketCounters (station);
810 
811  UpdateRetry (station);
812  UpdateStats (station);
813 
814  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).");
815 
816  if (station->m_nModes >= 1)
817  {
818  station->m_txrate = FindRate (station);
819  }
820  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
821 }
822 
823 void
825 {
826  NS_LOG_FUNCTION (this << station);
827 
828  station->m_totalPacketsCount++;
829  // If it is a sampling frame and the sampleRate was used, increase counter
830  if (station->m_isSampling && (!station->m_sampleDeferred || station->m_longRetry >= station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
831  {
832  station->m_samplePacketsCount++;
833  }
834 
835  if (station->m_numSamplesDeferred > 0)
836  {
837  station->m_numSamplesDeferred--;
838  }
839 
840  if (station->m_totalPacketsCount == ~0)
841  {
842  station->m_numSamplesDeferred = 0;
843  station->m_samplePacketsCount = 0;
844  station->m_totalPacketsCount = 0;
845  }
846  station->m_isSampling = false;
847  station->m_sampleDeferred = false;
848 }
849 
850 void
852 {
853  NS_LOG_FUNCTION (this << station);
854  station->m_retry = station->m_shortRetry + station->m_longRetry;
855  station->m_shortRetry = 0;
856  station->m_longRetry = 0;
857 }
858 
861 {
862  NS_LOG_FUNCTION (this << st);
864  return GetDataTxVector (station);
865 }
866 
869 {
870  NS_LOG_FUNCTION (this << st);
872  return GetRtsTxVector (station);
873 }
874 
875 bool
877 {
878  NS_LOG_FUNCTION (this << st << packet << normally);
880 
881  CheckInit (station);
882  if (!station->m_initialized)
883  {
884  return normally;
885  }
886  if (station->m_longRetry >= CountRetries (station))
887  {
888  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
889  return false;
890  }
891  else
892  {
893  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
894  return true;
895  }
896 }
897 
898 bool
900 {
901  return true;
902 }
903 
904 uint16_t
906 {
907  NS_LOG_FUNCTION (this << station);
908  uint16_t bitrate;
909  bitrate = station->m_sampleTable[station->m_index][station->m_col];
910  station->m_index++;
911 
912  //bookkeeping for m_index and m_col variables
913  NS_ABORT_MSG_IF (station->m_nModes < 2, "Integer overflow detected");
914  if (station->m_index > station->m_nModes - 2)
915  {
916  station->m_index = 0;
917  station->m_col++;
918  if (station->m_col >= m_sampleCol)
919  {
920  station->m_col = 0;
921  }
922  }
923  return bitrate;
924 }
925 
926 void
928 {
929  NS_LOG_FUNCTION (this << station);
930  for (uint8_t i = 0; i < station->m_nModes; i++)
931  {
932  NS_LOG_DEBUG ("Initializing rate index " << +i << " " << GetSupported (station, i));
933  station->m_minstrelTable[i].numRateAttempt = 0;
934  station->m_minstrelTable[i].numRateSuccess = 0;
935  station->m_minstrelTable[i].prevNumRateSuccess = 0;
936  station->m_minstrelTable[i].prevNumRateAttempt = 0;
937  station->m_minstrelTable[i].successHist = 0;
938  station->m_minstrelTable[i].attemptHist = 0;
939  station->m_minstrelTable[i].numSamplesSkipped = 0;
940  station->m_minstrelTable[i].prob = 0;
941  station->m_minstrelTable[i].ewmaProb = 0;
942  station->m_minstrelTable[i].throughput = 0;
943  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
944  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
945  station->m_minstrelTable[i].retryCount = 1;
946  station->m_minstrelTable[i].adjustedRetryCount = 1;
947  //Emulating minstrel.c::ath_rate_ctl_reset
948  //We only check from 2 to 10 retries. This guarantee that
949  //at least one retry is permitter.
950  Time totalTxTimeWithGivenRetries = Seconds (0.0); //tx_time in minstrel.c
951  NS_LOG_DEBUG (" Calculating the number of retries");
952  for (uint32_t retries = 2; retries < 11; retries++)
953  {
954  NS_LOG_DEBUG (" Checking " << retries << " retries");
955  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
956  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
957  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
958  {
959  break;
960  }
961  station->m_minstrelTable[i].sampleLimit = -1;
962  station->m_minstrelTable[i].retryCount = retries;
963  station->m_minstrelTable[i].adjustedRetryCount = retries;
964  }
965  }
966  UpdateStats (station);
967 }
968 
969 Time
970 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
971 {
972  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
973  //See rc80211_minstrel.c
974 
975  //First transmission (DATA + ACK timeout)
976  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
977 
978  uint32_t cwMax = 1023;
979  uint32_t cw = 31;
980  for (uint32_t retry = 0; retry < longRetries; retry++)
981  {
982  //Add one re-transmission (DATA + ACK timeout)
983  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
984 
985  //Add average back off (half the current contention window)
986  tt += (cw / 2.0) * GetMac ()->GetSlot ();
987 
988  //Update contention window
989  cw = std::min (cwMax, (cw + 1) * 2);
990  }
991 
992  return tt;
993 }
994 
995 void
997 {
998  NS_LOG_FUNCTION (this << station);
999  station->m_col = station->m_index = 0;
1000 
1001  //for off-setting to make rates fall between 0 and nModes
1002  uint8_t numSampleRates = station->m_nModes;
1003 
1004  uint16_t newIndex;
1005  for (uint8_t col = 0; col < m_sampleCol; col++)
1006  {
1007  for (uint8_t i = 0; i < numSampleRates; i++ )
1008  {
1013  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
1014  NS_LOG_DEBUG ("InitSampleTable uv: " << uv);
1015  newIndex = (i + uv) % numSampleRates;
1016 
1017  //this loop is used for filling in other uninitialized places
1018  while (station->m_sampleTable[newIndex][col] != 0)
1019  {
1020  newIndex = (newIndex + 1) % station->m_nModes;
1021  }
1022  station->m_sampleTable[newIndex][col] = i;
1023  }
1024  }
1025 }
1026 
1027 void
1029 {
1030  uint8_t numSampleRates = station->m_nModes;
1031  std::stringstream table;
1032  for (uint8_t i = 0; i < numSampleRates; i++)
1033  {
1034  for (uint8_t j = 0; j < m_sampleCol; j++)
1035  {
1036  table << station->m_sampleTable[i][j] << "\t";
1037  }
1038  table << std::endl;
1039  }
1040  NS_LOG_DEBUG (table.str ());
1041 }
1042 
1043 void
1045 {
1046  station->m_statsFile << "best _______________rate________________ ________statistics________ ________last_______ ______sum-of________\n" <<
1047  "rate [ name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1048 
1049  uint16_t maxTpRate = station->m_maxTpRate;
1050  uint16_t maxTpRate2 = station->m_maxTpRate2;
1051  uint16_t maxProbRate = station->m_maxProbRate;
1052 
1053  for (uint8_t i = 0; i < station->m_nModes; i++)
1054  {
1055  RateInfo rate = station->m_minstrelTable[i];
1056 
1057  if (i == maxTpRate)
1058  {
1059  station->m_statsFile << 'A';
1060  }
1061  else
1062  {
1063  station->m_statsFile << ' ';
1064  }
1065  if (i == maxTpRate2)
1066  {
1067  station->m_statsFile << 'B';
1068  }
1069  else
1070  {
1071  station->m_statsFile << ' ';
1072  }
1073  if (i == maxProbRate)
1074  {
1075  station->m_statsFile << 'P';
1076  }
1077  else
1078  {
1079  station->m_statsFile << ' ';
1080  }
1081 
1082  float tmpTh = rate.throughput / 100000.0f;
1083  station->m_statsFile << " " <<
1084  std::setw (17) << GetSupported (station, i) << " " <<
1085  std::setw (2) << i << " " <<
1086  std::setw (4) << rate.perfectTxTime.GetMicroSeconds () <<
1087  std::setw (8) << " ----- " <<
1088  std::setw (8) << tmpTh << " " <<
1089  std::setw (3) << rate.ewmaProb / 180 <<
1090  std::setw (3) << " --- " <<
1091  std::setw (3) << rate.prob / 180 << " " <<
1092  std::setw (1) << rate.adjustedRetryCount << " " <<
1093  std::setw (3) << rate.prevNumRateSuccess << " " <<
1094  std::setw (3) << rate.prevNumRateAttempt << " " <<
1095  std::setw (9) << rate.successHist << " " <<
1096  std::setw (9) << rate.attemptHist << "\n";
1097  }
1098  station->m_statsFile << "\nTotal packet count: ideal " << station->m_totalPacketsCount - station->m_samplePacketsCount
1099  << " lookaround " << station->m_samplePacketsCount << "\n\n";
1100 
1101  station->m_statsFile.flush ();
1102 }
1103 
1104 } //namespace ns3
void CheckInit(MinstrelWifiRemoteStation *station)
check for initializations
void PrintTable(MinstrelWifiRemoteStation *station)
printing Minstrel Table
uint16_t m_maxProbRate
rate with highest prob of success
WifiTxVector DoGetDataTxVector(WifiRemoteStation *station)
void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Ptr< WifiMac > GetMac(void) const
Return the WifiMac.
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
#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 the RngStream.
uint8_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
bool m_printStats
whether statistics table should be printed.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
uint8_t m_lookAroundRate
the % to try other rates than our current rate
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time perfectTxTime
Perfect transmission time calculation, or frame calculation Given a bit rate and a packet length n by...
#define min(a, b)
Definition: 80211b.c:42
Implementation of Minstrel Rate Control AlgorithmMinstrel is a rate control algorithm implemented in ...
uint16_t m_maxTpRate
the current throughput rate
uint16_t m_txrate
current transmit rate
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:84
uint16_t m_maxTpRate2
second highest throughput rate
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
bool GetHeSupported(void) const
Return whether the device has HE capability support enabled.
#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:204
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
uint16_t m_sampleRate
current sample rate
Mac48Address m_address
Mac48Address of the remote station.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
MinstrelRate m_minstrelTable
minstrel table
std::ofstream m_statsFile
stats file
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble, bool useGreenfield)
Return the preamble to be used for the transmission.
Definition: wifi-utils.cc:128
WifiMode GetSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether mode associated with the specified station at the specified index. ...
bool m_sampleDeferred
a flag to indicate sample rate is on the second stage
std::vector< std::vector< uint8_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint8_t.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
std::vector< RateInfo > MinstrelRate
Data structure for a Minstrel Rate table A vector of a struct RateInfo.
TracedValue< uint64_t > m_currentRate
Trace rate changes.
uint8_t m_nModes
number of modes supported
uint32_t m_pktLen
packet length used for calculate mode TxTime
WifiRemoteStationState * m_state
Remote station state.
uint32_t adjustedRetryCount
adjust the retry limit for this rate
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
phy
Definition: third.py:86
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
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.
void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode)
This method is a pure virtual method that must be implemented by the sub-class.
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PLCP preambles.
A struct to contain all information related to a data rate.
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
bool m_isSampling
a flag to indicate we are currently sampling
int m_numSamplesDeferred
number samles deferred
AttributeValue implementation for Time.
Definition: nstime.h:1124
SampleRate m_sampleTable
sample table
uint8_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
uint32_t prevNumRateSuccess
Number of successful frames transmitted with previous rate.
Hold an unsigned integer type.
Definition: uinteger.h:44
uint16_t GetNextSample(MinstrelWifiRemoteStation *station)
getting the next sample from Sample Table
void PrintSampleTable(MinstrelWifiRemoteStation *station)
printing Sample Table
bool GetHtSupported(void) const
Return whether the device has HT capability support enabled.
mac
Definition: third.py:92
uint32_t prevNumRateAttempt
Number of transmission attempts with previous rate.
uint64_t attemptHist
Aggregate of all transmission attempts.
uint64_t successHist
Aggregate of all transmission successes.
void AddCalcTxTime(WifiMode mode, Time t)
Add transmission time for the given mode to an internal list.
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
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.
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:494
WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)
uint32_t m_longRetry
long retries such as data packets
uint16_t FindRate(MinstrelWifiRemoteStation *station)
find a rate to use from Minstrel Table
bool m_initialized
for initializing tables
uint32_t ewmaProb
EWMA calculation ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100.
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:363
TxTime m_calcTxTime
to hold all the calculated TxTime for all modes
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.
void UpdateRate(MinstrelWifiRemoteStation *station)
updating the rate
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
WifiTxVector GetDataTxVector(MinstrelWifiRemoteStation *station)
Get data transmit vector.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
bool UseGreenfieldForDestination(Mac48Address dest) const
bool DoNeedRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally)
Mac48Address GetAddress(const WifiRemoteStation *station) const
Return the address of the station.
WifiMode GetNonErpSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether non-ERP mode associated with the specified station at the specified index...
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:1125
uint32_t throughput
throughput of a rate
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:193
uint32_t m_retry
total retries short + long
int m_totalPacketsCount
total number of packets as of now
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
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
int m_samplePacketsCount
how many packets we have sample so far
static TypeId GetTypeId(void)
Get the type ID.
void InitSampleTable(MinstrelWifiRemoteStation *station)
initialize Sample Table
virtual void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
if(desigRtr==addrLocal)
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
void DoReportRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
WifiTxVector GetRtsTxVector(MinstrelWifiRemoteStation *station)
Get RTS transmit vector.
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:272
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
uint32_t CountRetries(MinstrelWifiRemoteStation *station)
Count retries.
void DoReportDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
void DoInitialize(void)
Initialize() implementation.
bool m_printSamples
whether samples table should be printed.
uint32_t m_shortRetry
short retries such as control packts
WifiRemoteStation * DoCreateStation(void) const
uint8_t m_sampleCol
number of sample columns
Time GetCalcTxTime(WifiMode mode) const
for estimating the TxTime of a packet with a given mode
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
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:58
uint8_t m_ewmaLevel
exponential weighted moving average
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)
Set the parent TypeId.
Definition: type-id.cc:915
hold per-remote-station state.
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:150
uint32_t prob
(# pkts success )/(# total pkts)
uint16_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
void UpdatePacketCounters(MinstrelWifiRemoteStation *station)
Update packet counters.
Time m_nextStatsUpdate
10 times every second