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