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