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 "minstrel-wifi-manager.h"
33 #include "ns3/simulator.h"
34 #include "ns3/log.h"
35 #include "ns3/double.h"
36 #include "ns3/boolean.h"
37 #include "wifi-mac.h"
38 #include "wifi-phy.h"
39 #include <iomanip>
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  DoubleValue (10),
65  MakeDoubleChecker<double> ())
66  .AddAttribute ("EWMA",
67  "EWMA level",
68  DoubleValue (75),
70  MakeDoubleChecker<double> ())
71  .AddAttribute ("SampleColumn",
72  "The number of columns used for sampling",
73  UintegerValue (10),
75  MakeUintegerChecker <uint32_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  .AddTraceSource ("Rate",
87  "Traced value for rate changes (b/s)",
89  "ns3::TracedValueCallback::Uint64")
90  ;
91  return tid;
92 }
93 
96  m_currentRate (0)
97 {
98  NS_LOG_FUNCTION (this);
99  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
100 }
101 
103 {
104  NS_LOG_FUNCTION (this);
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION (this << phy);
111  uint8_t nModes = phy->GetNModes ();
112  for (uint8_t i = 0; i < nModes; i++)
113  {
114  WifiMode mode = phy->GetMode (i);
115  WifiTxVector txVector;
116  txVector.SetMode (mode);
118  AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, phy->GetFrequency ()));
119  }
121 }
122 
123 void
125 {
126  NS_LOG_FUNCTION (this << mac);
128 }
129 
130 int64_t
132 {
133  NS_LOG_FUNCTION (this << stream);
135  return 1;
136 }
137 
138 Time
140 {
141  NS_LOG_FUNCTION (this << mode);
142  for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
143  {
144  if (mode == i->second)
145  {
146  return i->first;
147  }
148  }
149  NS_ASSERT (false);
150  return Seconds (0);
151 }
152 
153 void
155 {
156  NS_LOG_FUNCTION (this << mode << t);
157  m_calcTxTime.push_back (std::make_pair (t, mode));
158 }
159 
162 {
163  NS_LOG_FUNCTION (this);
165 
167  station->m_col = 0;
168  station->m_index = 0;
169  station->m_maxTpRate = 0;
170  station->m_maxTpRate2 = 0;
171  station->m_maxProbRate = 0;
172  station->m_nModes = 0;
173  station->m_totalPacketsCount = 0;
174  station->m_samplePacketsCount = 0;
175  station->m_isSampling = false;
176  station->m_sampleRate = 0;
177  station->m_sampleDeferred = false;
178  station->m_shortRetry = 0;
179  station->m_longRetry = 0;
180  station->m_retry = 0;
181  station->m_txrate = 0;
182  station->m_initialized = false;
183 
184  return station;
185 }
186 
187 void
189 {
190  NS_LOG_FUNCTION (this << station);
191  if (!station->m_initialized && GetNSupported (station) > 1)
192  {
193  //Note: we appear to be doing late initialization of the table
194  //to make sure that the set of supported rates has been initialized
195  //before we perform our own initialization.
196  station->m_nModes = GetNSupported (station);
197  station->m_minstrelTable = MinstrelRate (station->m_nModes);
198  station->m_sampleTable = SampleRate (station->m_nModes, std::vector<uint32_t> (m_sampleCol));
199  InitSampleTable (station);
200  RateInit (station);
201  station->m_initialized = true;
202  std::ostringstream tmp;
203  tmp << "minstrel-stats-" << station->m_state->m_address << ".txt";
204  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
205  }
206 }
207 
223 void
225 {
226  NS_LOG_FUNCTION (this << station);
227  station->m_longRetry++;
228  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
229 
230  NS_LOG_DEBUG ("DoReportDataFailed " << station << " rate " << station->m_txrate << " longRetry " << station->m_longRetry);
231 
232  //for normal rate, we're not currently sampling random rates
233  if (!station->m_isSampling)
234  {
235  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);
236  //use best throughput rate
237  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
238  {
239  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
240  station->m_txrate = station->m_maxTpRate;
241  }
242 
243  //use second best throughput rate
244  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
245  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount))
246  {
247  NS_LOG_DEBUG (" More retries left for the second maximum throughput rate.");
248  station->m_txrate = station->m_maxTpRate2;
249  }
250 
251  //use best probability rate
252  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
253  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
254  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
255  {
256  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
257  station->m_txrate = station->m_maxProbRate;
258  }
259 
260  //use lowest base rate
261  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
262  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
263  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
264  {
265  NS_LOG_DEBUG (" More retries left for the base rate.");
266  station->m_txrate = 0;
267  }
268  }
269 
270  //for look-around rate, we're currently sampling random rates
271  else
272  {
273  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);
274  //current sampling rate is slower than the current best rate
275  if (station->m_sampleDeferred)
276  {
277  NS_LOG_DEBUG ("Look around rate is slower than the maximum throughput rate.");
278  //use best throughput rate
279  if (station->m_longRetry < station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount)
280  {
281  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
282  station->m_txrate = station->m_maxTpRate;
283  }
284 
285  //use random rate
286  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
287  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
288  {
289  NS_LOG_DEBUG (" More retries left for the sampling rate.");
290  station->m_txrate = station->m_sampleRate;
291  }
292 
293  //use max probability rate
294  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
295  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
296  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount ))
297  {
298  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
299  station->m_txrate = station->m_maxProbRate;
300  }
301 
302  //use lowest base rate
303  else if (station->m_longRetry > (station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
304  station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
305  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
306  {
307  NS_LOG_DEBUG (" More retries left for the base rate.");
308  station->m_txrate = 0;
309  }
310  }
311  //current sampling rate is better than current best rate
312  else
313  {
314  NS_LOG_DEBUG ("Look around rate is faster than the maximum throughput rate.");
315  //use random rate
316  if (station->m_longRetry < station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount)
317  {
318  NS_LOG_DEBUG (" More retries left for the sampling rate.");
319  station->m_txrate = station->m_sampleRate;
320  }
321 
322  //use the best throughput rate
323  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
324  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
325  {
326  NS_LOG_DEBUG (" More retries left for the maximum throughput rate.");
327  station->m_txrate = station->m_maxTpRate;
328  }
329 
330  //use the best probability rate
331  else if (station->m_longRetry <= (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
332  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
333  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
334  {
335  NS_LOG_DEBUG (" More retries left for the maximum probability rate.");
336  station->m_txrate = station->m_maxProbRate;
337  }
338 
339  //use the lowest base rate
340  else if (station->m_longRetry > (station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
341  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
342  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount))
343  {
344  NS_LOG_DEBUG (" More retries left for the base rate.");
345  station->m_txrate = 0;
346  }
347  }
348  }
349 }
350 
353 {
354  NS_LOG_FUNCTION (this << station);
355  uint8_t channelWidth = GetChannelWidth (station);
356  if (channelWidth > 20 && channelWidth != 22)
357  {
358  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
359  channelWidth = 20;
360  }
361  if (!station->m_initialized)
362  {
363  CheckInit (station);
364  }
365  WifiMode mode = GetSupported (station, station->m_txrate);
366  if (m_currentRate != mode.GetDataRate (channelWidth) && !station->m_isSampling)
367  {
368  NS_LOG_DEBUG ("New datarate: " << mode.GetDataRate (channelWidth));
369  m_currentRate = mode.GetDataRate (channelWidth);
370  }
371  return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
372 }
373 
376 {
377  NS_LOG_FUNCTION (this << station);
378  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
379  uint8_t channelWidth = GetChannelWidth (station);
380  if (channelWidth > 20 && channelWidth != 22)
381  {
382  //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
383  channelWidth = 20;
384  }
385  WifiTxVector rtsTxVector;
386  WifiMode mode;
387  if (GetUseNonErpProtection () == false)
388  {
389  mode = GetSupported (station, 0);
390  }
391  else
392  {
393  mode = GetNonErpSupported (station, 0);
394  }
395  rtsTxVector = WifiTxVector (mode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 1, 0, channelWidth, GetAggregation (station), false);
396  return rtsTxVector;
397 }
398 
399 uint32_t
401 {
402  if (!station->m_isSampling)
403  {
404  return station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
405  station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount +
406  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
407  station->m_minstrelTable[0].adjustedRetryCount;
408  }
409  else
410  {
411  return station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount +
412  station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +
413  station->m_minstrelTable[station->m_maxProbRate].adjustedRetryCount +
414  station->m_minstrelTable[0].adjustedRetryCount;
415  }
416 }
417 
418 uint32_t
420 {
421  NS_LOG_FUNCTION (this << station);
422 
423  if (station->m_totalPacketsCount == 0)
424  {
425  return 0;
426  }
427 
428  uint32_t idx = 0;
429  NS_LOG_DEBUG ("Total: " << station->m_totalPacketsCount << " Sample: " << station->m_samplePacketsCount << " Deferred: " << station->m_numSamplesDeferred);
430 
431  int delta = (station->m_totalPacketsCount * m_lookAroundRate / 100) - (station->m_samplePacketsCount + station->m_numSamplesDeferred / 2);
432 
433  NS_LOG_DEBUG ("Decide sampling. Delta: " << delta << " lookAroundRatio: " << m_lookAroundRate);
434 
435  /* delta < 0: no sampling required */
436  if (delta >= 0)
437  {
438  NS_LOG_DEBUG ("Search next sampling rate");
439  uint8_t ratesSupported = station->m_nModes;
440  if (delta > ratesSupported * 2)
441  {
442  /* From Linux implementation:
443  * With multi-rate retry, not every planned sample
444  * attempt actually gets used, due to the way the retry
445  * chain is set up - [max_tp,sample,prob,lowest] for
446  * sample_rate < max_tp.
447  *
448  * If there's too much sampling backlog and the link
449  * starts getting worse, minstrel would start bursting
450  * out lots of sampling frames, which would result
451  * in a large throughput loss. */
452  station->m_samplePacketsCount += (delta - ratesSupported * 2);
453  }
454 
455  //now go through the table and find an index rate
456  idx = GetNextSample (station);
457 
458  NS_LOG_DEBUG ("Sample rate = " << idx << "(" << GetSupported (station, idx) << ")");
459 
460  //error check
461  if (idx >= station->m_nModes)
462  {
463  NS_LOG_DEBUG ("ALERT!!! ERROR");
464  }
465 
466  //set the rate that we're currently sampling
467  station->m_sampleRate = idx;
468 
469  /* From Linux implementation:
470  * Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
471  * rate sampling method should be used.
472  * Respect such rates that are not sampled for 20 iterations.
473  */
474  if ((station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime)
475  && (station->m_minstrelTable[idx].numSamplesSkipped < 20))
476  {
477  // If the rate is slower and we have sample it enough, defer to second stage
478  station->m_sampleDeferred = true;
479  station->m_numSamplesDeferred++;
480 
481  //set flag that we are currently sampling
482  station->m_isSampling = true;
483  }
484  else
485  {
486  // if samplieLimit is zero, then don't sample this rate
487  if (!station->m_minstrelTable[idx].sampleLimit)
488  {
489  idx = station->m_maxTpRate;
490  station->m_isSampling = false;
491  }
492  else
493  {
494  //set flag that we are currently sampling
495  station->m_isSampling = true;
496  if (station->m_minstrelTable[idx].sampleLimit > 0)
497  {
498  station->m_minstrelTable[idx].sampleLimit--;
499  }
500  }
501  }
502 
503  //using the best rate instead
504  if (station->m_sampleDeferred)
505  {
506  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) << ")");
507  idx = station->m_maxTpRate;
508  }
509  }
510  //continue using the best rate
511  else
512  {
513  NS_LOG_DEBUG ("Continue using the maximum throughput rate: " << station->m_maxTpRate << "(" << GetSupported (station, station->m_maxTpRate) << ")");
514  idx = station->m_maxTpRate;
515  }
516 
517  NS_LOG_DEBUG ("Rate = " << idx << "(" << GetSupported (station, idx) << ")");
518 
519  return idx;
520 }
521 
522 void
524 {
525  NS_LOG_FUNCTION (this << station);
526  if (Simulator::Now () < station->m_nextStatsUpdate)
527  {
528  return;
529  }
530 
531  if (!station->m_initialized)
532  {
533  return;
534  }
535  NS_LOG_FUNCTION (this);
537  NS_LOG_DEBUG ("Next update at " << station->m_nextStatsUpdate);
538  NS_LOG_DEBUG ("Currently using rate: " << station->m_txrate << " (" << GetSupported (station, station->m_txrate) << ")");
539 
540  Time txTime;
541  uint32_t tempProb;
542 
543  NS_LOG_DEBUG ("Index-Rate\t\tAttempt\tSuccess");
544  for (uint8_t i = 0; i < station->m_nModes; i++)
545  {
546 
547  //calculate the perfect tx time for this rate
548  txTime = station->m_minstrelTable[i].perfectTxTime;
549 
550  //just for initialization
551  if (txTime.GetMicroSeconds () == 0)
552  {
553  txTime = Seconds (1);
554  }
555 
556  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
557  "\t" << station->m_minstrelTable[i].numRateAttempt <<
558  "\t" << station->m_minstrelTable[i].numRateSuccess);
559 
560  //if we've attempted something
561  if (station->m_minstrelTable[i].numRateAttempt)
562  {
563  station->m_minstrelTable[i].numSamplesSkipped = 0;
568  tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
569 
570  //bookeeping
571  station->m_minstrelTable[i].prob = tempProb;
572 
573  if (station->m_minstrelTable[i].successHist == 0)
574  {
575  station->m_minstrelTable[i].ewmaProb = tempProb;
576  }
577  else
578  {
579  //ewma probability (cast for gcc 3.4 compatibility)
580  tempProb = static_cast<uint32_t> (((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) ) / 100);
581 
582  station->m_minstrelTable[i].ewmaProb = tempProb;
583  }
584 
585  //calculating throughput
586  station->m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds ());
587 
588  }
589  else
590  {
591  station->m_minstrelTable[i].numSamplesSkipped++;
592  }
593 
594  //bookeeping
595  station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess;
596  station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt;
597  station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess;
598  station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt;
599  station->m_minstrelTable[i].numRateSuccess = 0;
600  station->m_minstrelTable[i].numRateAttempt = 0;
601 
602  //Sample less often below 10% and above 95% of success
603  if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800))
604  {
612  if (station->m_minstrelTable[i].retryCount > 2)
613  {
614  station->m_minstrelTable[i].adjustedRetryCount = 2;
615  }
616  station->m_minstrelTable[i].sampleLimit = 4;
617  }
618  else
619  {
620  // no sampling limit.
621  station->m_minstrelTable[i].sampleLimit = -1;
622  station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
623  }
624 
625  //if it's 0 allow two retries.
626  if (station->m_minstrelTable[i].adjustedRetryCount == 0)
627  {
628  station->m_minstrelTable[i].adjustedRetryCount = 2;
629  }
630  }
631 
632  NS_LOG_DEBUG ("Attempt/success resetted to 0");
633 
634  uint32_t max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
635 
636  //go find max throughput, second maximum throughput, high probability succ
637  NS_LOG_DEBUG ("Finding the maximum throughput, second maximum throughput, and highest probability");
638  NS_LOG_DEBUG ("Index-Rate\t\tT-put\tEWMA");
639  for (uint8_t i = 0; i < station->m_nModes; i++)
640  {
641  NS_LOG_DEBUG (i << " " << GetSupported (station, i) <<
642  "\t" << station->m_minstrelTable[i].throughput <<
643  "\t" << station->m_minstrelTable[i].ewmaProb);
644 
645  if (max_tp < station->m_minstrelTable[i].throughput)
646  {
647  index_max_tp = i;
648  max_tp = station->m_minstrelTable[i].throughput;
649  }
650  }
651 
652  max_tp = 0;
653  //find the second highest max
654  for (uint8_t i = 0; i < station->m_nModes; i++)
655  {
656  if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
657  {
658  index_max_tp2 = i;
659  max_tp = station->m_minstrelTable[i].throughput;
660  }
661  }
662 
663  uint32_t max_prob = 0, index_max_prob = 0;
664  for (uint8_t i = 0; i < station->m_nModes; i++)
665  {
666  if ((station->m_minstrelTable[i].ewmaProb >= 95 * 180) && (station->m_minstrelTable[i].throughput >= station->m_minstrelTable[index_max_prob].throughput))
667  {
668  index_max_prob = i;
669  max_prob = station->m_minstrelTable[i].ewmaProb;
670  }
671  else if (station->m_minstrelTable[i].ewmaProb >= max_prob)
672  {
673  index_max_prob = i;
674  max_prob = station->m_minstrelTable[i].ewmaProb;
675  }
676  }
677 
678  station->m_maxTpRate = index_max_tp;
679  station->m_maxTpRate2 = index_max_tp2;
680  station->m_maxProbRate = index_max_prob;
681 
682  if (index_max_tp > station->m_txrate)
683  {
684  station->m_txrate = index_max_tp;
685  }
686 
687  NS_LOG_DEBUG ("max throughput=" << index_max_tp << "(" << GetSupported (station, index_max_tp) <<
688  ")\tsecond max throughput=" << index_max_tp2 << "(" << GetSupported (station, index_max_tp2) <<
689  ")\tmax prob=" << index_max_prob << "(" << GetSupported (station, index_max_prob) << ")");
690  if (m_printStats)
691  {
692  PrintTable (station);
693  }
694 }
695 
696 void
698 {
699  NS_LOG_FUNCTION (this << st << rxSnr << txMode);
700  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelWifiRemoteStation *)st)->m_txrate);
701 }
702 
703 void
705 {
706  NS_LOG_FUNCTION (this << st);
708  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
709  station->m_shortRetry++;
710 }
711 
712 void
713 MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
714 {
715  NS_LOG_FUNCTION (this << st << ctsSnr << ctsMode << rtsSnr);
716 }
717 
718 void
720 {
721  NS_LOG_FUNCTION (this << st);
723  UpdateRetry (station);
724 }
725 
726 void
728 {
729  NS_LOG_FUNCTION (this << st);
731  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
732  CheckInit (station);
733  if (!station->m_initialized)
734  {
735  return;
736  }
737 
738  UpdateRate (station);
739 }
740 
741 void
743  double ackSnr, WifiMode ackMode, double dataSnr)
744 {
745  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
747 
748  CheckInit (station);
749  if (!station->m_initialized)
750  {
751  return;
752  }
753 
754  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).");
755 
756  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
757  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
758 
759  UpdatePacketCounters (station);
760 
761  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).");
762 
763  UpdateRetry (station);
764  UpdateStats (station);
765 
766  if (station->m_nModes >= 1)
767  {
768  station->m_txrate = FindRate (station);
769  }
770  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
771 }
772 
773 void
775 {
776  NS_LOG_FUNCTION (this << st);
778 
779  CheckInit (station);
780  if (!station->m_initialized)
781  {
782  return;
783  }
784 
785  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).");
786 
787  UpdatePacketCounters (station);
788 
789  UpdateRetry (station);
790  UpdateStats (station);
791 
792  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).");
793 
794  if (station->m_nModes >= 1)
795  {
796  station->m_txrate = FindRate (station);
797  }
798  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
799 }
800 
801 void
803 {
804  NS_LOG_FUNCTION (this << station);
805 
806  station->m_totalPacketsCount++;
807  // If it is a sampling frame and the sampleRate was used, increase counter
808  if (station->m_isSampling && (!station->m_sampleDeferred || station->m_longRetry >= station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
809  {
810  station->m_samplePacketsCount++;
811  }
812 
813  if (station->m_numSamplesDeferred > 0)
814  {
815  station->m_numSamplesDeferred--;
816  }
817 
818  if (station->m_totalPacketsCount == ~0)
819  {
820  station->m_numSamplesDeferred = 0;
821  station->m_samplePacketsCount = 0;
822  station->m_totalPacketsCount = 0;
823  }
824  station->m_isSampling = false;
825  station->m_sampleDeferred = false;
826 }
827 
828 void
830 {
831  NS_LOG_FUNCTION (this << station);
832  station->m_retry = station->m_shortRetry + station->m_longRetry;
833  station->m_shortRetry = 0;
834  station->m_longRetry = 0;
835 }
836 
839 {
840  NS_LOG_FUNCTION (this << st);
842  return GetDataTxVector (station);
843 }
844 
847 {
848  NS_LOG_FUNCTION (this << st);
850  return GetRtsTxVector (station);
851 }
852 
853 bool
855 {
856  NS_LOG_FUNCTION (this << st << packet << normally);
858 
859  CheckInit (station);
860  if (!station->m_initialized)
861  {
862  return normally;
863  }
864  if (station->m_longRetry >= CountRetries (station))
865  {
866  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
867  return false;
868  }
869  else
870  {
871  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << CountRetries (station));
872  return true;
873  }
874 }
875 
876 bool
878 {
879  return true;
880 }
881 
882 uint32_t
884 {
885  NS_LOG_FUNCTION (this << station);
886  uint32_t bitrate;
887  bitrate = station->m_sampleTable[station->m_index][station->m_col];
888  station->m_index++;
889 
890  //bookeeping for m_index and m_col variables
891  NS_ABORT_MSG_IF (station->m_nModes < 2, "Integer overflow detected");
892  if (station->m_index > station->m_nModes - 2)
893  {
894  station->m_index = 0;
895  station->m_col++;
896  if (station->m_col >= m_sampleCol)
897  {
898  station->m_col = 0;
899  }
900  }
901  return bitrate;
902 }
903 
904 void
906 {
907  NS_LOG_FUNCTION (this << station);
908  for (uint8_t i = 0; i < station->m_nModes; i++)
909  {
910  NS_LOG_DEBUG ("Initializing rate index " << +i << " " << GetSupported (station, i));
911  station->m_minstrelTable[i].numRateAttempt = 0;
912  station->m_minstrelTable[i].numRateSuccess = 0;
913  station->m_minstrelTable[i].prevNumRateSuccess = 0;
914  station->m_minstrelTable[i].prevNumRateAttempt = 0;
915  station->m_minstrelTable[i].successHist = 0;
916  station->m_minstrelTable[i].attemptHist = 0;
917  station->m_minstrelTable[i].numSamplesSkipped = 0;
918  station->m_minstrelTable[i].prob = 0;
919  station->m_minstrelTable[i].ewmaProb = 0;
920  station->m_minstrelTable[i].throughput = 0;
921  station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
922  NS_LOG_DEBUG (" perfectTxTime = " << station->m_minstrelTable[i].perfectTxTime);
923  station->m_minstrelTable[i].retryCount = 1;
924  station->m_minstrelTable[i].adjustedRetryCount = 1;
925  //Emulating minstrel.c::ath_rate_ctl_reset
926  //We only check from 2 to 10 retries. This guarantee that
927  //at least one retry is permitter.
928  Time totalTxTimeWithGivenRetries = Seconds (0.0); //tx_time in minstrel.c
929  NS_LOG_DEBUG (" Calculating the number of retries");
930  for (uint32_t retries = 2; retries < 11; retries++)
931  {
932  NS_LOG_DEBUG (" Checking " << retries << " retries");
933  totalTxTimeWithGivenRetries = CalculateTimeUnicastPacket (station->m_minstrelTable[i].perfectTxTime, 0, retries);
934  NS_LOG_DEBUG (" totalTxTimeWithGivenRetries = " << totalTxTimeWithGivenRetries);
935  if (totalTxTimeWithGivenRetries > MilliSeconds (6))
936  {
937  break;
938  }
939  station->m_minstrelTable[i].sampleLimit = -1;
940  station->m_minstrelTable[i].retryCount = retries;
941  station->m_minstrelTable[i].adjustedRetryCount = retries;
942  }
943  }
944  UpdateStats (station);
945 }
946 
947 Time
948 MinstrelWifiManager::CalculateTimeUnicastPacket (Time dataTransmissionTime, uint32_t shortRetries, uint32_t longRetries)
949 {
950  NS_LOG_FUNCTION (this << dataTransmissionTime << shortRetries << longRetries);
951  //See rc80211_minstrel.c
952 
953  //First transmission (DATA + ACK timeout)
954  Time tt = dataTransmissionTime + GetMac ()->GetAckTimeout ();
955 
956  uint32_t cwMax = 1023;
957  uint32_t cw = 31;
958  for (uint32_t retry = 0; retry < longRetries; retry++)
959  {
960  //Add one re-transmission (DATA + ACK timeout)
961  tt += dataTransmissionTime + GetMac ()->GetAckTimeout ();
962 
963  //Add average back off (half the current contention window)
964  tt += NanoSeconds ((cw / 2) * GetMac ()->GetSlot ());
965 
966  //Update contention window
967  cw = std::min (cwMax, (cw + 1) * 2);
968  }
969 
970  return tt;
971 }
972 
973 void
975 {
976  NS_LOG_FUNCTION (this << station);
977  station->m_col = station->m_index = 0;
978 
979  //for off-setting to make rates fall between 0 and nModes
980  uint8_t numSampleRates = station->m_nModes;
981 
982  uint32_t newIndex;
983  for (uint32_t col = 0; col < m_sampleCol; col++)
984  {
985  for (uint8_t i = 0; i < numSampleRates; i++ )
986  {
991  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
992  NS_LOG_DEBUG ("InitSampleTable uv: " << uv);
993  newIndex = (i + uv) % numSampleRates;
994 
995  //this loop is used for filling in other uninitialized places
996  while (station->m_sampleTable[newIndex][col] != 0)
997  {
998  newIndex = (newIndex + 1) % station->m_nModes;
999  }
1000  station->m_sampleTable[newIndex][col] = i;
1001  }
1002  }
1003 }
1004 
1005 void
1007 {
1008  NS_LOG_FUNCTION (this << station);
1009  uint8_t numSampleRates = station->m_nModes;
1010  std::stringstream table;
1011  for (uint8_t i = 0; i < numSampleRates; i++)
1012  {
1013  for (uint32_t j = 0; j < m_sampleCol; j++)
1014  {
1015  table << station->m_sampleTable[i][j] << "\t";
1016  }
1017  table << std::endl;
1018  }
1019  NS_LOG_DEBUG (table.str ());
1020 }
1021 
1022 void
1024 {
1025  NS_LOG_FUNCTION (this << station);
1026  NS_LOG_DEBUG ("PrintTable=" << station);
1027 
1028  station->m_statsFile << "best _______________rate________________ ________statistics________ ________last_______ ______sum-of________\n" <<
1029  "rate [ name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1030 
1031  uint32_t maxTpRate = station->m_maxTpRate;
1032  uint32_t maxTpRate2 = station->m_maxTpRate2;
1033  uint32_t maxProbRate = station->m_maxProbRate;
1034 
1035  for (uint8_t i = 0; i < station->m_nModes; i++)
1036  {
1037  RateInfo rate = station->m_minstrelTable[i];
1038 
1039  if (i == maxTpRate)
1040  {
1041  station->m_statsFile << 'A';
1042  }
1043  else
1044  {
1045  station->m_statsFile << ' ';
1046  }
1047  if (i == maxTpRate2)
1048  {
1049  station->m_statsFile << 'B';
1050  }
1051  else
1052  {
1053  station->m_statsFile << ' ';
1054  }
1055  if (i == maxProbRate)
1056  {
1057  station->m_statsFile << 'P';
1058  }
1059  else
1060  {
1061  station->m_statsFile << ' ';
1062  }
1063 
1064  float tmpTh = rate.throughput / 100000.0f;
1065  station->m_statsFile << " " <<
1066  std::setw (17) << GetSupported (station, i) << " " <<
1067  std::setw (2) << i << " " <<
1068  std::setw (4) << rate.perfectTxTime.GetMicroSeconds () <<
1069  std::setw (8) << " ----- " <<
1070  std::setw (8) << tmpTh << " " <<
1071  std::setw (3) << rate.ewmaProb / 180 <<
1072  std::setw (3) << " --- " <<
1073  std::setw (3) << rate.prob / 180 << " " <<
1074  std::setw (1) << rate.adjustedRetryCount << " " <<
1075  std::setw (3) << rate.prevNumRateSuccess << " " <<
1076  std::setw (3) << rate.prevNumRateAttempt << " " <<
1077  std::setw (9) << rate.successHist << " " <<
1078  std::setw (9) << rate.attemptHist << "\n";
1079  }
1080  station->m_statsFile << "\nTotal packet count: ideal " << station->m_totalPacketsCount - station->m_samplePacketsCount
1081  << " lookaround " << station->m_samplePacketsCount << "\n\n";
1082 
1083  station->m_statsFile.flush ();
1084 }
1085 
1086 void
1088 {
1089  //HT is not supported by this algorithm.
1090  if (enable)
1091  {
1092  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HT rates");
1093  }
1094 }
1095 
1096 void
1098 {
1099  //VHT is not supported by this algorithm.
1100  if (enable)
1101  {
1102  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support VHT rates");
1103  }
1104 }
1105 
1106 void
1108 {
1109  //HE is not supported by this algorithm.
1110  if (enable)
1111  {
1112  NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates");
1113  }
1114 }
1115 
1116 } //namespace ns3
void CheckInit(MinstrelWifiRemoteStation *station)
check for initializations
void PrintTable(MinstrelWifiRemoteStation *station)
printing Minstrel Table
WifiTxVector DoGetDataTxVector(WifiRemoteStation *station)
void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
bool m_printStats
If statistics table should be printed.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time perfectTxTime
Perfect transmission time calculation, or frame calculation Given a bit rate and a packet length n by...
#define min(a, b)
Definition: 80211b.c:44
Implementation of Minstrel Rate Control AlgorithmMinstrel is a rate control algorithm implemented in ...
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:84
void DoReportFinalDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
hold per-remote-station state for Minstrel Wifi manager.
Time m_updateStats
how frequent do we calculate the stats (1/10 seconds)
void UpdateStats(MinstrelWifiRemoteStation *station)
updating the Minstrel Table every 1/10 seconds
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t m_sampleRate
current sample rate
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1015
uint32_t GetNextSample(MinstrelWifiRemoteStation *station)
getting the next sample from Sample Table
Mac48Address m_address
Mac48Address of the remote station.
bool DoNeedDataRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally)
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
uint32_t m_txrate
current transmit rate
MinstrelRate m_minstrelTable
minstrel table
std::ofstream m_statsFile
stats file
bool m_sampleDeferred
a flag to indicate sample rate is on the second stage
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1260
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
std::vector< RateInfo > MinstrelRate
Data structure for a Minstrel Rate table A vector of a struct RateInfo.
TracedValue< uint64_t > m_currentRate
Trace rate changes.
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
uint8_t m_nModes
number of modes supported
uint32_t FindRate(MinstrelWifiRemoteStation *station)
find a rate to use from Minstrel Table
uint32_t m_pktLen
packet length used for calculate mode TxTime
WifiRemoteStationState * m_state
Remote station state.
void SetHeSupported(bool enable)
Enable or disable HE capability support.
uint32_t adjustedRetryCount
adjust the retry limit for this rate
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr)
This method is a pure virtual method that must be implemented by the sub-class.
void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode)
This method is a pure virtual method that must be implemented by the sub-class.
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2301
A struct to contain all information related to a data rate.
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
tuple phy
Definition: third.py:86
void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
bool m_isSampling
a flag to indicate we are currently sampling
int m_numSamplesDeferred
number samles deferred
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:363
void SetHtSupported(bool enable)
Enable or disable HT capability support.
AttributeValue implementation for Time.
Definition: nstime.h:1069
SampleRate m_sampleTable
sample table
uint8_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1031
uint32_t prevNumRateSuccess
Number of successful frames transmitted with previous rate.
Hold an unsigned integer type.
Definition: uinteger.h:44
WifiPreamble GetPreambleForTransmission(WifiMode mode, Mac48Address dest)
Return the preamble to be used for the transmission.
uint64_t GetDataRate(uint8_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:143
void PrintSampleTable(MinstrelWifiRemoteStation *station)
printing Sample Table
uint8_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
uint32_t prevNumRateAttempt
Number of transmission attempts with previous rate.
WifiMode GetMode(uint8_t mode) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3576
uint64_t attemptHist
Aggregate of all transmission attempts.
double m_ewmaLevel
exponential weighted moving average
uint64_t successHist
Aggregate of all transmission successes.
WifiRemoteStation * DoCreateStation(void) const
Mac48Address GetAddress(const WifiRemoteStation *station) const
Return the address of the station.
void AddCalcTxTime(WifiMode mode, Time t)
Add transmission time for the given mode to an internal list.
tuple mac
Definition: third.py:92
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
void DoReportFinalRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
hold a list of per-remote-station state.
WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)
uint32_t m_longRetry
long retries such as data packets
bool m_initialized
for initializing tables
uint32_t ewmaProb
EWMA calculation ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100.
TxTime m_calcTxTime
to hold all the calculated TxTime for all modes
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void UpdateRate(MinstrelWifiRemoteStation *station)
updating the rate
uint32_t m_maxTpRate2
second highest throughput rate
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
WifiTxVector GetDataTxVector(MinstrelWifiRemoteStation *station)
Get data transmit vector.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:1070
uint32_t throughput
throughput of a rate
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
uint32_t m_retry
total retries short + long
int m_totalPacketsCount
total number of packets as of now
WifiMode GetSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether mode associated with the specified station at the specified index. ...
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void UpdateRetry(MinstrelWifiRemoteStation *station)
update the number of retries and reset accordingly
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
double m_lookAroundRate
the % to try other rates than our current rate
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...
uint32_t m_maxProbRate
rate with highest prob of success
WifiMode GetNonErpSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether non-ERP mode associated with the specified station at the specified index...
if(desigRtr==addrLocal)
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
void DoReportRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
WifiTxVector GetRtsTxVector(MinstrelWifiRemoteStation *station)
Get RTS transmit vector.
void SetVhtSupported(bool enable)
Enable or disable VHT capability support.
uint32_t m_maxTpRate
the current throughput rate
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
uint32_t CountRetries(MinstrelWifiRemoteStation *station)
Count retries.
Time GetCalcTxTime(WifiMode mode) const
for estimating the TxTime of a packet with a given mode
void DoReportDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
uint8_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
uint32_t m_sampleCol
number of sample columns
uint32_t m_shortRetry
short retries such as control packts
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
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
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:914
std::vector< std::vector< uint32_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint32_t.
hold per-remote-station state.
uint8_t GetNModes(void) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3570
uint32_t prob
(# pkts success )/(# total pkts)
Ptr< WifiMac > GetMac(void) const
Return the WifiMac.
void UpdatePacketCounters(MinstrelWifiRemoteStation *station)
Update packet counters.
Time m_nextStatsUpdate
10 times every second