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 uint8_t
419 {
420  NS_LOG_FUNCTION (this << station);
421 
422  if (station->m_totalPacketsCount == 0)
423  {
424  return 0;
425  }
426 
427  uint8_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 uint8_t
888 {
889  NS_LOG_FUNCTION (this << station);
890  uint8_t bitrate = station->m_sampleTable[station->m_index][station->m_col];
891  station->m_index++;
892 
893  //bookkeeping for m_index and m_col variables
894  NS_ABORT_MSG_IF (station->m_nModes < 2, "Integer overflow detected");
895  if (station->m_index > station->m_nModes - 2)
896  {
897  station->m_index = 0;
898  station->m_col++;
899  if (station->m_col >= m_sampleCol)
900  {
901  station->m_col = 0;
902  }
903  }
904  return bitrate;
905 }
906 
907 void
909 {
910  NS_LOG_FUNCTION (this << station);
911  for (uint8_t i = 0; i < station->m_nModes; i++)
912  {
913  NS_LOG_DEBUG ("Initializing rate index " << +i << " " << GetSupported (station, i));
914  station->m_minstrelTable[i].numRateAttempt = 0;
915  station->m_minstrelTable[i].numRateSuccess = 0;
916  station->m_minstrelTable[i].prevNumRateSuccess = 0;
917  station->m_minstrelTable[i].prevNumRateAttempt = 0;
918  station->m_minstrelTable[i].successHist = 0;
919  station->m_minstrelTable[i].attemptHist = 0;
920  station->m_minstrelTable[i].numSamplesSkipped = 0;
921  station->m_minstrelTable[i].prob = 0;
922  station->m_minstrelTable[i].ewmaProb = 0;
923  station->m_minstrelTable[i].throughput = 0;
924  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
925  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
926  station->m_minstrelTable[i].retryCount = 1;
927  station->m_minstrelTable[i].adjustedRetryCount = 1;
928  //Emulating minstrel.c::ath_rate_ctl_reset
929  //We only check from 2 to 10 retries. This guarantee that
930  //at least one retry is permitter.
931  Time totalTxTimeWithGivenRetries = Seconds (0.0); //tx_time in minstrel.c
932  NS_LOG_DEBUG (" Calculating the number of retries");
933  for (uint32_t retries = 2; retries < 11; retries++)
934  {
935  NS_LOG_DEBUG (" Checking " << retries << " retries");
936  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
937  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
938  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
939  {
940  break;
941  }
942  station->m_minstrelTable[i].sampleLimit = -1;
943  station->m_minstrelTable[i].retryCount = retries;
944  station->m_minstrelTable[i].adjustedRetryCount = retries;
945  }
946  }
947  UpdateStats (station);
948 }
949 
950 Time
951 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
952 {
953  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
954  //See rc80211_minstrel.c
955 
956  //First transmission (DATA + ACK timeout)
957  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
958 
959  uint32_t cwMax = 1023;
960  uint32_t cw = 31;
961  for (uint32_t retry = 0; retry < longRetries; retry++)
962  {
963  //Add one re-transmission (DATA + ACK timeout)
964  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
965 
966  //Add average back off (half the current contention window)
967  tt += NanoSeconds ((cw / 2) * GetMac ()->GetSlot ());
968 
969  //Update contention window
970  cw = std::min (cwMax, (cw + 1) * 2);
971  }
972 
973  return tt;
974 }
975 
976 void
978 {
979  NS_LOG_FUNCTION (this << station);
980  station->m_col = station->m_index = 0;
981 
982  //for off-setting to make rates fall between 0 and nModes
983  uint8_t numSampleRates = station->m_nModes;
984 
985  uint8_t newIndex;
986  for (uint8_t col = 0; col < m_sampleCol; col++)
987  {
988  for (uint8_t i = 0; i < numSampleRates; i++ )
989  {
994  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
995  NS_LOG_DEBUG ("InitSampleTable uv: " << uv);
996  newIndex = (i + uv) % numSampleRates;
997 
998  //this loop is used for filling in other uninitialized places
999  while (station->m_sampleTable[newIndex][col] != 0)
1000  {
1001  newIndex = (newIndex + 1) % station->m_nModes;
1002  }
1003  station->m_sampleTable[newIndex][col] = i;
1004  }
1005  }
1006 }
1007 
1008 void
1010 {
1011  uint8_t numSampleRates = station->m_nModes;
1012  std::stringstream table;
1013  for (uint8_t i = 0; i < numSampleRates; i++)
1014  {
1015  for (uint8_t j = 0; j < m_sampleCol; j++)
1016  {
1017  table << station->m_sampleTable[i][j] << "\t";
1018  }
1019  table << std::endl;
1020  }
1021  NS_LOG_DEBUG (table.str ());
1022 }
1023 
1024 void
1026 {
1027  station->m_statsFile << "best _______________rate________________ ________statistics________ ________last_______ ______sum-of________\n" <<
1028  "rate [ name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1029 
1030  uint8_t maxTpRate = station->m_maxTpRate;
1031  uint8_t maxTpRate2 = station->m_maxTpRate2;
1032  uint8_t maxProbRate = station->m_maxProbRate;
1033 
1034  for (uint8_t i = 0; i < station->m_nModes; i++)
1035  {
1036  RateInfo rate = station->m_minstrelTable[i];
1037 
1038  if (i == maxTpRate)
1039  {
1040  station->m_statsFile << 'A';
1041  }
1042  else
1043  {
1044  station->m_statsFile << ' ';
1045  }
1046  if (i == maxTpRate2)
1047  {
1048  station->m_statsFile << 'B';
1049  }
1050  else
1051  {
1052  station->m_statsFile << ' ';
1053  }
1054  if (i == maxProbRate)
1055  {
1056  station->m_statsFile << 'P';
1057  }
1058  else
1059  {
1060  station->m_statsFile << ' ';
1061  }
1062 
1063  float tmpTh = rate.throughput / 100000.0f;
1064  station->m_statsFile << " " <<
1065  std::setw (17) << GetSupported (station, i) << " " <<
1066  std::setw (2) << i << " " <<
1067  std::setw (4) << rate.perfectTxTime.GetMicroSeconds () <<
1068  std::setw (8) << " ----- " <<
1069  std::setw (8) << tmpTh << " " <<
1070  std::setw (3) << rate.ewmaProb / 180 <<
1071  std::setw (3) << " --- " <<
1072  std::setw (3) << rate.prob / 180 << " " <<
1073  std::setw (1) << rate.adjustedRetryCount << " " <<
1074  std::setw (3) << rate.prevNumRateSuccess << " " <<
1075  std::setw (3) << rate.prevNumRateAttempt << " " <<
1076  std::setw (9) << rate.successHist << " " <<
1077  std::setw (9) << rate.attemptHist << "\n";
1078  }
1079  station->m_statsFile << "\nTotal packet count: ideal " << station->m_totalPacketsCount - station->m_samplePacketsCount
1080  << " lookaround " << station->m_samplePacketsCount << "\n\n";
1081 
1082  station->m_statsFile.flush ();
1083 }
1084 
1085 void
1087 {
1088  //HT is not supported by this algorithm.
1089  if (enable)
1090  {
1091  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
1092  }
1093 }
1094 
1095 void
1097 {
1098  //VHT is not supported by this algorithm.
1099  if (enable)
1100  {
1101  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
1102  }
1103 }
1104 
1105 void
1107 {
1108  //HE is not supported by this algorithm.
1109  if (enable)
1110  {
1111  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
1112  }
1113 }
1114 
1115 } //namespace ns3
void CheckInit(MinstrelWifiRemoteStation *station)
check for initializations
void PrintTable(MinstrelWifiRemoteStation *station)
printing Minstrel Table
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
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:156
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
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
uint8_t m_txrate
current transmit rate
Implementation of Minstrel Rate Control AlgorithmMinstrel is a rate control algorithm implemented in ...
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
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
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
uint8_t m_maxProbRate
rate with highest prob of success
#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:1015
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
uint8_t m_sampleRate
current sample rate
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.
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1235
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.
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
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.
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2226
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
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:363
void SetHtSupported(bool enable)
Enable or disable HT capability support.
AttributeValue implementation for Time.
Definition: nstime.h:1069
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:1031
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.
void PrintSampleTable(MinstrelWifiRemoteStation *station)
printing Sample Table
mac
Definition: third.py:92
uint32_t prevNumRateAttempt
Number of transmission attempts with previous rate.
WifiMode GetMode(uint8_t mode) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3501
uint64_t attemptHist
Aggregate of all transmission attempts.
uint64_t successHist
Aggregate of all transmission successes.
WifiRemoteStation * DoCreateStation(void) const
Mac48Address GetAddress(const WifiRemoteStation *station) const
Return the address of the station.
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
bool m_initialized
for initializing tables
uint32_t ewmaProb
EWMA calculation ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100.
TxTime m_calcTxTime
to hold all the calculated TxTime for all modes
uint8_t GetNextSample(MinstrelWifiRemoteStation *station)
getting the next sample from Sample Table
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)
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:1070
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
WifiMode GetSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether mode associated with the specified station at the specified index. ...
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...
WifiMode GetNonErpSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether non-ERP mode associated with the specified station at the specified index...
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.
#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:1007
uint32_t CountRetries(MinstrelWifiRemoteStation *station)
Count retries.
Time GetCalcTxTime(WifiMode mode) const
for estimating the TxTime of a packet with a given mode
void DoReportDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
uint8_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
bool m_printSamples
whether samples table should be printed.
uint32_t m_shortRetry
short retries such as control packts
uint8_t m_sampleCol
number of sample columns
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.
uint8_t FindRate(MinstrelWifiRemoteStation *station)
find a rate to use from Minstrel Table
uint8_t GetNModes(void) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3495
uint32_t prob
(# pkts success )/(# total pkts)
Ptr< WifiMac > GetMac(void) const
Return the WifiMac.
uint8_t m_maxTpRate
the current throughput rate
uint8_t m_maxTpRate2
second highest throughput rate
void UpdatePacketCounters(MinstrelWifiRemoteStation *station)
Update packet counters.
Time m_nextStatsUpdate
10 times every second
uint16_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.