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 "ns3/wifi-mac.h"
39 #include "ns3/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  for (const auto & mode : phy->GetModeList ())
117  {
118  WifiTxVector txVector;
119  txVector.SetMode (mode);
121  AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, phy->GetPhyBand ()));
122  }
124 }
125 
126 void
128 {
129  NS_LOG_FUNCTION (this << mac);
131 }
132 
133 void
135 {
136  NS_LOG_FUNCTION (this);
137  if (GetHtSupported ())
138  {
139  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
140  }
141  if (GetVhtSupported ())
142  {
143  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
144  }
145  if (GetHeSupported ())
146  {
147  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
148  }
149 }
150 
151 int64_t
153 {
154  NS_LOG_FUNCTION (this << stream);
156  return 1;
157 }
158 
159 Time
161 {
162  NS_LOG_FUNCTION (this << mode);
163  auto it = m_calcTxTime.find (mode);
164  NS_ASSERT (it != m_calcTxTime.end ());
165  return it->second;
166 }
167 
168 void
170 {
171  NS_LOG_FUNCTION (this << mode << t);
172  m_calcTxTime.insert (std::make_pair (mode, t));
173 }
174 
177 {
178  NS_LOG_FUNCTION (this);
180 
182  station->m_col = 0;
183  station->m_index = 0;
184  station->m_maxTpRate = 0;
185  station->m_maxTpRate2 = 0;
186  station->m_maxProbRate = 0;
187  station->m_nModes = 0;
188  station->m_totalPacketsCount = 0;
189  station->m_samplePacketsCount = 0;
190  station->m_isSampling = false;
191  station->m_sampleRate = 0;
192  station->m_sampleDeferred = false;
193  station->m_shortRetry = 0;
194  station->m_longRetry = 0;
195  station->m_retry = 0;
196  station->m_txrate = 0;
197  station->m_initialized = false;
198 
199  return station;
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION (this << station);
206  if (!station->m_initialized && GetNSupported (station) > 1)
207  {
208  //Note: we appear to be doing late initialization of the table
209  //to make sure that the set of supported rates has been initialized
210  //before we perform our own initialization.
211  station->m_nModes = GetNSupported (station);
212  station->m_minstrelTable = MinstrelRate (station->m_nModes);
213  station->m_sampleTable = SampleRate (station->m_nModes, std::vector<uint8_t> (m_sampleCol));
214  InitSampleTable (station);
215  RateInit (station);
216  station->m_initialized = true;
217  }
218 }
219 
235 void
237 {
238  NS_LOG_FUNCTION (this << station);
239  station->m_longRetry++;
240  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
241 
242  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
243 
244  //for normal rate, we're not currently sampling random rates
245  if (!station->m_isSampling)
246  {
247  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);
248  //use best throughput rate
249  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
250  {
251  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
252  station->m_txrate = station->m_maxTpRate;
253  }
254 
255  //use second best throughput rate
256  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
257  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
258  {
259  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
260  station->m_txrate = station->m_maxTpRate2;
261  }
262 
263  //use best probability rate
264  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
265  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
266  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
267  {
268  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
269  station->m_txrate = station->m_maxProbRate;
270  }
271 
272  //use lowest base rate
273  else if (station->m_longRetry > (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 base rate.");
278  station->m_txrate = 0;
279  }
280  }
281 
282  //for look-around rate, we're currently sampling random rates
283  else
284  {
285  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);
286  //current sampling rate is slower than the current best rate
287  if (station->m_sampleDeferred)
288  {
289  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
290  //use best throughput rate
291  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
292  {
293  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
294  station->m_txrate = station->m_maxTpRate;
295  }
296 
297  //use random rate
298  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
299  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
300  {
301  NS_LOG_DEBUG (" More retries left for the sampling rate.");
302  station->m_txrate = station->m_sampleRate;
303  }
304 
305  //use max probability rate
306  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
307  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
308  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
309  {
310  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
311  station->m_txrate = station->m_maxProbRate;
312  }
313 
314  //use lowest base rate
315  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
316  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
317  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
318  {
319  NS_LOG_DEBUG (" More retries left for the base rate.");
320  station->m_txrate = 0;
321  }
322  }
323  //current sampling rate is better than current best rate
324  else
325  {
326  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
327  //use random rate
328  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
329  {
330  NS_LOG_DEBUG (" More retries left for the sampling rate.");
331  station->m_txrate = station->m_sampleRate;
332  }
333 
334  //use the best throughput rate
335  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
336  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
337  {
338  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
339  station->m_txrate = station->m_maxTpRate;
340  }
341 
342  //use the best probability rate
343  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
344  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
345  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
346  {
347  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
348  station->m_txrate = station->m_maxProbRate;
349  }
350 
351  //use the lowest base rate
352  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
353  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
354  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
355  {
356  NS_LOG_DEBUG (" More retries left for the base rate.");
357  station->m_txrate = 0;
358  }
359  }
360  }
361 }
362 
365 {
366  NS_LOG_FUNCTION (this << station);
367  uint16_t channelWidth = GetChannelWidth (station);
368  if (channelWidth > 20 && channelWidth != 22)
369  {
370  channelWidth = 20;
371  }
372  if (!station->m_initialized)
373  {
374  CheckInit (station);
375  }
376  WifiMode mode = GetSupported (station, station->m_txrate);
377  uint64_t rate = mode.GetDataRate (channelWidth);
378  if (m_currentRate != rate && !station->m_isSampling)
379  {
380  NS_LOG_DEBUG ("New datarate: " << rate);
381  m_currentRate = rate;
382  }
383  return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode.GetModulationClass (), GetShortPreambleEnabled ()), 800, 1, 1, 0, channelWidth, GetAggregation (station));
384 }
385 
388 {
389  NS_LOG_FUNCTION (this << station);
390  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
391  uint16_t channelWidth = GetChannelWidth (station);
392  if (channelWidth > 20 && channelWidth != 22)
393  {
394  channelWidth = 20;
395  }
396  WifiMode mode;
397  if (GetUseNonErpProtection () == false)
398  {
399  mode = GetSupported (station, 0);
400  }
401  else
402  {
403  mode = GetNonErpSupported (station, 0);
404  }
405  return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode.GetModulationClass (), GetShortPreambleEnabled ()), 800, 1, 1, 0, channelWidth, GetAggregation (station));
406 }
407 
408 uint32_t
410 {
411  if (!station->m_isSampling)
412  {
413  return station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
414  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
415  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
416  station->m_minstrelTable[0].adjustedRetryCount;
417  }
418  else
419  {
420  return station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
421  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
422  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
423  station->m_minstrelTable[0].adjustedRetryCount;
424  }
425 }
426 
427 uint16_t
429 {
430  NS_LOG_FUNCTION (this << station);
431 
432  if (station->m_totalPacketsCount == 0)
433  {
434  return 0;
435  }
436 
437  uint16_t idx = 0;
438  NS_LOG_DEBUG ("Total: " << station->m_totalPacketsCount << " Sample: " << station->m_samplePacketsCount << " Deferred: " << station->m_numSamplesDeferred);
439 
440  int delta = (station->m_totalPacketsCount * m_lookAroundRate / 100) - (station->m_samplePacketsCount + station->m_numSamplesDeferred / 2);
441 
442  NS_LOG_DEBUG ("Decide sampling. Delta: " << delta << " lookAroundRatio: " << m_lookAroundRate);
443 
444  /* delta < 0: no sampling required */
445  if (delta >= 0)
446  {
447  NS_LOG_DEBUG ("Search next sampling rate");
448  uint8_t ratesSupported = station->m_nModes;
449  if (delta > ratesSupported * 2)
450  {
451  /* From Linux implementation:
452  * With multi-rate retry, not every planned sample
453  * attempt actually gets used, due to the way the retry
454  * chain is set up - [max_tp,sample,prob,lowest] for
455  * sample_rate < max_tp.
456  *
457  * If there's too much sampling backlog and the link
458  * starts getting worse, minstrel would start bursting
459  * out lots of sampling frames, which would result
460  * in a large throughput loss. */
461  station->m_samplePacketsCount += (delta - ratesSupported * 2);
462  }
463 
464  //now go through the table and find an index rate
465  idx = GetNextSample (station);
466 
467  NS_LOG_DEBUG ("Sample rate = " << idx << "(" << GetSupported (station, idx) << ")");
468 
469  //error check
470  if (idx >= station->m_nModes)
471  {
472  NS_LOG_DEBUG ("ALERT!!! ERROR");
473  }
474 
475  //set the rate that we're currently sampling
476  station->m_sampleRate = idx;
477 
478  /* From Linux implementation:
479  * Decide if direct ( 1st MRR stage) or indirect (2nd MRR stage)
480  * rate sampling method should be used.
481  * Respect such rates that are not sampled for 20 iterations.
482  */
483  if ((station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime)
484  && (station->m_minstrelTable[idx].numSamplesSkipped < 20))
485  {
486  // If the rate is slower and we have sample it enough, defer to second stage
487  station->m_sampleDeferred = true;
488  station->m_numSamplesDeferred++;
489 
490  //set flag that we are currently sampling
491  station->m_isSampling = true;
492  }
493  else
494  {
495  // if samplieLimit is zero, then don't sample this rate
496  if (!station->m_minstrelTable[idx].sampleLimit)
497  {
498  idx = station->m_maxTpRate;
499  station->m_isSampling = false;
500  }
501  else
502  {
503  //set flag that we are currently sampling
504  station->m_isSampling = true;
505  if (station->m_minstrelTable[idx].sampleLimit > 0)
506  {
507  station->m_minstrelTable[idx].sampleLimit--;
508  }
509  }
510  }
511 
512  //using the best rate instead
513  if (station->m_sampleDeferred)
514  {
515  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) << ")");
516  idx = station->m_maxTpRate;
517  }
518  }
519  //continue using the best rate
520  else
521  {
522  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
523  idx = station->m_maxTpRate;
524  }
525 
526  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
527 
528  return idx;
529 }
530 
531 void
533 {
534  NS_LOG_FUNCTION (this << station);
535  if (Simulator::Now () < station->m_nextStatsUpdate)
536  {
537  return;
538  }
539 
540  if (!station->m_initialized)
541  {
542  return;
543  }
544  NS_LOG_FUNCTION (this);
546  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
547  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
548 
549  Time txTime;
550  uint32_t tempProb;
551 
552  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
553  for (uint8_t i = 0; i < station->m_nModes; i++)
554  {
555 
556  //calculate the perfect TX time for this rate
557  txTime = station->m_minstrelTable[i].perfectTxTime;
558 
559  //just for initialization
560  if (txTime.GetMicroSeconds () == 0)
561  {
562  txTime = Seconds (1);
563  }
564 
565  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
566  "\t" << station->m_minstrelTable[i].numRateAttempt <<
567  "\t" << station->m_minstrelTable[i].numRateSuccess);
568 
569  //if we've attempted something
570  if (station->m_minstrelTable[i].numRateAttempt)
571  {
572  station->m_minstrelTable[i].numSamplesSkipped = 0;
577  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
578 
579  //bookkeeping
580  station->m_minstrelTable[i].prob = tempProb;
581 
582  if (station->m_minstrelTable[i].successHist == 0)
583  {
584  station->m_minstrelTable[i].ewmaProb = tempProb;
585  }
586  else
587  {
588  //EWMA probability (cast for gcc 3.4 compatibility)
589  tempProb = ((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100;
590 
591  station->m_minstrelTable[i].ewmaProb = tempProb;
592  }
593 
594  //calculating throughput
595  station->m_minstrelTable[i].throughput = tempProb * static_cast<uint32_t> ((1000000 / txTime.GetMicroSeconds ()));
596  }
597  else
598  {
599  station->m_minstrelTable[i].numSamplesSkipped++;
600  }
601 
602  //bookkeeping
603  station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess;
604  station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt;
605  station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess;
606  station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt;
607  station->m_minstrelTable[i].numRateSuccess = 0;
608  station->m_minstrelTable[i].numRateAttempt = 0;
609 
610  //Sample less often below 10% and above 95% of success
611  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
612  {
620  if (station->m_minstrelTable[i].retryCount > 2)
621  {
622  station->m_minstrelTable[i].adjustedRetryCount = 2;
623  }
624  station->m_minstrelTable[i].sampleLimit = 4;
625  }
626  else
627  {
628  // no sampling limit.
629  station->m_minstrelTable[i].sampleLimit = -1;
630  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
631  }
632 
633  //if it's 0 allow two retries.
634  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
635  {
636  station->m_minstrelTable[i].adjustedRetryCount = 2;
637  }
638  }
639 
640  NS_LOG_DEBUG ("Attempt/success reset to 0");
641 
642  uint32_t max_tp = 0;
643  uint8_t index_max_tp = 0, index_max_tp2 = 0;
644 
645  //go find max throughput, second maximum throughput, high probability of success
646  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
647  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
648  for (uint8_t i = 0; i < station->m_nModes; i++)
649  {
650  NS_LOG_DEBUG (+i << " " << GetSupported (station, i) <<
651  "\t" << station->m_minstrelTable[i].throughput <<
652  "\t" << station->m_minstrelTable[i].ewmaProb);
653 
654  if (max_tp < station->m_minstrelTable[i].throughput)
655  {
656  index_max_tp = i;
657  max_tp = station->m_minstrelTable[i].throughput;
658  }
659  }
660 
661  max_tp = 0;
662  //find the second highest max
663  for (uint8_t i = 0; i < station->m_nModes; i++)
664  {
665  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
666  {
667  index_max_tp2 = i;
668  max_tp = station->m_minstrelTable[i].throughput;
669  }
670  }
671 
672  uint32_t max_prob = 0;
673  uint8_t index_max_prob = 0;
674  for (uint8_t i = 0; i < station->m_nModes; i++)
675  {
676  if ((station->m_minstrelTable[i].ewmaProb >= 95 * 180) && (station->m_minstrelTable[i].throughput >= station->m_minstrelTable[index_max_prob].throughput))
677  {
678  index_max_prob = i;
679  max_prob = station->m_minstrelTable[i].ewmaProb;
680  }
681  else if (station->m_minstrelTable[i].ewmaProb >= max_prob)
682  {
683  index_max_prob = i;
684  max_prob = station->m_minstrelTable[i].ewmaProb;
685  }
686  }
687 
688  station->m_maxTpRate = index_max_tp;
689  station->m_maxTpRate2 = index_max_tp2;
690  station->m_maxProbRate = index_max_prob;
691 
692  if (index_max_tp > station->m_txrate)
693  {
694  station->m_txrate = index_max_tp;
695  }
696 
697  NS_LOG_DEBUG ("max throughput=" << +index_max_tp << "(" << GetSupported (station, index_max_tp) <<
698  ")\tsecond max throughput=" << +index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
699  ")\tmax prob=" << +index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
700  if (m_printStats)
701  {
702  PrintTable (station);
703  }
704  if (m_printSamples)
705  {
706  PrintSampleTable (station);
707  }
708 }
709 
710 void
712 {
713  NS_LOG_FUNCTION (this << st << rxSnr << txMode);
714  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << static_cast<MinstrelWifiRemoteStation*> (st)->m_txrate);
715 }
716 
717 void
719 {
720  NS_LOG_FUNCTION (this << st);
721  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
722  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
723  station->m_shortRetry++;
724 }
725 
726 void
727 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
728 {
729  NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode << rtsSnr);
730 }
731 
732 void
734 {
735  NS_LOG_FUNCTION (this << st);
736  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
737  UpdateRetry (station);
738 }
739 
740 void
742 {
743  NS_LOG_FUNCTION (this << st);
744  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
745  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
746  CheckInit (station);
747  if (!station->m_initialized)
748  {
749  return;
750  }
751 
752  UpdateRate (station);
753 }
754 
755 void
757  double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss)
758 {
759  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr << dataChannelWidth << +dataNss);
760  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
761 
762  CheckInit (station);
763  if (!station->m_initialized)
764  {
765  return;
766  }
767 
768  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).");
769 
770  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
771  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
772 
773  UpdatePacketCounters (station);
774 
775  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).");
776 
777  UpdateRetry (station);
778  UpdateStats (station);
779 
780  if (station->m_nModes >= 1)
781  {
782  station->m_txrate = FindRate (station);
783  }
784  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
785 }
786 
787 void
789 {
790  NS_LOG_FUNCTION (this << st);
791  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
792 
793  CheckInit (station);
794  if (!station->m_initialized)
795  {
796  return;
797  }
798 
799  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).");
800 
801  UpdatePacketCounters (station);
802 
803  UpdateRetry (station);
804  UpdateStats (station);
805 
806  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).");
807 
808  if (station->m_nModes >= 1)
809  {
810  station->m_txrate = FindRate (station);
811  }
812  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
813 }
814 
815 void
817 {
818  NS_LOG_FUNCTION (this << station);
819 
820  station->m_totalPacketsCount++;
821  // If it is a sampling frame and the sampleRate was used, increase counter
822  if (station->m_isSampling && (!station->m_sampleDeferred || station->m_longRetry >= station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
823  {
824  station->m_samplePacketsCount++;
825  }
826 
827  if (station->m_numSamplesDeferred > 0)
828  {
829  station->m_numSamplesDeferred--;
830  }
831 
832  if (station->m_totalPacketsCount == ~0)
833  {
834  station->m_numSamplesDeferred = 0;
835  station->m_samplePacketsCount = 0;
836  station->m_totalPacketsCount = 0;
837  }
838  station->m_isSampling = false;
839  station->m_sampleDeferred = false;
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION (this << station);
846  station->m_retry = station->m_shortRetry + station->m_longRetry;
847  station->m_shortRetry = 0;
848  station->m_longRetry = 0;
849 }
850 
853 {
854  NS_LOG_FUNCTION (this << st);
855  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
856  return GetDataTxVector (station);
857 }
858 
861 {
862  NS_LOG_FUNCTION (this << st);
863  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
864  return GetRtsTxVector (station);
865 }
866 
867 bool
869 {
870  NS_LOG_FUNCTION (this << st << packet << normally);
871  MinstrelWifiRemoteStation *station = static_cast<MinstrelWifiRemoteStation*> (st);
872 
873  CheckInit (station);
874  if (!station->m_initialized)
875  {
876  return normally;
877  }
878  if (station->m_longRetry >= CountRetries (station))
879  {
880  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
881  return false;
882  }
883  else
884  {
885  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
886  return true;
887  }
888 }
889 
890 uint16_t
892 {
893  NS_LOG_FUNCTION (this << station);
894  uint16_t bitrate;
895  bitrate = station->m_sampleTable[station->m_index][station->m_col];
896  station->m_index++;
897 
898  //bookkeeping for m_index and m_col variables
899  NS_ABORT_MSG_IF (station->m_nModes < 2, "Integer overflow detected");
900  if (station->m_index > station->m_nModes - 2)
901  {
902  station->m_index = 0;
903  station->m_col++;
904  if (station->m_col >= m_sampleCol)
905  {
906  station->m_col = 0;
907  }
908  }
909  return bitrate;
910 }
911 
912 void
914 {
915  NS_LOG_FUNCTION (this << station);
916  for (uint8_t i = 0; i < station->m_nModes; i++)
917  {
918  NS_LOG_DEBUG ("Initializing rate index " << +i << " " << GetSupported (station, i));
919  station->m_minstrelTable[i].numRateAttempt = 0;
920  station->m_minstrelTable[i].numRateSuccess = 0;
921  station->m_minstrelTable[i].prevNumRateSuccess = 0;
922  station->m_minstrelTable[i].prevNumRateAttempt = 0;
923  station->m_minstrelTable[i].successHist = 0;
924  station->m_minstrelTable[i].attemptHist = 0;
925  station->m_minstrelTable[i].numSamplesSkipped = 0;
926  station->m_minstrelTable[i].prob = 0;
927  station->m_minstrelTable[i].ewmaProb = 0;
928  station->m_minstrelTable[i].throughput = 0;
929  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
930  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
931  station->m_minstrelTable[i].retryCount = 1;
932  station->m_minstrelTable[i].adjustedRetryCount = 1;
933  //Emulating minstrel.c::ath_rate_ctl_reset
934  //We only check from 2 to 10 retries. This guarantee that
935  //at least one retry is permitted.
936  Time totalTxTimeWithGivenRetries = Seconds (0.0); //tx_time in minstrel.c
937  NS_LOG_DEBUG (" Calculating the number of retries");
938  for (uint32_t retries = 2; retries < 11; retries++)
939  {
940  NS_LOG_DEBUG (" Checking " << retries << " retries");
941  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
942  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
943  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
944  {
945  break;
946  }
947  station->m_minstrelTable[i].sampleLimit = -1;
948  station->m_minstrelTable[i].retryCount = retries;
949  station->m_minstrelTable[i].adjustedRetryCount = retries;
950  }
951  }
952  UpdateStats (station);
953 }
954 
955 Time
956 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
957 {
958  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
959  //See rc80211_minstrel.c
960 
961  //First transmission (Data + Ack timeout)
962  Time tt = dataTransmissionTime + GetPhy ()->GetSifs () + GetPhy ()->GetAckTxTime ();
963 
964  uint32_t cwMax = 1023;
965  uint32_t cw = 31;
966  for (uint32_t retry = 0; retry < longRetries; retry++)
967  {
968  //Add one re-transmission (Data + Ack timeout)
969  tt += dataTransmissionTime + GetPhy ()->GetSifs () + GetPhy ()->GetAckTxTime ();
970 
971  //Add average back off (half the current contention window)
972  tt += (cw / 2.0) * GetPhy ()->GetSlot ();
973 
974  //Update contention window
975  cw = std::min (cwMax, (cw + 1) * 2);
976  }
977 
978  return tt;
979 }
980 
981 void
983 {
984  NS_LOG_FUNCTION (this << station);
985  station->m_col = station->m_index = 0;
986 
987  //for off-setting to make rates fall between 0 and nModes
988  uint8_t numSampleRates = station->m_nModes;
989 
990  uint16_t newIndex;
991  for (uint8_t col = 0; col < m_sampleCol; col++)
992  {
993  for (uint8_t i = 0; i < numSampleRates; i++ )
994  {
999  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
1000  NS_LOG_DEBUG ("InitSampleTable uv: " << uv);
1001  newIndex = (i + uv) % numSampleRates;
1002 
1003  //this loop is used for filling in other uninitialized places
1004  while (station->m_sampleTable[newIndex][col] != 0)
1005  {
1006  newIndex = (newIndex + 1) % station->m_nModes;
1007  }
1008  station->m_sampleTable[newIndex][col] = i;
1009  }
1010  }
1011 }
1012 
1013 void
1015 {
1016  uint8_t numSampleRates = station->m_nModes;
1017  std::stringstream table;
1018  for (uint8_t i = 0; i < numSampleRates; i++)
1019  {
1020  for (uint8_t j = 0; j < m_sampleCol; j++)
1021  {
1022  table << station->m_sampleTable[i][j] << "\t";
1023  }
1024  table << std::endl;
1025  }
1026  NS_LOG_DEBUG (table.str ());
1027 }
1028 
1029 void
1031 {
1032  if (!station->m_statsFile.is_open ())
1033  {
1034  std::ostringstream tmp;
1035  tmp << "minstrel-stats-" << station->m_state->m_address << ".txt";
1036  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
1037  }
1038 
1039  station->m_statsFile << "best _______________rate________________ ________statistics________ ________last_______ ______sum-of________\n" <<
1040  "rate [ name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1041 
1042  uint16_t maxTpRate = station->m_maxTpRate;
1043  uint16_t maxTpRate2 = station->m_maxTpRate2;
1044  uint16_t maxProbRate = station->m_maxProbRate;
1045 
1046  for (uint8_t i = 0; i < station->m_nModes; i++)
1047  {
1048  RateInfo rate = station->m_minstrelTable[i];
1049 
1050  if (i == maxTpRate)
1051  {
1052  station->m_statsFile << 'A';
1053  }
1054  else
1055  {
1056  station->m_statsFile << ' ';
1057  }
1058  if (i == maxTpRate2)
1059  {
1060  station->m_statsFile << 'B';
1061  }
1062  else
1063  {
1064  station->m_statsFile << ' ';
1065  }
1066  if (i == maxProbRate)
1067  {
1068  station->m_statsFile << 'P';
1069  }
1070  else
1071  {
1072  station->m_statsFile << ' ';
1073  }
1074 
1075  float tmpTh = rate.throughput / 100000.0f;
1076  station->m_statsFile << " " <<
1077  std::setw (17) << GetSupported (station, i) << " " <<
1078  std::setw (2) << i << " " <<
1079  std::setw (4) << rate.perfectTxTime.GetMicroSeconds () <<
1080  std::setw (8) << " ----- " <<
1081  std::setw (8) << tmpTh << " " <<
1082  std::setw (3) << rate.ewmaProb / 180 <<
1083  std::setw (3) << " --- " <<
1084  std::setw (3) << rate.prob / 180 << " " <<
1085  std::setw (1) << rate.adjustedRetryCount << " " <<
1086  std::setw (3) << rate.prevNumRateSuccess << " " <<
1087  std::setw (3) << rate.prevNumRateAttempt << " " <<
1088  std::setw (9) << rate.successHist << " " <<
1089  std::setw (9) << rate.attemptHist << "\n";
1090  }
1091  station->m_statsFile << "\nTotal packet count: ideal " << station->m_totalPacketsCount - station->m_samplePacketsCount
1092  << " lookaround " << station->m_samplePacketsCount << "\n\n";
1093 
1094  station->m_statsFile.flush ();
1095 }
1096 
1097 } //namespace ns3
#define min(a, b)
Definition: 80211b.c:42
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Implementation of Minstrel Rate Control Algorithm.
WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station) override
uint8_t m_lookAroundRate
the % to try other rates than our current rate
void AddCalcTxTime(WifiMode mode, Time t)
Add transmission time for the given mode to an internal list.
void PrintSampleTable(MinstrelWifiRemoteStation *station)
Print Sample Table.
void RateInit(MinstrelWifiRemoteStation *station)
Initialize Minstrel Table.
uint32_t m_pktLen
packet length used for 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(void) override
Initialize() implementation.
void UpdateStats(MinstrelWifiRemoteStation *station)
Update the Minstrel Table.
void CheckInit(MinstrelWifiRemoteStation *station)
Check for initializations.
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
TxTime m_calcTxTime
to hold all the calculated TxTime for all modes
WifiTxVector DoGetDataTxVector(WifiRemoteStation *station) override
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.
static TypeId GetTypeId(void)
Get the type ID.
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.
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.
WifiRemoteStation * DoCreateStation(void) const override
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(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value, as an unsigned integer in the specified range .
represent a single transmission mode
Definition: wifi-mode.h:48
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:177
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:114
Time GetSlot(void) const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:688
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:676
Time GetAckTxTime(void) const
Return the estimated Ack TX time for this PHY.
Definition: wifi-phy.cc:706
hold a list of per-remote-station state.
uint16_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
Ptr< WifiPhy > GetPhy(void) const
Return the WifiPhy.
uint8_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
WifiMode GetNonErpSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether non-ERP mode associated with the specified station at the specified index.
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PHY preambles.
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 GetHeSupported(void) const
Return whether the device has HE capability support enabled.
WifiMode GetSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether mode associated with the specified station at the specified index.
bool GetHtSupported(void) const
Return whether the device has HT 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:67
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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:85
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:1309
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
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
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.
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:522
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble)
Return the preamble to be used for the transmission.
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:99
phy
Definition: third.py:93
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.