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