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