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 int64_t
137 {
138  NS_LOG_FUNCTION (this << stream);
140  return 1;
141 }
142 
143 Time
145 {
146  NS_LOG_FUNCTION (this << mode);
147  auto it = m_calcTxTime.find (mode);
148  NS_ASSERT (it != m_calcTxTime.end ());
149  return it->second;
150 }
151 
152 void
154 {
155  NS_LOG_FUNCTION (this << mode << t);
156  m_calcTxTime.insert (std::make_pair (mode, t));
157 }
158 
161 {
162  NS_LOG_FUNCTION (this);
164 
166  station->m_col = 0;
167  station->m_index = 0;
168  station->m_maxTpRate = 0;
169  station->m_maxTpRate2 = 0;
170  station->m_maxProbRate = 0;
171  station->m_nModes = 0;
172  station->m_totalPacketsCount = 0;
173  station->m_samplePacketsCount = 0;
174  station->m_isSampling = false;
175  station->m_sampleRate = 0;
176  station->m_sampleDeferred = false;
177  station->m_shortRetry = 0;
178  station->m_longRetry = 0;
179  station->m_retry = 0;
180  station->m_txrate = 0;
181  station->m_initialized = false;
182 
183  return station;
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION (this << station);
190  if (!station->m_initialized && GetNSupported (station) > 1)
191  {
192  //Note: we appear to be doing late initialization of the table
193  //to make sure that the set of supported rates has been initialized
194  //before we perform our own initialization.
195  station->m_nModes = GetNSupported (station);
196  station->m_minstrelTable = MinstrelRate (station->m_nModes);
197  station->m_sampleTable = SampleRate (station->m_nModes, std::vector<uint8_t> (m_sampleCol));
198  InitSampleTable (station);
199  RateInit (station);
200  station->m_initialized = true;
201  std::ostringstream tmp;
202  tmp << "minstrel-stats-" << station->m_state->m_address << ".txt";
203  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
204  }
205 }
206 
222 void
224 {
225  NS_LOG_FUNCTION (this << station);
226  station->m_longRetry++;
227  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
228 
229  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
230 
231  //for normal rate, we're not currently sampling random rates
232  if (!station->m_isSampling)
233  {
234  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);
235  //use best throughput rate
236  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
237  {
238  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
239  station->m_txrate = station->m_maxTpRate;
240  }
241 
242  //use second best throughput rate
243  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
244  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
245  {
246  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
247  station->m_txrate = station->m_maxTpRate2;
248  }
249 
250  //use best probability rate
251  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
252  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
253  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
254  {
255  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
256  station->m_txrate = station->m_maxProbRate;
257  }
258 
259  //use lowest base rate
260  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
261  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
262  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
263  {
264  NS_LOG_DEBUG (" More retries left for the base rate.");
265  station->m_txrate = 0;
266  }
267  }
268 
269  //for look-around rate, we're currently sampling random rates
270  else
271  {
272  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);
273  //current sampling rate is slower than the current best rate
274  if (station->m_sampleDeferred)
275  {
276  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
277  //use best throughput rate
278  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
279  {
280  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
281  station->m_txrate = station->m_maxTpRate;
282  }
283 
284  //use random rate
285  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
286  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
287  {
288  NS_LOG_DEBUG (" More retries left for the sampling rate.");
289  station->m_txrate = station->m_sampleRate;
290  }
291 
292  //use max probability rate
293  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
294  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
295  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
296  {
297  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
298  station->m_txrate = station->m_maxProbRate;
299  }
300 
301  //use lowest base rate
302  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
303  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
304  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
305  {
306  NS_LOG_DEBUG (" More retries left for the base rate.");
307  station->m_txrate = 0;
308  }
309  }
310  //current sampling rate is better than current best rate
311  else
312  {
313  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
314  //use random rate
315  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
316  {
317  NS_LOG_DEBUG (" More retries left for the sampling rate.");
318  station->m_txrate = station->m_sampleRate;
319  }
320 
321  //use the best throughput rate
322  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
323  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
324  {
325  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
326  station->m_txrate = station->m_maxTpRate;
327  }
328 
329  //use the best probability rate
330  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
331  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
332  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
333  {
334  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
335  station->m_txrate = station->m_maxProbRate;
336  }
337 
338  //use the lowest base rate
339  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
340  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
341  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
342  {
343  NS_LOG_DEBUG (" More retries left for the base rate.");
344  station->m_txrate = 0;
345  }
346  }
347  }
348 }
349 
352 {
353  NS_LOG_FUNCTION (this << station);
354  uint16_t channelWidth = GetChannelWidth (station);
355  if (channelWidth > 20 && channelWidth != 22)
356  {
357  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
358  channelWidth = 20;
359  }
360  if (!station->m_initialized)
361  {
362  CheckInit (station);
363  }
364  WifiMode mode = GetSupported (station, station->m_txrate);
365  if (m_currentRate != mode.GetDataRate (channelWidth) && !station->m_isSampling)
366  {
367  NS_LOG_DEBUG ("New datarate: " << mode.GetDataRate (channelWidth));
368  m_currentRate = mode.GetDataRate (channelWidth);
369  }
370  return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
371 }
372 
375 {
376  NS_LOG_FUNCTION (this << station);
377  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
378  uint16_t channelWidth = GetChannelWidth (station);
379  if (channelWidth > 20 && channelWidth != 22)
380  {
381  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
382  channelWidth = 20;
383  }
384  WifiTxVector rtsTxVector;
385  WifiMode mode;
386  if (GetUseNonErpProtection () == false)
387  {
388  mode = GetSupported (station, 0);
389  }
390  else
391  {
392  mode = GetNonErpSupported (station, 0);
393  }
394  rtsTxVector = WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
395  return rtsTxVector;
396 }
397 
398 uint32_t
400 {
401  if (!station->m_isSampling)
402  {
403  return station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
404  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
405  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
406  station->m_minstrelTable[0].adjustedRetryCount;
407  }
408  else
409  {
410  return station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
411  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
412  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
413  station->m_minstrelTable[0].adjustedRetryCount;
414  }
415 }
416 
417 uint16_t
419 {
420  NS_LOG_FUNCTION (this << station);
421 
422  if (station->m_totalPacketsCount == 0)
423  {
424  return 0;
425  }
426 
427  uint16_t idx = 0;
428  NS_LOG_DEBUG ("Total: " << station->m_totalPacketsCount << " Sample: " << station->m_samplePacketsCount << " Deferred: " << station->m_numSamplesDeferred);
429 
430  int delta = (station->m_totalPacketsCount * m_lookAroundRate / 100) - (station->m_samplePacketsCount + station->m_numSamplesDeferred / 2);
431 
432  NS_LOG_DEBUG ("Decide sampling. Delta: " << delta << " lookAroundRatio: " << m_lookAroundRate);
433 
434  /* delta < 0: no sampling required */
435  if (delta >= 0)
436  {
437  NS_LOG_DEBUG ("Search next sampling rate");
438  uint8_t ratesSupported = station->m_nModes;
439  if (delta > ratesSupported * 2)
440  {
441  /* From Linux implementation:
442  * With multi-rate retry, not every planned sample
443  * attempt actually gets used, due to the way the retry
444  * chain is set up - [max_tp,sample,prob,lowest] for
445  * sample_rate < max_tp.
446  *
447  * If there's too much sampling backlog and the link
448  * starts getting worse, minstrel would start bursting
449  * out lots of sampling frames, which would result
450  * in a large throughput loss. */
451  station->m_samplePacketsCount += (delta - ratesSupported * 2);
452  }
453 
454  //now go through the table and find an index rate
455  idx = GetNextSample (station);
456 
457  NS_LOG_DEBUG ("Sample rate = " << idx << "(" << GetSupported (station, idx) << ")");
458 
459  //error check
460  if (idx >= station->m_nModes)
461  {
462  NS_LOG_DEBUG ("ALERT!!! ERROR");
463  }
464 
465  //set the rate that we're currently sampling
466  station->m_sampleRate = idx;
467 
468  /* From Linux implementation:
469  * Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
470  * rate sampling method should be used.
471  * Respect such rates that are not sampled for 20 iterations.
472  */
473  if ((station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime)
474  && (station->m_minstrelTable[idx].numSamplesSkipped < 20))
475  {
476  // If the rate is slower and we have sample it enough, defer to second stage
477  station->m_sampleDeferred = true;
478  station->m_numSamplesDeferred++;
479 
480  //set flag that we are currently sampling
481  station->m_isSampling = true;
482  }
483  else
484  {
485  // if samplieLimit is zero, then don't sample this rate
486  if (!station->m_minstrelTable[idx].sampleLimit)
487  {
488  idx = station->m_maxTpRate;
489  station->m_isSampling = false;
490  }
491  else
492  {
493  //set flag that we are currently sampling
494  station->m_isSampling = true;
495  if (station->m_minstrelTable[idx].sampleLimit > 0)
496  {
497  station->m_minstrelTable[idx].sampleLimit--;
498  }
499  }
500  }
501 
502  //using the best rate instead
503  if (station->m_sampleDeferred)
504  {
505  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) << ")");
506  idx = station->m_maxTpRate;
507  }
508  }
509  //continue using the best rate
510  else
511  {
512  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
513  idx = station->m_maxTpRate;
514  }
515 
516  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
517 
518  return idx;
519 }
520 
521 void
523 {
524  NS_LOG_FUNCTION (this << station);
525  if (Simulator::Now () < station->m_nextStatsUpdate)
526  {
527  return;
528  }
529 
530  if (!station->m_initialized)
531  {
532  return;
533  }
534  NS_LOG_FUNCTION (this);
536  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
537  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
538 
539  Time txTime;
540  uint32_t tempProb;
541 
542  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
543  for (uint8_t i = 0; i < station->m_nModes; i++)
544  {
545 
546  //calculate the perfect tx time for this rate
547  txTime = station->m_minstrelTable[i].perfectTxTime;
548 
549  //just for initialization
550  if (txTime.GetMicroSeconds () == 0)
551  {
552  txTime = Seconds (1);
553  }
554 
555  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
556  "\t" << station->m_minstrelTable[i].numRateAttempt <<
557  "\t" << station->m_minstrelTable[i].numRateSuccess);
558 
559  //if we've attempted something
560  if (station->m_minstrelTable[i].numRateAttempt)
561  {
562  station->m_minstrelTable[i].numSamplesSkipped = 0;
567  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
568 
569  //bookkeeping
570  station->m_minstrelTable[i].prob = tempProb;
571 
572  if (station->m_minstrelTable[i].successHist == 0)
573  {
574  station->m_minstrelTable[i].ewmaProb = tempProb;
575  }
576  else
577  {
578  //ewma probability (cast for gcc 3.4 compatibility)
579  tempProb = ((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100;
580 
581  station->m_minstrelTable[i].ewmaProb = tempProb;
582  }
583 
584  //calculating throughput
585  station->m_minstrelTable[i].throughput = tempProb * static_cast<uint32_t> ((1000000 / txTime.GetMicroSeconds ()));
586  }
587  else
588  {
589  station->m_minstrelTable[i].numSamplesSkipped++;
590  }
591 
592  //bookkeeping
593  station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess;
594  station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt;
595  station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess;
596  station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt;
597  station->m_minstrelTable[i].numRateSuccess = 0;
598  station->m_minstrelTable[i].numRateAttempt = 0;
599 
600  //Sample less often below 10% and above 95% of success
601  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
602  {
610  if (station->m_minstrelTable[i].retryCount > 2)
611  {
612  station->m_minstrelTable[i].adjustedRetryCount = 2;
613  }
614  station->m_minstrelTable[i].sampleLimit = 4;
615  }
616  else
617  {
618  // no sampling limit.
619  station->m_minstrelTable[i].sampleLimit = -1;
620  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
621  }
622 
623  //if it's 0 allow two retries.
624  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
625  {
626  station->m_minstrelTable[i].adjustedRetryCount = 2;
627  }
628  }
629 
630  NS_LOG_DEBUG ("Attempt/success reset to 0");
631 
632  uint32_t max_tp = 0;
633  uint8_t index_max_tp = 0, index_max_tp2 = 0;
634 
635  //go find max throughput, second maximum throughput, high probability succ
636  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
637  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
638  for (uint8_t i = 0; i < station->m_nModes; i++)
639  {
640  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
641  "\t" << station->m_minstrelTable[i].throughput <<
642  "\t" << station->m_minstrelTable[i].ewmaProb);
643 
644  if (max_tp < station->m_minstrelTable[i].throughput)
645  {
646  index_max_tp = i;
647  max_tp = station->m_minstrelTable[i].throughput;
648  }
649  }
650 
651  max_tp = 0;
652  //find the second highest max
653  for (uint8_t i = 0; i < station->m_nModes; i++)
654  {
655  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
656  {
657  index_max_tp2 = i;
658  max_tp = station->m_minstrelTable[i].throughput;
659  }
660  }
661 
662  uint32_t max_prob = 0;
663  uint8_t index_max_prob = 0;
664  for (uint8_t i = 0; i < station->m_nModes; i++)
665  {
666  if ((station->m_minstrelTable[i].ewmaProb >= 95 * 180) && (station->m_minstrelTable[i].throughput >= station->m_minstrelTable[index_max_prob].throughput))
667  {
668  index_max_prob = i;
669  max_prob = station->m_minstrelTable[i].ewmaProb;
670  }
671  else if (station->m_minstrelTable[i].ewmaProb >= max_prob)
672  {
673  index_max_prob = i;
674  max_prob = station->m_minstrelTable[i].ewmaProb;
675  }
676  }
677 
678  station->m_maxTpRate = index_max_tp;
679  station->m_maxTpRate2 = index_max_tp2;
680  station->m_maxProbRate = index_max_prob;
681 
682  if (index_max_tp > station->m_txrate)
683  {
684  station->m_txrate = index_max_tp;
685  }
686 
687  NS_LOG_DEBUG ("max throughput=" << +index_max_tp << "(" << GetSupported (station, index_max_tp) <<
688  ")\tsecond max throughput=" << +index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
689  ")\tmax prob=" << +index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
690  if (m_printStats)
691  {
692  PrintTable (station);
693  }
694  if (m_printSamples)
695  {
696  PrintSampleTable (station);
697  }
698 }
699 
700 void
702 {
703  NS_LOG_FUNCTION (this << st << rxSnr << txMode);
704  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelWifiRemoteStation *)st)->m_txrate);
705 }
706 
707 void
709 {
710  NS_LOG_FUNCTION (this << st);
712  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
713  station->m_shortRetry++;
714 }
715 
716 void
717 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
718 {
719  NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode << rtsSnr);
720 }
721 
722 void
724 {
725  NS_LOG_FUNCTION (this << st);
727  UpdateRetry (station);
728 }
729 
730 void
732 {
733  NS_LOG_FUNCTION (this << st);
735  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
736  CheckInit (station);
737  if (!station->m_initialized)
738  {
739  return;
740  }
741 
742  UpdateRate (station);
743 }
744 
745 void
747  double ackSnr, WifiMode ackMode, double dataSnr)
748 {
749  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
751 
752  CheckInit (station);
753  if (!station->m_initialized)
754  {
755  return;
756  }
757 
758  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).");
759 
760  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
761  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
762 
763  UpdatePacketCounters (station);
764 
765  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).");
766 
767  UpdateRetry (station);
768  UpdateStats (station);
769 
770  if (station->m_nModes >= 1)
771  {
772  station->m_txrate = FindRate (station);
773  }
774  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
775 }
776 
777 void
779 {
780  NS_LOG_FUNCTION (this << st);
782 
783  CheckInit (station);
784  if (!station->m_initialized)
785  {
786  return;
787  }
788 
789  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).");
790 
791  UpdatePacketCounters (station);
792 
793  UpdateRetry (station);
794  UpdateStats (station);
795 
796  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).");
797 
798  if (station->m_nModes >= 1)
799  {
800  station->m_txrate = FindRate (station);
801  }
802  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
803 }
804 
805 void
807 {
808  NS_LOG_FUNCTION (this << station);
809 
810  station->m_totalPacketsCount++;
811  // If it is a sampling frame and the sampleRate was used, increase counter
812  if (station->m_isSampling && (!station->m_sampleDeferred || station->m_longRetry >= station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
813  {
814  station->m_samplePacketsCount++;
815  }
816 
817  if (station->m_numSamplesDeferred > 0)
818  {
819  station->m_numSamplesDeferred--;
820  }
821 
822  if (station->m_totalPacketsCount == ~0)
823  {
824  station->m_numSamplesDeferred = 0;
825  station->m_samplePacketsCount = 0;
826  station->m_totalPacketsCount = 0;
827  }
828  station->m_isSampling = false;
829  station->m_sampleDeferred = false;
830 }
831 
832 void
834 {
835  NS_LOG_FUNCTION (this << station);
836  station->m_retry = station->m_shortRetry + station->m_longRetry;
837  station->m_shortRetry = 0;
838  station->m_longRetry = 0;
839 }
840 
843 {
844  NS_LOG_FUNCTION (this << st);
846  return GetDataTxVector (station);
847 }
848 
851 {
852  NS_LOG_FUNCTION (this << st);
854  return GetRtsTxVector (station);
855 }
856 
857 bool
859 {
860  NS_LOG_FUNCTION (this << st << packet << normally);
862 
863  CheckInit (station);
864  if (!station->m_initialized)
865  {
866  return normally;
867  }
868  if (station->m_longRetry >= CountRetries (station))
869  {
870  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
871  return false;
872  }
873  else
874  {
875  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
876  return true;
877  }
878 }
879 
880 bool
882 {
883  return true;
884 }
885 
886 uint16_t
888 {
889  NS_LOG_FUNCTION (this << station);
890  uint16_t bitrate;
891  bitrate = station->m_sampleTable[station->m_index][station->m_col];
892  station->m_index++;
893 
894  //bookkeeping for m_index and m_col variables
895  NS_ABORT_MSG_IF (station->m_nModes < 2, "Integer overflow detected");
896  if (station->m_index > station->m_nModes - 2)
897  {
898  station->m_index = 0;
899  station->m_col++;
900  if (station->m_col >= m_sampleCol)
901  {
902  station->m_col = 0;
903  }
904  }
905  return bitrate;
906 }
907 
908 void
910 {
911  NS_LOG_FUNCTION (this << station);
912  for (uint8_t i = 0; i < station->m_nModes; i++)
913  {
914  NS_LOG_DEBUG ("Initializing rate index " << +i << " " << GetSupported (station, i));
915  station->m_minstrelTable[i].numRateAttempt = 0;
916  station->m_minstrelTable[i].numRateSuccess = 0;
917  station->m_minstrelTable[i].prevNumRateSuccess = 0;
918  station->m_minstrelTable[i].prevNumRateAttempt = 0;
919  station->m_minstrelTable[i].successHist = 0;
920  station->m_minstrelTable[i].attemptHist = 0;
921  station->m_minstrelTable[i].numSamplesSkipped = 0;
922  station->m_minstrelTable[i].prob = 0;
923  station->m_minstrelTable[i].ewmaProb = 0;
924  station->m_minstrelTable[i].throughput = 0;
925  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
926  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
927  station->m_minstrelTable[i].retryCount = 1;
928  station->m_minstrelTable[i].adjustedRetryCount = 1;
929  //Emulating minstrel.c::ath_rate_ctl_reset
930  //We only check from 2 to 10 retries. This guarantee that
931  //at least one retry is permitter.
932  Time totalTxTimeWithGivenRetries = Seconds (0.0); //tx_time in minstrel.c
933  NS_LOG_DEBUG (" Calculating the number of retries");
934  for (uint32_t retries = 2; retries < 11; retries++)
935  {
936  NS_LOG_DEBUG (" Checking " << retries << " retries");
937  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
938  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
939  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
940  {
941  break;
942  }
943  station->m_minstrelTable[i].sampleLimit = -1;
944  station->m_minstrelTable[i].retryCount = retries;
945  station->m_minstrelTable[i].adjustedRetryCount = retries;
946  }
947  }
948  UpdateStats (station);
949 }
950 
951 Time
952 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
953 {
954  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
955  //See rc80211_minstrel.c
956 
957  //First transmission (DATA + ACK timeout)
958  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
959 
960  uint32_t cwMax = 1023;
961  uint32_t cw = 31;
962  for (uint32_t retry = 0; retry < longRetries; retry++)
963  {
964  //Add one re-transmission (DATA + ACK timeout)
965  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
966 
967  //Add average back off (half the current contention window)
968  tt += NanoSeconds ((cw / 2) * GetMac ()->GetSlot ());
969 
970  //Update contention window
971  cw = std::min (cwMax, (cw + 1) * 2);
972  }
973 
974  return tt;
975 }
976 
977 void
979 {
980  NS_LOG_FUNCTION (this << station);
981  station->m_col = station->m_index = 0;
982 
983  //for off-setting to make rates fall between 0 and nModes
984  uint8_t numSampleRates = station->m_nModes;
985 
986  uint16_t newIndex;
987  for (uint8_t col = 0; col < m_sampleCol; col++)
988  {
989  for (uint8_t i = 0; i < numSampleRates; i++ )
990  {
995  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
996  NS_LOG_DEBUG ("InitSampleTable uv: " << uv);
997  newIndex = (i + uv) % numSampleRates;
998 
999  //this loop is used for filling in other uninitialized places
1000  while (station->m_sampleTable[newIndex][col] != 0)
1001  {
1002  newIndex = (newIndex + 1) % station->m_nModes;
1003  }
1004  station->m_sampleTable[newIndex][col] = i;
1005  }
1006  }
1007 }
1008 
1009 void
1011 {
1012  uint8_t numSampleRates = station->m_nModes;
1013  std::stringstream table;
1014  for (uint8_t i = 0; i < numSampleRates; i++)
1015  {
1016  for (uint8_t j = 0; j < m_sampleCol; j++)
1017  {
1018  table << station->m_sampleTable[i][j] << "\t";
1019  }
1020  table << std::endl;
1021  }
1022  NS_LOG_DEBUG (table.str ());
1023 }
1024 
1025 void
1027 {
1028  station->m_statsFile << "best _______________rate________________ ________statistics________ ________last_______ ______sum-of________\n" <<
1029  "rate [ name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1030 
1031  uint16_t maxTpRate = station->m_maxTpRate;
1032  uint16_t maxTpRate2 = station->m_maxTpRate2;
1033  uint16_t maxProbRate = station->m_maxProbRate;
1034 
1035  for (uint8_t i = 0; i < station->m_nModes; i++)
1036  {
1037  RateInfo rate = station->m_minstrelTable[i];
1038 
1039  if (i == maxTpRate)
1040  {
1041  station->m_statsFile << 'A';
1042  }
1043  else
1044  {
1045  station->m_statsFile << ' ';
1046  }
1047  if (i == maxTpRate2)
1048  {
1049  station->m_statsFile << 'B';
1050  }
1051  else
1052  {
1053  station->m_statsFile << ' ';
1054  }
1055  if (i == maxProbRate)
1056  {
1057  station->m_statsFile << 'P';
1058  }
1059  else
1060  {
1061  station->m_statsFile << ' ';
1062  }
1063 
1064  float tmpTh = rate.throughput / 100000.0f;
1065  station->m_statsFile << " " <<
1066  std::setw (17) << GetSupported (station, i) << " " <<
1067  std::setw (2) << i << " " <<
1068  std::setw (4) << rate.perfectTxTime.GetMicroSeconds () <<
1069  std::setw (8) << " ----- " <<
1070  std::setw (8) << tmpTh << " " <<
1071  std::setw (3) << rate.ewmaProb / 180 <<
1072  std::setw (3) << " --- " <<
1073  std::setw (3) << rate.prob / 180 << " " <<
1074  std::setw (1) << rate.adjustedRetryCount << " " <<
1075  std::setw (3) << rate.prevNumRateSuccess << " " <<
1076  std::setw (3) << rate.prevNumRateAttempt << " " <<
1077  std::setw (9) << rate.successHist << " " <<
1078  std::setw (9) << rate.attemptHist << "\n";
1079  }
1080  station->m_statsFile << "\nTotal packet count: ideal " << station->m_totalPacketsCount - station->m_samplePacketsCount
1081  << " lookaround " << station->m_samplePacketsCount << "\n\n";
1082 
1083  station->m_statsFile.flush ();
1084 }
1085 
1086 void
1088 {
1089  //HT is not supported by this algorithm.
1090  if (enable)
1091  {
1092  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
1093  }
1094 }
1095 
1096 void
1098 {
1099  //VHT is not supported by this algorithm.
1100  if (enable)
1101  {
1102  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
1103  }
1104 }
1105 
1106 void
1108 {
1109  //HE is not supported by this algorithm.
1110  if (enable)
1111  {
1112  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
1113  }
1114 }
1115 
1116 } //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.
#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
#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:202
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1022
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
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.
void SetHeSupported(bool enable)
Enable or disable HE capability support.
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.
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
void SetHtSupported(bool enable)
Enable or disable HT capability support.
AttributeValue implementation for Time.
Definition: nstime.h:1076
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...
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1038
uint32_t prevNumRateSuccess
Number of successful frames transmitted with previous rate.
Hold an unsigned integer type.
Definition: uinteger.h:44
WifiPreamble GetPreambleForTransmission(WifiMode mode, Mac48Address dest)
Return the preamble to be used for the transmission.
uint16_t GetNextSample(MinstrelWifiRemoteStation *station)
getting the next sample from Sample Table
void PrintSampleTable(MinstrelWifiRemoteStation *station)
printing Sample Table
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.
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 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:1077
uint32_t throughput
throughput of a rate
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
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.
void SetVhtSupported(bool enable)
Enable or disable VHT capability support.
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:270
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
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.
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:156
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