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