A Discrete-Event Network Simulator
API
minstrel-ht-wifi-manager.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 Duy Nguyen
4  * Copyright (c) 2015 Ghada Badawy
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Duy Nguyen <duy@soe.ucsc.edu>
20  * Ghada Badawy <gbadawy@gmail.com>
21  * Matias Richart <mrichart@fing.edu.uy>
22  *
23  * Some Comments:
24  *
25  * 1) By default, Minstrel applies the multi-rate retry (the core of Minstrel
26  * algorithm). Otherwise, please use ConstantRateWifiManager instead.
27  *
28  * 2) Sampling is done differently from legacy Minstrel. Minstrel-HT tries
29  * to sample all rates in all groups at least once and to avoid many
30  * consecutive samplings.
31  *
32  * 3) Sample rate is tried only once, at first place of the MRR chain.
33  *
34  * reference: http://lwn.net/Articles/376765/
35  */
36 
37 #include <iomanip>
38 #include "ns3/packet.h"
39 #include "ns3/simulator.h"
40 #include "ns3/log.h"
41 #include "ns3/random-variable-stream.h"
43 #include "ns3/wifi-mac.h"
44 #include "ns3/wifi-phy.h"
45 
46 #define Min(a,b) ((a < b) ? a : b)
47 #define Max(a,b) ((a > b) ? a : b)
48 
49 NS_LOG_COMPONENT_DEFINE ("MinstrelHtWifiManager");
50 
51 namespace ns3 {
52 
55 {
56  uint8_t m_sampleGroup;
57 
58  uint32_t m_sampleWait;
59  uint32_t m_sampleTries;
60  uint32_t m_sampleCount;
61  uint32_t m_numSamplesSlow;
62 
63  uint32_t m_avgAmpduLen;
64  uint32_t m_ampduLen;
65  uint32_t m_ampduPacketCount;
66 
68  bool m_isHt;
69 
70  std::ofstream m_statsFile;
71 };
72 
74 
75 TypeId
77 {
78  static TypeId tid = TypeId ("ns3::MinstrelHtWifiManager")
80  .AddConstructor<MinstrelHtWifiManager> ()
81  .SetGroupName ("Wifi")
82  .AddAttribute ("UpdateStatistics",
83  "The interval between updating statistics table ",
84  TimeValue (MilliSeconds (50)),
86  MakeTimeChecker ())
87  .AddAttribute ("LegacyUpdateStatistics",
88  "The interval between updating statistics table (for legacy Minstrel) ",
89  TimeValue (MilliSeconds (100)),
91  MakeTimeChecker ())
92  .AddAttribute ("LookAroundRate",
93  "The percentage to try other rates (for legacy Minstrel)",
94  UintegerValue (10),
96  MakeUintegerChecker<uint8_t>(0, 100))
97  .AddAttribute ("EWMA",
98  "EWMA level",
99  UintegerValue (75),
101  MakeUintegerChecker<uint8_t>(0, 100))
102  .AddAttribute ("SampleColumn",
103  "The number of columns used for sampling",
104  UintegerValue (10),
106  MakeUintegerChecker <uint8_t> ())
107  .AddAttribute ("PacketLength",
108  "The packet length used for calculating mode TxTime (bytes)",
109  UintegerValue (1200),
111  MakeUintegerChecker <uint32_t> ())
112  .AddAttribute ("UseLatestAmendmentOnly",
113  "Use only the latest amendment when it is supported by both peers",
114  BooleanValue (true),
117  .AddAttribute ("PrintStats",
118  "Control the printing of the statistics table",
119  BooleanValue (false),
122  .AddTraceSource ("Rate",
123  "Traced value for rate changes (b/s)",
125  "ns3::TracedValueCallback::Uint64")
126  ;
127  return tid;
128 }
129 
131  : m_numGroups (0),
132  m_numRates (0),
133  m_currentRate (0)
134 {
135  NS_LOG_FUNCTION (this);
136  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
141  m_legacyManager = CreateObject<MinstrelWifiManager> ();
142 }
143 
145 {
146  NS_LOG_FUNCTION (this);
147  for (uint8_t i = 0; i < m_numGroups; i++)
148  {
149  m_minstrelGroups[i].ratesFirstMpduTxTimeTable.clear ();
150  m_minstrelGroups[i].ratesTxTimeTable.clear ();
151  }
152 }
153 
154 int64_t
156 {
157  NS_LOG_FUNCTION (this << stream);
158  int64_t numStreamsAssigned = 0;
160  numStreamsAssigned++;
161  numStreamsAssigned += m_legacyManager->AssignStreams (stream);
162  return numStreamsAssigned;
163 }
164 
165 void
167 {
168  NS_LOG_FUNCTION (this << phy);
169  // Setup PHY for legacy manager.
170  m_legacyManager->SetupPhy (phy);
172 }
173 
174 void
176 {
177  NS_LOG_FUNCTION (this << mac);
178  m_legacyManager->SetupMac (mac);
180 }
181 
182 void
184 {
185  NS_LOG_FUNCTION (this);
192  if (GetHtSupported ())
193  {
196  if (GetVhtSupported ())
197  {
200  }
201  if (GetHeSupported ())
202  {
205  }
206 
217  NS_LOG_DEBUG ("Initialize MCS Groups:");
219 
220  // Initialize all HT groups
221  for (uint16_t chWidth = 20; chWidth <= MAX_HT_WIDTH; chWidth *= 2)
222  {
223  for (int gi = 800; gi >= 400; )
224  {
225  for (uint8_t streams = 1; streams <= MAX_HT_SUPPORTED_STREAMS; streams++)
226  {
227  uint8_t groupId = GetHtGroupId (streams, gi, chWidth);
228 
229  m_minstrelGroups[groupId].streams = streams;
230  m_minstrelGroups[groupId].gi = gi;
231  m_minstrelGroups[groupId].chWidth = chWidth;
232  m_minstrelGroups[groupId].type = GROUP_HT;
233  m_minstrelGroups[groupId].isSupported = false;
234 
235  // Check capabilities of the device
236  if (!(!GetShortGuardIntervalSupported () && (gi == 400))
237  && (GetPhy ()->GetChannelWidth () >= chWidth)
238  && (GetPhy ()->GetMaxSupportedTxSpatialStreams () >= streams))
239  {
240  m_minstrelGroups[groupId].isSupported = true;
241 
242  // Calculate TX time for all rates of the group
243  WifiModeList htMcsList = GetHtDeviceMcsList ();
244  for (uint8_t i = 0; i < MAX_HT_GROUP_RATES; i++)
245  {
246  uint16_t deviceIndex = i + (m_minstrelGroups[groupId].streams - 1) * 8;
247  WifiMode mode = htMcsList[deviceIndex];
248  AddFirstMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, FIRST_MPDU_IN_AGGREGATE));
249  AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, MIDDLE_MPDU_IN_AGGREGATE));
250  }
251  NS_LOG_DEBUG ("Initialized group " << +groupId << ": (" << +streams << "," << gi << "," << chWidth << ")");
252  }
253  }
254  gi /= 2;
255  }
256  }
257 
258  if (GetVhtSupported ())
259  {
260  // Initialize all VHT groups
261  for (uint16_t chWidth = 20; chWidth <= MAX_VHT_WIDTH; chWidth *= 2)
262  {
263  for (int gi = 800; gi >= 400; )
264  {
265  for (uint8_t streams = 1; streams <= MAX_VHT_SUPPORTED_STREAMS; streams++)
266  {
267  uint8_t groupId = GetVhtGroupId (streams, gi, chWidth);
268 
269  m_minstrelGroups[groupId].streams = streams;
270  m_minstrelGroups[groupId].gi = gi;
271  m_minstrelGroups[groupId].chWidth = chWidth;
272  m_minstrelGroups[groupId].type = GROUP_VHT;
273  m_minstrelGroups[groupId].isSupported = false;
274 
275  // Check capabilities of the device
276  if (!(!GetShortGuardIntervalSupported () && (gi == 400))
277  && (GetPhy ()->GetChannelWidth () >= chWidth)
278  && (GetPhy ()->GetMaxSupportedTxSpatialStreams () >= streams))
279  {
280  m_minstrelGroups[groupId].isSupported = true;
281 
282  // Calculate TX time for all rates of the group
283  WifiModeList vhtMcsList = GetVhtDeviceMcsList ();
284  for (uint8_t i = 0; i < MAX_VHT_GROUP_RATES; i++)
285  {
286  WifiMode mode = vhtMcsList[i];
287  // Check for invalid VHT MCSs and do not add time to array.
288  if (IsValidMcs (GetPhy (), streams, chWidth, mode))
289  {
290  AddFirstMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, FIRST_MPDU_IN_AGGREGATE));
291  AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, MIDDLE_MPDU_IN_AGGREGATE));
292  }
293  }
294  NS_LOG_DEBUG ("Initialized group " << +groupId << ": (" << +streams << "," << gi << "," << chWidth << ")");
295  }
296  }
297  gi /= 2;
298  }
299  }
300  }
301 
302  if (GetHeSupported ())
303  {
304  // Initialize all HE groups
305  for (uint16_t chWidth = 20; chWidth <= MAX_HE_WIDTH; chWidth *= 2)
306  {
307  for (int gi = 3200; gi >= 800; )
308  {
309  for (uint8_t streams = 1; streams <= MAX_HE_SUPPORTED_STREAMS; streams++)
310  {
311  uint8_t groupId = GetHeGroupId (streams, gi, chWidth);
312 
313  m_minstrelGroups[groupId].streams = streams;
314  m_minstrelGroups[groupId].gi = gi;
315  m_minstrelGroups[groupId].chWidth = chWidth;
316  m_minstrelGroups[groupId].type = GROUP_HE;
317  m_minstrelGroups[groupId].isSupported = false;
318 
319  // Check capabilities of the device
320  if ((GetGuardInterval () <= gi)
321  && (GetPhy ()->GetChannelWidth () >= chWidth)
322  && (GetPhy ()->GetMaxSupportedTxSpatialStreams () >= streams))
323  {
324  m_minstrelGroups[groupId].isSupported = true;
325 
326  // Calculate tx time for all rates of the group
327  WifiModeList heMcsList = GetHeDeviceMcsList ();
328  for (uint8_t i = 0; i < MAX_HE_GROUP_RATES; i++)
329  {
330  WifiMode mode = heMcsList.at (i);
331  // Check for invalid HE MCSs and do not add time to array.
332  if (IsValidMcs (GetPhy (), streams, chWidth, mode))
333  {
334  AddFirstMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, FIRST_MPDU_IN_AGGREGATE));
335  AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, gi, chWidth, mode, MIDDLE_MPDU_IN_AGGREGATE));
336  }
337  }
338  NS_LOG_DEBUG ("Initialized group " << +groupId << ": (" << +streams << "," << gi << "," << chWidth << ")");
339  }
340  }
341  gi /= 2;
342  }
343  }
344  }
345  }
346 }
347 
348 bool
349 MinstrelHtWifiManager::IsValidMcs (Ptr<WifiPhy> phy, uint8_t streams, uint16_t chWidth, WifiMode mode)
350 {
351  NS_LOG_FUNCTION (this << phy << +streams << chWidth << mode);
352  WifiTxVector txvector;
353  txvector.SetNss (streams);
354  txvector.SetChannelWidth (chWidth);
355  txvector.SetMode (mode);
356  return txvector.IsValid ();
357 }
358 
359 Time
361  uint16_t chWidth, WifiMode mode, MpduType mpduType)
362 {
363  NS_LOG_FUNCTION (this << phy << +streams << gi << chWidth << mode << mpduType);
364  WifiTxVector txvector;
365  txvector.SetNss (streams);
366  txvector.SetGuardInterval (gi);
367  txvector.SetChannelWidth (chWidth);
368  txvector.SetNess (0);
369  txvector.SetStbc (0);
370  txvector.SetMode (mode);
373  + WifiPhy::GetPayloadDuration (m_frameLength, txvector, phy->GetPhyBand (), mpduType);
374 }
375 
376 Time
378 {
379  NS_LOG_FUNCTION (this << +groupId << mode);
380  auto it = m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.find (mode);
381  NS_ASSERT (it != m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.end ());
382  return it->second;
383 }
384 
385 void
387 {
388  NS_LOG_FUNCTION (this << +groupId << mode << t);
389  m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.insert (std::make_pair (mode, t));
390 }
391 
392 Time
393 MinstrelHtWifiManager::GetMpduTxTime (uint8_t groupId, WifiMode mode) const
394 {
395  NS_LOG_FUNCTION (this << +groupId << mode);
396  auto it = m_minstrelGroups[groupId].ratesTxTimeTable.find (mode);
397  NS_ASSERT (it != m_minstrelGroups[groupId].ratesTxTimeTable.end ());
398  return it->second;
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION (this << +groupId << mode << t);
405  m_minstrelGroups[groupId].ratesTxTimeTable.insert (std::make_pair (mode, t));
406 }
407 
410 {
411  NS_LOG_FUNCTION (this);
413 
414  // Initialize variables common to both stations.
416  station->m_col = 0;
417  station->m_index = 0;
418  station->m_maxTpRate = 0;
419  station->m_maxTpRate2 = 0;
420  station->m_maxProbRate = 0;
421  station->m_nModes = 0;
422  station->m_totalPacketsCount = 0;
423  station->m_samplePacketsCount = 0;
424  station->m_isSampling = false;
425  station->m_sampleRate = 0;
426  station->m_sampleDeferred = false;
427  station->m_shortRetry = 0;
428  station->m_longRetry = 0;
429  station->m_txrate = 0;
430  station->m_initialized = false;
431 
432  // Variables specific to HT station
433  station->m_sampleGroup = 0;
434  station->m_numSamplesSlow = 0;
435  station->m_sampleCount = 16;
436  station->m_sampleWait = 0;
437  station->m_sampleTries = 4;
438 
439  station->m_avgAmpduLen = 1;
440  station->m_ampduLen = 0;
441  station->m_ampduPacketCount = 0;
442 
443  // If the device supports HT
444  if (GetHtSupported ())
445  {
450  station->m_isHt = true;
451  }
452  // Use the variable in the station to indicate that the device do not support HT
453  else
454  {
455  station->m_isHt = false;
456  }
457 
458  return station;
459 }
460 
461 void
463 {
464  NS_LOG_FUNCTION (this << station);
465  // Note: we appear to be doing late initialization of the table
466  // to make sure that the set of supported rates has been initialized
467  // before we perform our own initialization.
468  if (!station->m_initialized)
469  {
476  if (!GetHtSupported (station))
477  {
478  NS_LOG_INFO ("non-HT station " << station);
479  station->m_isHt = false;
480  // We will use non-HT minstrel for this station. Initialize the manager.
481  m_legacyManager->SetAttribute ("UpdateStatistics", TimeValue (m_legacyUpdateStats));
482  m_legacyManager->SetAttribute ("LookAroundRate", UintegerValue (m_lookAroundRate));
483  m_legacyManager->SetAttribute ("EWMA", UintegerValue (m_ewmaLevel));
484  m_legacyManager->SetAttribute ("SampleColumn", UintegerValue (m_nSampleCol));
485  m_legacyManager->SetAttribute ("PacketLength", UintegerValue (m_frameLength));
486  m_legacyManager->SetAttribute ("PrintStats", BooleanValue (m_printStats));
487  m_legacyManager->CheckInit (station);
488  }
489  else
490  {
491  NS_LOG_DEBUG ("HT station " << station);
492  station->m_isHt = true;
493  station->m_nModes = GetNMcsSupported (station);
494  station->m_minstrelTable = MinstrelRate (station->m_nModes);
495  station->m_sampleTable = SampleRate (m_numRates, std::vector<uint8_t> (m_nSampleCol));
496  InitSampleTable (station);
497  RateInit (station);
498  station->m_initialized = true;
499  }
500  }
501 }
502 
503 void
505 {
506  NS_LOG_FUNCTION (this << st);
507  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << static_cast<MinstrelHtWifiRemoteStation*> (st)->m_txrate);
508 }
509 
510 void
512 {
513  NS_LOG_FUNCTION (this << st);
514  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
515  CheckInit (station);
516  if (!station->m_initialized)
517  {
518  return;
519  }
520  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate = " << station->m_txrate);
521  station->m_shortRetry++;
522 }
523 
524 void
525 MinstrelHtWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
526 {
527  NS_LOG_FUNCTION (this << st);
528 }
529 
530 void
532 {
533  NS_LOG_FUNCTION (this << st);
534  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
535  NS_LOG_DEBUG ("Final RTS failed");
536  CheckInit (station);
537  if (!station->m_initialized)
538  {
539  return;
540  }
541  UpdateRetry (station);
542 }
543 
544 void
546 {
547  NS_LOG_FUNCTION (this << st);
548  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
549 
550  CheckInit (station);
551  if (!station->m_initialized)
552  {
553  return;
554  }
555 
556  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
557 
558  if (!station->m_isHt)
559  {
560  m_legacyManager->UpdateRate (station);
561  }
562  else if (station->m_longRetry < CountRetries (station))
563  {
564  uint8_t rateId = GetRateId (station->m_txrate);
565  uint8_t groupId = GetGroupId (station->m_txrate);
566  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++; // Increment the attempts counter for the rate used.
567  UpdateRate (station);
568  }
569 }
570 
571 void
573  double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss)
574 {
575  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr << dataChannelWidth << +dataNss);
576  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
577 
578  CheckInit (station);
579  if (!station->m_initialized)
580  {
581  return;
582  }
583 
584  NS_LOG_DEBUG ("DoReportDataOk m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (before update).");
585 
586  if (!station->m_isHt)
587  {
588  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
589  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
590 
591  m_legacyManager->UpdatePacketCounters (station);
592 
593  NS_LOG_DEBUG ("DoReportDataOk m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (after update).");
594 
595  UpdateRetry (station);
596  m_legacyManager->UpdateStats (station);
597 
598  if (station->m_nModes >= 1)
599  {
600  station->m_txrate = m_legacyManager->FindRate (station);
601  }
602  }
603  else
604  {
605  uint8_t rateId = GetRateId (station->m_txrate);
606  uint8_t groupId = GetGroupId (station->m_txrate);
607  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess++;
608  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++;
609 
610  UpdatePacketCounters (station, 1, 0);
611 
612  NS_LOG_DEBUG ("DoReportDataOk m_txrate = " << station->m_txrate << ", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt << ", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess << " (after update).");
613 
614  station->m_isSampling = false;
615  station->m_sampleDeferred = false;
616 
617  UpdateRetry (station);
618  if (Simulator::Now () >= station->m_nextStatsUpdate)
619  {
620  UpdateStats (station);
621  }
622 
623  if (station->m_nModes >= 1)
624  {
625  station->m_txrate = FindRate (station);
626  }
627  }
628 
629  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
630 }
631 
632 void
634 {
635  NS_LOG_FUNCTION (this << st);
636  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
637 
638  CheckInit (station);
639  if (!station->m_initialized)
640  {
641  return;
642  }
643 
644  NS_LOG_DEBUG ("DoReportFinalDataFailed - TxRate=" << station->m_txrate);
645 
646  if (!station->m_isHt)
647  {
648  m_legacyManager->UpdatePacketCounters (station);
649 
650  UpdateRetry (station);
651 
652  m_legacyManager->UpdateStats (station);
653  if (station->m_nModes >= 1)
654  {
655  station->m_txrate = m_legacyManager->FindRate (station);
656  }
657  }
658  else
659  {
660  UpdatePacketCounters (station, 0, 1);
661 
662  station->m_isSampling = false;
663  station->m_sampleDeferred = false;
664 
665  UpdateRetry (station);
666  if (Simulator::Now () >= station->m_nextStatsUpdate)
667  {
668  UpdateStats (station);
669  }
670 
671  if (station->m_nModes >= 1)
672  {
673  station->m_txrate = FindRate (station);
674  }
675  }
676  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
677 }
678 
679 void
680 MinstrelHtWifiManager::DoReportAmpduTxStatus (WifiRemoteStation *st, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus,
681  double rxSnr, double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss)
682 {
683  NS_LOG_FUNCTION (this << st << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr << dataChannelWidth << +dataNss);
684  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
685 
686  CheckInit (station);
687  if (!station->m_initialized)
688  {
689  return;
690  }
691 
692  NS_ASSERT_MSG (station->m_isHt, "A-MPDU Tx Status called but this is a non-HT STA.");
693 
694  NS_LOG_DEBUG ("DoReportAmpduTxStatus. TxRate=" << station->m_txrate << " SuccMpdus=" <<
695  nSuccessfulMpdus << " FailedMpdus=" << nFailedMpdus);
696 
697  station->m_ampduPacketCount++;
698  station->m_ampduLen += nSuccessfulMpdus + nFailedMpdus;
699 
700  UpdatePacketCounters (station, nSuccessfulMpdus, nFailedMpdus);
701 
702  uint8_t rateId = GetRateId (station->m_txrate);
703  uint8_t groupId = GetGroupId (station->m_txrate);
704  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess += nSuccessfulMpdus;
705  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt += nSuccessfulMpdus + nFailedMpdus;
706 
707  if (nSuccessfulMpdus == 0 && station->m_longRetry < CountRetries (station))
708  {
709  // We do not receive a BlockAck. The entire AMPDU fail.
710  UpdateRate (station);
711  }
712  else
713  {
714  station->m_isSampling = false;
715  station->m_sampleDeferred = false;
716 
717  UpdateRetry (station);
718  if (Simulator::Now () >= station->m_nextStatsUpdate)
719  {
720  UpdateStats (station);
721  }
722 
723  if (station->m_nModes >= 1)
724  {
725  station->m_txrate = FindRate (station);
726  }
727  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
728  }
729 }
730 
731 void
733 {
734  NS_LOG_FUNCTION (this << station);
735 
757  CheckInit (station);
758  if (!station->m_initialized)
759  {
760  return;
761  }
762  station->m_longRetry++;
763 
767  uint8_t maxTpRateId = GetRateId (station->m_maxTpRate);
768  uint8_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
769  uint8_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
770  uint8_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
771  uint8_t maxProbRateId = GetRateId (station->m_maxProbRate);
772  uint8_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
773 
775  if (!station->m_isSampling)
776  {
778  if (station->m_longRetry < station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount)
779  {
780  NS_LOG_DEBUG ("Not Sampling; use the same rate again");
781  station->m_txrate = station->m_maxTpRate;
782  }
783 
785  else if (station->m_longRetry < ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
786  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount))
787  {
788  NS_LOG_DEBUG ("Not Sampling; use the Max TP2");
789  station->m_txrate = station->m_maxTpRate2;
790  }
791 
793  else if (station->m_longRetry <= ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
794  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
795  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount))
796  {
797  NS_LOG_DEBUG ("Not Sampling; use Max Prob");
798  station->m_txrate = station->m_maxProbRate;
799  }
800  else
801  {
802  NS_FATAL_ERROR ("Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry);
803  }
804  }
805 
807  else
808  {
811  if (station->m_longRetry < 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount)
812  {
813  NS_LOG_DEBUG ("Sampling use the MaxTP rate");
814  station->m_txrate = station->m_maxTpRate2;
815  }
816 
818  else if (station->m_longRetry <= 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
819  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount)
820  {
821  NS_LOG_DEBUG ("Sampling use the MaxProb rate");
822  station->m_txrate = station->m_maxProbRate;
823  }
824  else
825  {
826  NS_FATAL_ERROR ("Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry);
827  }
828  }
829  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
830 }
831 
832 void
834 {
835  NS_LOG_FUNCTION (this << station);
836  station->m_shortRetry = 0;
837  station->m_longRetry = 0;
838 }
839 
840 void
841 MinstrelHtWifiManager::UpdatePacketCounters (MinstrelHtWifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus)
842 {
843  NS_LOG_FUNCTION (this << station << nSuccessfulMpdus << nFailedMpdus);
844 
845  station->m_totalPacketsCount += nSuccessfulMpdus + nFailedMpdus;
846  if (station->m_isSampling)
847  {
848  station->m_samplePacketsCount += nSuccessfulMpdus + nFailedMpdus;
849  }
850  if (station->m_totalPacketsCount == ~0)
851  {
852  station->m_samplePacketsCount = 0;
853  station->m_totalPacketsCount = 0;
854  }
855 
856  if (!station->m_sampleWait && !station->m_sampleTries && station->m_sampleCount > 0)
857  {
858  station->m_sampleWait = 16 + 2 * station->m_avgAmpduLen;
859  station->m_sampleTries = 1;
860  station->m_sampleCount--;
861  }
862 }
863 
866 {
867  NS_LOG_FUNCTION (this << st);
868  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
869 
870  if (!station->m_initialized)
871  {
872  CheckInit (station);
873  }
874 
875  if (!station->m_isHt)
876  {
877  WifiTxVector vector = m_legacyManager->GetDataTxVector (station);
878  uint64_t dataRate = vector.GetMode ().GetDataRate (vector);
879  if (m_currentRate != dataRate && !station->m_isSampling)
880  {
881  NS_LOG_DEBUG ("New datarate: " << dataRate);
882  m_currentRate = dataRate;
883  }
884  return vector;
885  }
886  else
887  {
888  NS_LOG_DEBUG ("DoGetDataMode m_txrate= " << station->m_txrate);
889 
890  uint8_t rateId = GetRateId (station->m_txrate);
891  uint8_t groupId = GetGroupId (station->m_txrate);
892  uint8_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
893 
894  NS_LOG_DEBUG ("DoGetDataMode rateId= " << +rateId << " groupId= " << +groupId << " mode= " << GetMcsSupported (station, mcsIndex));
895 
896  McsGroup group = m_minstrelGroups[groupId];
897 
898  // Check consistency of rate selected.
899  if (((group.type == GROUP_HE) && (group.gi < GetGuardInterval (station))) ||
900  (((group.type == GROUP_HT) || (group.type == GROUP_VHT)) && (group.gi == 400) && !GetShortGuardIntervalSupported (station)) ||
901  (group.chWidth > GetChannelWidth (station)) ||
902  (group.streams > GetNumberOfSupportedStreams (station)))
903  {
904  NS_FATAL_ERROR ("Inconsistent group selected. Group: (" << +group.streams <<
905  "," << group.gi << "," << group.chWidth << ")" <<
906  " Station capabilities: (" << GetNumberOfSupportedStreams (station) <<
907  "," << ((group.type == GROUP_HE) ? GetGuardInterval (station) : (GetShortGuardIntervalSupported (station) ? 400 : 800)) <<
908  "," << GetChannelWidth (station) << ")");
909  }
910  WifiMode mode = GetMcsSupported (station, mcsIndex);
911  uint64_t dataRate = mode.GetDataRate (group.chWidth, group.gi, group.streams);
912  if (m_currentRate != dataRate && !station->m_isSampling)
913  {
914  NS_LOG_DEBUG ("New datarate: " << dataRate);
915  m_currentRate = dataRate;
916  }
918  }
919 }
920 
923 {
924  NS_LOG_FUNCTION (this << st);
925  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
926 
927  if (!station->m_initialized)
928  {
929  CheckInit (station);
930  }
931 
932  if (!station->m_isHt)
933  {
934  return m_legacyManager->GetRtsTxVector (station);
935  }
936  else
937  {
938  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
939 
940  /* RTS is sent in a non-HT frame. RTS with HT is not supported yet in NS3.
941  * When supported, decision of using HT has to follow rules in Section 9.7.6 from 802.11-2012.
942  * From Sec. 9.7.6.5: "A frame other than a BlockAckReq or BlockAck that is carried in a
943  * non-HT PPDU shall be transmitted by the STA using a rate no higher than the highest
944  * rate in the BSSBasicRateSet parameter that is less than or equal to the rate or
945  * non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
946  * directed to the same receiving STA. If no rate in the BSSBasicRateSet parameter meets
947  * these conditions, the control frame shall be transmitted at a rate no higher than the
948  * highest mandatory rate of the attached PHY that is less than or equal to the rate
949  * or non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
950  * directed to the same receiving STA."
951  */
952 
953  // As we are in Minstrel HT, assume the last rate was an HT rate.
954  uint8_t rateId = GetRateId (station->m_txrate);
955  uint8_t groupId = GetGroupId (station->m_txrate);
956  uint8_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
957 
958  WifiMode lastRate = GetMcsSupported (station, mcsIndex);
959  uint64_t lastDataRate = lastRate.GetNonHtReferenceRate ();
960  uint8_t nBasicRates = GetNBasicModes ();
961 
962  WifiMode rtsRate;
963  bool rateFound = false;
964 
965  for (uint8_t i = 0; i < nBasicRates; i++)
966  {
967  uint64_t rate = GetBasicMode (i).GetDataRate (20);
968  if (rate <= lastDataRate)
969  {
970  rtsRate = GetBasicMode (i);
971  rateFound = true;
972  }
973  }
974 
975  if (!rateFound)
976  {
977  Ptr<WifiPhy> phy = GetPhy ();
978  for (const auto & mode : phy->GetModeList ())
979  {
980  uint64_t rate = mode.GetDataRate (20);
981  if (rate <= lastDataRate)
982  {
983  rtsRate = mode;
984  rateFound = true;
985  }
986  }
987  }
988 
989  NS_ASSERT (rateFound);
990 
992  800, 1, 1, 0, GetChannelWidthForTransmission (rtsRate, GetChannelWidth (station)), GetAggregation (station));
993  }
994 }
995 
996 bool
998 {
999  NS_LOG_FUNCTION (this << st << packet << normally);
1000 
1001  MinstrelHtWifiRemoteStation *station = static_cast<MinstrelHtWifiRemoteStation*> (st);
1002 
1003  CheckInit (station);
1004  if (!station->m_initialized)
1005  {
1006  return normally;
1007  }
1008 
1009  uint32_t maxRetries;
1010 
1011  if (!station->m_isHt)
1012  {
1013  maxRetries = m_legacyManager->CountRetries (station);
1014  }
1015  else
1016  {
1017  maxRetries = CountRetries (station);
1018  }
1019 
1020  if (station->m_longRetry >= maxRetries)
1021  {
1022  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << maxRetries);
1023  return false;
1024  }
1025  else
1026  {
1027  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << maxRetries);
1028  return true;
1029  }
1030 }
1031 
1032 uint32_t
1034 {
1035  uint8_t maxProbRateId = GetRateId (station->m_maxProbRate);
1036  uint8_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1037  uint8_t maxTpRateId = GetRateId (station->m_maxTpRate);
1038  uint8_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1039  uint8_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1040  uint8_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1041 
1042  if (!station->m_isSampling)
1043  {
1044  return station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
1045  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
1046  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1047  }
1048  else
1049  {
1050  return 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
1051  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1052  }
1053 }
1054 
1055 uint16_t
1057 {
1058  NS_LOG_FUNCTION (this << station);
1059  uint8_t sampleGroup = station->m_sampleGroup;
1060  uint8_t index = station->m_groupsTable[sampleGroup].m_index;
1061  uint8_t col = station->m_groupsTable[sampleGroup].m_col;
1062  uint8_t sampleIndex = station->m_sampleTable[index][col];
1063  uint16_t rateIndex = GetIndex (sampleGroup, sampleIndex);
1064  NS_LOG_DEBUG ("Next Sample is " << rateIndex);
1065  SetNextSample (station); //Calculate the next sample rate.
1066  return rateIndex;
1067 }
1068 
1069 void
1071 {
1072  NS_LOG_FUNCTION (this << station);
1073  do
1074  {
1075  station->m_sampleGroup++;
1076  station->m_sampleGroup %= m_numGroups;
1077  }
1078  while (!station->m_groupsTable[station->m_sampleGroup].m_supported);
1079 
1080  station->m_groupsTable[station->m_sampleGroup].m_index++;
1081 
1082  uint8_t sampleGroup = station->m_sampleGroup;
1083  uint8_t index = station->m_groupsTable[station->m_sampleGroup].m_index;
1084  uint8_t col = station->m_groupsTable[sampleGroup].m_col;
1085 
1086  if (index >= m_numRates)
1087  {
1088  station->m_groupsTable[station->m_sampleGroup].m_index = 0;
1089  station->m_groupsTable[station->m_sampleGroup].m_col++;
1090  if (station->m_groupsTable[station->m_sampleGroup].m_col >= m_nSampleCol)
1091  {
1092  station->m_groupsTable[station->m_sampleGroup].m_col = 0;
1093  }
1094  index = station->m_groupsTable[station->m_sampleGroup].m_index;
1095  col = station->m_groupsTable[sampleGroup].m_col;
1096  }
1097  NS_LOG_DEBUG ("New sample set: group= " << +sampleGroup << " index= " << +station->m_sampleTable[index][col]);
1098 }
1099 
1100 uint16_t
1102 {
1103  NS_LOG_FUNCTION (this << station);
1104  NS_LOG_DEBUG ("FindRate packet=" << station->m_totalPacketsCount);
1105 
1106  if ((station->m_samplePacketsCount + station->m_totalPacketsCount) == 0)
1107  {
1108  return station->m_maxTpRate;
1109  }
1110 
1111  // If we have waited enough, then sample.
1112  if (station->m_sampleWait == 0 && station->m_sampleTries != 0)
1113  {
1114  //SAMPLING
1115  NS_LOG_DEBUG ("Obtaining a sampling rate");
1117  uint16_t sampleIdx = GetNextSample (station);
1118  NS_LOG_DEBUG ("Sampling rate = " << sampleIdx);
1119 
1120  //Evaluate if the sampling rate selected should be used.
1121  uint8_t sampleGroupId = GetGroupId (sampleIdx);
1122  uint8_t sampleRateId = GetRateId (sampleIdx);
1123 
1124  // If the rate selected is not supported, then don't sample.
1125  if (station->m_groupsTable[sampleGroupId].m_supported && station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId].supported)
1126  {
1134  MinstrelHtRateInfo sampleRateInfo = station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId];
1135 
1136  NS_LOG_DEBUG ("Use sample rate? MaxTpRate= " << station->m_maxTpRate << " CurrentRate= " << station->m_txrate <<
1137  " SampleRate= " << sampleIdx << " SampleProb= " << sampleRateInfo.ewmaProb);
1138 
1139  if (sampleIdx != station->m_maxTpRate && sampleIdx != station->m_maxTpRate2
1140  && sampleIdx != station->m_maxProbRate && sampleRateInfo.ewmaProb <= 95)
1141  {
1142 
1148  uint8_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1149  uint8_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1150  uint8_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1151  uint8_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1152  uint8_t maxProbRateId = GetRateId (station->m_maxProbRate);
1153 
1154  uint8_t maxTpStreams = m_minstrelGroups[maxTpGroupId].streams;
1155  uint8_t sampleStreams = m_minstrelGroups[sampleGroupId].streams;
1156 
1157  Time sampleDuration = sampleRateInfo.perfectTxTime;
1158  Time maxTp2Duration = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].perfectTxTime;
1159  Time maxProbDuration = station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].perfectTxTime;
1160 
1161  NS_LOG_DEBUG ("Use sample rate? SampleDuration= " << sampleDuration << " maxTp2Duration= " << maxTp2Duration <<
1162  " maxProbDuration= " << maxProbDuration << " sampleStreams= " << +sampleStreams <<
1163  " maxTpStreams= " << +maxTpStreams);
1164  if (sampleDuration < maxTp2Duration || (sampleStreams < maxTpStreams && sampleDuration < maxProbDuration))
1165  {
1167  station->m_isSampling = true;
1168 
1170  station->m_sampleRate = sampleIdx;
1171 
1172  NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx);
1173  station->m_sampleTries--;
1174  return sampleIdx;
1175  }
1176  else
1177  {
1178  station->m_numSamplesSlow++;
1179  if (sampleRateInfo.numSamplesSkipped >= 20 && station->m_numSamplesSlow <= 2)
1180  {
1182  station->m_isSampling = true;
1183 
1185  station->m_sampleRate = sampleIdx;
1186 
1187  NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx);
1188  station->m_sampleTries--;
1189  return sampleIdx;
1190  }
1191  }
1192  }
1193  }
1194  }
1195  if (station->m_sampleWait > 0)
1196  {
1197  station->m_sampleWait--;
1198  }
1199 
1201 
1202  NS_LOG_DEBUG ("FindRate " << "maxTpRrate=" << station->m_maxTpRate);
1203  return station->m_maxTpRate;
1204 }
1205 void
1207 {
1208  NS_LOG_FUNCTION (this << station);
1209 
1211 
1212  station->m_numSamplesSlow = 0;
1213  station->m_sampleCount = 0;
1214 
1215  double tempProb;
1216 
1217  if (station->m_ampduPacketCount > 0)
1218  {
1219  uint32_t newLen = station->m_ampduLen / station->m_ampduPacketCount;
1220  station->m_avgAmpduLen = ( newLen * (100 - m_ewmaLevel) + (station->m_avgAmpduLen * m_ewmaLevel) ) / 100;
1221  station->m_ampduLen = 0;
1222  station->m_ampduPacketCount = 0;
1223  }
1224 
1225  /* Initialize global rate indexes */
1226  station->m_maxTpRate = GetLowestIndex (station);
1227  station->m_maxTpRate2 = GetLowestIndex (station);
1228  station->m_maxProbRate = GetLowestIndex (station);
1229 
1231  for (uint8_t j = 0; j < m_numGroups; j++)
1232  {
1233  if (station->m_groupsTable[j].m_supported)
1234  {
1235  station->m_sampleCount++;
1236 
1237  /* (re)Initialize group rate indexes */
1238  station->m_groupsTable[j].m_maxTpRate = GetLowestIndex (station, j);
1239  station->m_groupsTable[j].m_maxTpRate2 = GetLowestIndex (station, j);
1240  station->m_groupsTable[j].m_maxProbRate = GetLowestIndex (station, j);
1241 
1242  for (uint8_t i = 0; i < m_numRates; i++)
1243  {
1244  if (station->m_groupsTable[j].m_ratesTable[i].supported)
1245  {
1246  station->m_groupsTable[j].m_ratesTable[i].retryUpdated = false;
1247 
1248  NS_LOG_DEBUG (+i << " " << GetMcsSupported (station, station->m_groupsTable[j].m_ratesTable[i].mcsIndex) <<
1249  "\t attempt=" << station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<
1250  "\t success=" << station->m_groupsTable[j].m_ratesTable[i].numRateSuccess);
1251 
1253  if (station->m_groupsTable[j].m_ratesTable[i].numRateAttempt > 0)
1254  {
1255  station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped = 0;
1260  tempProb = (100 * station->m_groupsTable[j].m_ratesTable[i].numRateSuccess) / station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1261 
1263  station->m_groupsTable[j].m_ratesTable[i].prob = tempProb;
1264 
1265  if (station->m_groupsTable[j].m_ratesTable[i].successHist == 0)
1266  {
1267  station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1268  }
1269  else
1270  {
1271  station->m_groupsTable[j].m_ratesTable[i].ewmsdProb = CalculateEwmsd (station->m_groupsTable[j].m_ratesTable[i].ewmsdProb,
1272  tempProb, station->m_groupsTable[j].m_ratesTable[i].ewmaProb,
1273  m_ewmaLevel);
1275  tempProb = (tempProb * (100 - m_ewmaLevel) + station->m_groupsTable[j].m_ratesTable[i].ewmaProb * m_ewmaLevel) / 100;
1276  station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1277  }
1278 
1279  station->m_groupsTable[j].m_ratesTable[i].throughput = CalculateThroughput (station, j, i, tempProb);
1280 
1281  station->m_groupsTable[j].m_ratesTable[i].successHist += station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1282  station->m_groupsTable[j].m_ratesTable[i].attemptHist += station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1283  }
1284  else
1285  {
1286  station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped++;
1287  }
1288 
1290  station->m_groupsTable[j].m_ratesTable[i].prevNumRateSuccess = station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1291  station->m_groupsTable[j].m_ratesTable[i].prevNumRateAttempt = station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1292  station->m_groupsTable[j].m_ratesTable[i].numRateSuccess = 0;
1293  station->m_groupsTable[j].m_ratesTable[i].numRateAttempt = 0;
1294 
1295  if (station->m_groupsTable[j].m_ratesTable[i].throughput != 0)
1296  {
1297  SetBestStationThRates (station, GetIndex (j, i));
1298  SetBestProbabilityRate (station, GetIndex (j, i));
1299  }
1300 
1301  }
1302  }
1303  }
1304  }
1305 
1306  //Try to sample all available rates during each interval.
1307  station->m_sampleCount *= 8;
1308 
1309  //Recalculate retries for the rates selected.
1310  CalculateRetransmits (station, station->m_maxTpRate);
1311  CalculateRetransmits (station, station->m_maxTpRate2);
1312  CalculateRetransmits (station, station->m_maxProbRate);
1313 
1314  NS_LOG_DEBUG ("max tp=" << station->m_maxTpRate << "\nmax tp2=" << station->m_maxTpRate2 << "\nmax prob=" << station->m_maxProbRate);
1315  if (m_printStats)
1316  {
1317  PrintTable (station);
1318  }
1319 }
1320 
1321 double
1322 MinstrelHtWifiManager::CalculateThroughput (MinstrelHtWifiRemoteStation *station, uint8_t groupId, uint8_t rateId, double ewmaProb)
1323 {
1329  if (ewmaProb < 10)
1330  {
1331  return 0;
1332  }
1333  else
1334  {
1339  Time txTime = station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime;
1340  if (ewmaProb > 90)
1341  {
1342  return 90 / txTime.GetSeconds ();
1343  }
1344  else
1345  {
1346  return ewmaProb / txTime.GetSeconds ();
1347  }
1348  }
1349 }
1350 
1351 void
1353 {
1354  GroupInfo *group;
1355  MinstrelHtRateInfo rate;
1356  uint8_t tmpGroupId, tmpRateId;
1357  double tmpTh, tmpProb;
1358  uint8_t groupId, rateId;
1359  double currentTh;
1360  // maximum group probability (GP) variables
1361  uint8_t maxGPGroupId, maxGPRateId;
1362  double maxGPTh;
1363 
1364  groupId = GetGroupId (index);
1365  rateId = GetRateId (index);
1366  group = &station->m_groupsTable[groupId];
1367  rate = group->m_ratesTable[rateId];
1368 
1369  tmpGroupId = GetGroupId (station->m_maxProbRate);
1370  tmpRateId = GetRateId (station->m_maxProbRate);
1371  tmpProb = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].ewmaProb;
1372  tmpTh = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].throughput;
1373 
1374  if (rate.ewmaProb > 75)
1375  {
1376  currentTh = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1377  if (currentTh > tmpTh)
1378  {
1379  station->m_maxProbRate = index;
1380  }
1381 
1382  maxGPGroupId = GetGroupId (group->m_maxProbRate);
1383  maxGPRateId = GetRateId (group->m_maxProbRate);
1384  maxGPTh = station->m_groupsTable[maxGPGroupId].m_ratesTable[maxGPRateId].throughput;
1385 
1386  if (currentTh > maxGPTh)
1387  {
1388  group->m_maxProbRate = index;
1389  }
1390  }
1391  else
1392  {
1393  if (rate.ewmaProb > tmpProb)
1394  {
1395  station->m_maxProbRate = index;
1396  }
1397  maxGPRateId = GetRateId (group->m_maxProbRate);
1398  if (rate.ewmaProb > group->m_ratesTable[maxGPRateId].ewmaProb)
1399  {
1400  group->m_maxProbRate = index;
1401  }
1402  }
1403 }
1404 
1405 /*
1406  * Find & sort topmost throughput rates
1407  *
1408  * If multiple rates provide equal throughput the sorting is based on their
1409  * current success probability. Higher success probability is preferred among
1410  * MCS groups.
1411  */
1412 void
1414 {
1415  uint8_t groupId, rateId;
1416  double th, prob;
1417  uint8_t maxTpGroupId, maxTpRateId;
1418  uint8_t maxTp2GroupId, maxTp2RateId;
1419  double maxTpTh, maxTpProb;
1420  double maxTp2Th, maxTp2Prob;
1421 
1422  groupId = GetGroupId (index);
1423  rateId = GetRateId (index);
1424  prob = station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb;
1425  th = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1426 
1427  maxTpGroupId = GetGroupId (station->m_maxTpRate);
1428  maxTpRateId = GetRateId (station->m_maxTpRate);
1429  maxTpProb = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].ewmaProb;
1430  maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1431 
1432  maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1433  maxTp2RateId = GetRateId (station->m_maxTpRate2);
1434  maxTp2Prob = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].ewmaProb;
1435  maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1436 
1437  if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1438  {
1439  station->m_maxTpRate2 = station->m_maxTpRate;
1440  station->m_maxTpRate = index;
1441  }
1442  else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1443  {
1444  station->m_maxTpRate2 = index;
1445  }
1446 
1447  //Find best rates per group
1448 
1449  GroupInfo *group = &station->m_groupsTable[groupId];
1450  maxTpGroupId = GetGroupId (group->m_maxTpRate);
1451  maxTpRateId = GetRateId (group->m_maxTpRate);
1452  maxTpProb = group->m_ratesTable[maxTpRateId].ewmaProb;
1453  maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1454 
1455  maxTp2GroupId = GetGroupId (group->m_maxTpRate2);
1456  maxTp2RateId = GetRateId (group->m_maxTpRate2);
1457  maxTp2Prob = group->m_ratesTable[maxTp2RateId].ewmaProb;
1458  maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1459 
1460  if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1461  {
1462  group->m_maxTpRate2 = group->m_maxTpRate;
1463  group->m_maxTpRate = index;
1464  }
1465  else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1466  {
1467  group->m_maxTpRate2 = index;
1468  }
1469 }
1470 
1471 void
1473 {
1474  NS_LOG_FUNCTION (this << station);
1475 
1476  station->m_groupsTable = McsGroupData (m_numGroups);
1477 
1481  NS_LOG_DEBUG ("Supported groups by station:");
1482  bool noSupportedGroupFound = true;
1483  for (uint8_t groupId = 0; groupId < m_numGroups; groupId++)
1484  {
1485  if (m_minstrelGroups[groupId].isSupported)
1486  {
1487  station->m_groupsTable[groupId].m_supported = false;
1488 
1489  if ((m_minstrelGroups[groupId].type == GROUP_HE) && !GetHeSupported (station))
1490  {
1491  //It is a HE group but the receiver does not support HE: skip
1492  continue;
1493  }
1494  if ((m_minstrelGroups[groupId].type == GROUP_VHT) && !GetVhtSupported (station))
1495  {
1496  //It is a VHT group but the receiver does not support VHT: skip
1497  continue;
1498  }
1499  if ((m_minstrelGroups[groupId].type != GROUP_HE) && GetHeSupported (station) && m_useLatestAmendmentOnly)
1500  {
1501  //It is not a HE group and the receiver supports HE: skip since UseLatestAmendmentOnly attribute is enabled
1502  continue;
1503  }
1504  if (!GetHeSupported (station) && (m_minstrelGroups[groupId].type != GROUP_VHT) && GetVhtSupported (station) && m_useLatestAmendmentOnly)
1505  {
1506  //It is not a VHT group and the receiver supports VHT (but not HE): skip since UseLatestAmendmentOnly attribute is enabled
1507  continue;
1508  }
1509  if (((m_minstrelGroups[groupId].type == GROUP_HT) || (m_minstrelGroups[groupId].type == GROUP_VHT))
1510  && (m_minstrelGroups[groupId].gi == 400) && !GetShortGuardIntervalSupported (station))
1511  {
1512  //It is a SGI group but the receiver does not support SGI: skip
1513  continue;
1514  }
1515  if ((m_minstrelGroups[groupId].type == GROUP_HE) && (m_minstrelGroups[groupId].gi < GetGuardInterval (station)))
1516  {
1517  //The receiver does not support the GI: skip
1518  continue;
1519  }
1520  if (GetChannelWidth (station) < m_minstrelGroups[groupId].chWidth)
1521  {
1522  //The receiver does not support the channel width: skip
1523  continue;
1524  }
1525  if (GetNumberOfSupportedStreams (station) < m_minstrelGroups[groupId].streams)
1526  {
1527  //The receiver does not support the number of spatial streams: skip
1528  continue;
1529  }
1530 
1531  NS_LOG_DEBUG ("Group: " << +groupId
1532  << " type: " << m_minstrelGroups[groupId].type
1533  << " streams: " << +m_minstrelGroups[groupId].streams
1534  << " GI: " << m_minstrelGroups[groupId].gi
1535  << " width: " << m_minstrelGroups[groupId].chWidth);
1536 
1537  noSupportedGroupFound = false;
1538  station->m_groupsTable[groupId].m_supported = true;
1539  station->m_groupsTable[groupId].m_col = 0;
1540  station->m_groupsTable[groupId].m_index = 0;
1541 
1542  station->m_groupsTable[groupId].m_ratesTable = MinstrelHtRate (m_numRates);
1543  for (uint8_t i = 0; i < m_numRates; i++)
1544  {
1545  station->m_groupsTable[groupId].m_ratesTable[i].supported = false;
1546  }
1547 
1548  // Initialize all modes supported by the remote station that belong to the current group.
1549  for (uint8_t i = 0; i < station->m_nModes; i++)
1550  {
1551  WifiMode mode = GetMcsSupported (station, i);
1552 
1555  uint8_t rateId = mode.GetMcsValue ();
1556  if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1557  {
1558  rateId %= MAX_HT_GROUP_RATES;
1559  }
1560 
1561  if (((m_minstrelGroups[groupId].type == GROUP_HE)
1562  && (mode.GetModulationClass () == WIFI_MOD_CLASS_HE)
1563  && IsValidMcs (GetPhy (), m_minstrelGroups[groupId].streams, m_minstrelGroups[groupId].chWidth, mode))
1564  || ((m_minstrelGroups[groupId].type == GROUP_VHT)
1565  && (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)
1566  && IsValidMcs (GetPhy (), m_minstrelGroups[groupId].streams, m_minstrelGroups[groupId].chWidth, mode))
1567  || ((m_minstrelGroups[groupId].type == GROUP_HT)
1568  && (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1569  && (mode.GetMcsValue () < (m_minstrelGroups[groupId].streams * 8))
1570  && (mode.GetMcsValue () >= ((m_minstrelGroups[groupId].streams - 1) * 8))))
1571  {
1572  NS_LOG_DEBUG ("Mode " << +i << ": " << mode);
1573 
1574  station->m_groupsTable[groupId].m_ratesTable[rateId].supported = true;
1575  station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex = i;
1576  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt = 0;
1577  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess = 0;
1578  station->m_groupsTable[groupId].m_ratesTable[rateId].prob = 0;
1579  station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb = 0;
1580  station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateAttempt = 0;
1581  station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateSuccess = 0;
1582  station->m_groupsTable[groupId].m_ratesTable[rateId].numSamplesSkipped = 0;
1583  station->m_groupsTable[groupId].m_ratesTable[rateId].successHist = 0;
1584  station->m_groupsTable[groupId].m_ratesTable[rateId].attemptHist = 0;
1585  station->m_groupsTable[groupId].m_ratesTable[rateId].throughput = 0;
1586  station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, i));
1587  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 0;
1588  station->m_groupsTable[groupId].m_ratesTable[rateId].adjustedRetryCount = 0;
1589  CalculateRetransmits (station, groupId, rateId);
1590  }
1591  }
1592  }
1593  }
1595  if (noSupportedGroupFound)
1596  {
1597  NS_FATAL_ERROR ("No supported group has been found");
1598  }
1599  SetNextSample (station);
1600  UpdateStats (station);
1601  station->m_txrate = FindRate (station);
1602 }
1603 
1604 void
1606 {
1607  NS_LOG_FUNCTION (this << station << index);
1608  uint8_t groupId = GetGroupId (index);
1609  uint8_t rateId = GetRateId (index);
1610  if (!station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated)
1611  {
1612  CalculateRetransmits (station, groupId, rateId);
1613  }
1614 }
1615 
1616 void
1618 {
1619  NS_LOG_FUNCTION (this << station << +groupId << +rateId);
1620 
1621  uint32_t cw = 15; // Is an approximation.
1622  uint32_t cwMax = 1023;
1623  Time cwTime, txTime, dataTxTime;
1624  Time slotTime = GetPhy ()->GetSlot ();
1625  Time ackTime = GetPhy ()->GetSifs () + GetPhy ()->GetBlockAckTxTime ();
1626 
1627  if (station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb < 1)
1628  {
1629  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 1;
1630  }
1631  else
1632  {
1633  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 2;
1634  station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated = true;
1635 
1636  dataTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) +
1637  GetMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) * (station->m_avgAmpduLen - 1);
1638 
1639  /* Contention time for first 2 tries */
1640  cwTime = (cw / 2) * slotTime;
1641  cw = Min ((cw + 1) * 2, cwMax);
1642  cwTime += (cw / 2) * slotTime;
1643  cw = Min ((cw + 1) * 2, cwMax);
1644 
1645  /* Total TX time for data and Contention after first 2 tries */
1646  txTime = cwTime + 2 * (dataTxTime + ackTime);
1647 
1648  /* See how many more tries we can fit inside segment size */
1649  do
1650  {
1651  /* Contention time for this try */
1652  cwTime = (cw / 2) * slotTime;
1653  cw = Min ((cw + 1) * 2, cwMax);
1654 
1655  /* Total TX time after this try */
1656  txTime += cwTime + ackTime + dataTxTime;
1657  }
1658  while ((txTime < MilliSeconds (6))
1659  && (++station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount < 7));
1660  }
1661 }
1662 
1663 double
1664 MinstrelHtWifiManager::CalculateEwmsd (double oldEwmsd, double currentProb, double ewmaProb, double weight)
1665 {
1666  double diff, incr, tmp;
1667 
1668  /* calculate exponential weighted moving variance */
1669  diff = currentProb - ewmaProb;
1670  incr = (100 - weight) * diff / 100;
1671  tmp = oldEwmsd * oldEwmsd;
1672  tmp = weight * (tmp + diff * incr) / 100;
1673 
1674  /* return standard deviation */
1675  return sqrt (tmp);
1676 }
1677 
1678 void
1680 {
1681  NS_LOG_FUNCTION (this << station);
1682  station->m_col = station->m_index = 0;
1683 
1684  //for off-setting to make rates fall between 0 and nModes
1685  uint8_t numSampleRates = m_numRates;
1686 
1687  uint16_t newIndex;
1688  for (uint8_t col = 0; col < m_nSampleCol; col++)
1689  {
1690  for (uint8_t i = 0; i < numSampleRates; i++ )
1691  {
1696  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
1697  newIndex = (i + uv) % numSampleRates;
1698 
1699  //this loop is used for filling in other uninitialized places
1700  while (station->m_sampleTable[newIndex][col] != 0)
1701  {
1702  newIndex = (newIndex + 1) % m_numRates;
1703  }
1704  station->m_sampleTable[newIndex][col] = i;
1705  }
1706  }
1707 }
1708 
1709 void
1711 {
1712  if (!station->m_statsFile.is_open ())
1713  {
1714  std::ostringstream tmp;
1715  tmp << "minstrel-ht-stats-" << station->m_state->m_address << ".txt";
1716  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
1717  }
1718 
1719  station->m_statsFile << " best ____________rate__________ ________statistics________ ________last_______ ______sum-of________\n" <<
1720  " mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1721  for (uint8_t i = 0; i < m_numGroups; i++)
1722  {
1723  StatsDump (station, i, station->m_statsFile);
1724  }
1725 
1726  station->m_statsFile << "\nTotal packet count:: ideal " << Max (0, station->m_totalPacketsCount - station->m_samplePacketsCount) <<
1727  " lookaround " << station->m_samplePacketsCount << "\n";
1728  station->m_statsFile << "Average # of aggregated frames per A-MPDU: " << station->m_avgAmpduLen << "\n\n";
1729 
1730  station->m_statsFile.flush ();
1731 }
1732 
1733 void
1734 MinstrelHtWifiManager::StatsDump (MinstrelHtWifiRemoteStation *station, uint8_t groupId, std::ofstream &of)
1735 {
1736  uint8_t numRates = m_numRates;
1737  McsGroup group = m_minstrelGroups[groupId];
1738  Time txTime;
1739  for (uint8_t i = 0; i < numRates; i++)
1740  {
1741  if (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[i].supported)
1742  {
1743  of << group.type << " " << group.chWidth << " " << group.gi << " " << +group.streams << " ";
1744 
1745  uint16_t maxTpRate = station->m_maxTpRate;
1746  uint16_t maxTpRate2 = station->m_maxTpRate2;
1747  uint16_t maxProbRate = station->m_maxProbRate;
1748 
1749  uint16_t idx = GetIndex (groupId, i);
1750  if (idx == maxTpRate)
1751  {
1752  of << 'A';
1753  }
1754  else
1755  {
1756  of << ' ';
1757  }
1758  if (idx == maxTpRate2)
1759  {
1760  of << 'B';
1761  }
1762  else
1763  {
1764  of << ' ';
1765  }
1766  if (idx == maxProbRate)
1767  {
1768  of << 'P';
1769  }
1770  else
1771  {
1772  of << ' ';
1773  }
1774 
1775  if (group.type == GROUP_HT)
1776  {
1777  of << std::setw (4) << " MCS" << (group.streams - 1) * 8 + i;
1778  }
1779  else
1780  {
1781  of << std::setw (7) << " MCS" << +i << "/" << static_cast<int>(group.streams);
1782  }
1783 
1784  of << " " << std::setw (3) << +idx << " ";
1785 
1786  /* tx_time[rate(i)] in usec */
1787  txTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[i].mcsIndex));
1788  of << std::setw (6) << txTime.GetMicroSeconds () << " ";
1789 
1790  of << std::setw (7) << CalculateThroughput (station, groupId, i, 100) / 100 << " " <<
1791  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].throughput / 100 << " " <<
1792  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmaProb << " " <<
1793  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmsdProb << " " <<
1794  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].prob << " " <<
1795  std::setw (2) << station->m_groupsTable[groupId].m_ratesTable[i].retryCount << " " <<
1796  std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateSuccess << " " <<
1797  std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt << " " <<
1798  std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].successHist << " " <<
1799  std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].attemptHist << "\n";
1800  }
1801  }
1802 }
1803 uint16_t
1804 MinstrelHtWifiManager::GetIndex (uint8_t groupId, uint8_t rateId)
1805 {
1806  NS_LOG_FUNCTION (this << +groupId << +rateId);
1807  uint16_t index;
1808  index = groupId * m_numRates + rateId;
1809  return index;
1810 }
1811 
1812 uint8_t
1814 {
1815  NS_LOG_FUNCTION (this << index);
1816  uint8_t id;
1817  id = index % m_numRates;
1818  return id;
1819 }
1820 
1821 uint8_t
1823 {
1824  NS_LOG_FUNCTION (this << index);
1825  return index / m_numRates;
1826 }
1827 
1828 uint8_t
1829 MinstrelHtWifiManager::GetHtGroupId (uint8_t txstreams, uint16_t gi, uint16_t chWidth)
1830 {
1831  NS_LOG_FUNCTION (this << +txstreams << gi << chWidth);
1832  uint8_t giIndex = (gi == 400) ? 1 : 0;
1833  uint8_t widthIndex = (chWidth == 40) ? 1 : 0;
1834  return (MAX_HT_SUPPORTED_STREAMS * 2 * widthIndex) + (MAX_HT_SUPPORTED_STREAMS * giIndex) + txstreams - 1;
1835 }
1836 
1837 uint8_t
1838 MinstrelHtWifiManager::GetVhtGroupId (uint8_t txstreams, uint16_t gi, uint16_t chWidth)
1839 {
1840  NS_LOG_FUNCTION (this << +txstreams << gi << chWidth);
1841  uint8_t giIndex = (gi == 400) ? 1 : 0;
1842  uint8_t widthIndex;
1843  if (chWidth == 160)
1844  {
1845  widthIndex = 3;
1846  }
1847  else if (chWidth == 80)
1848  {
1849  widthIndex = 2;
1850  }
1851  else if (chWidth == 40)
1852  {
1853  widthIndex = 1;
1854  }
1855  else //20 MHz
1856  {
1857  widthIndex = 0;
1858  }
1859  uint8_t groupId = (MAX_HT_STREAM_GROUPS * MAX_HT_SUPPORTED_STREAMS);
1860  groupId += (MAX_VHT_SUPPORTED_STREAMS * 2 * widthIndex) + (MAX_VHT_SUPPORTED_STREAMS * giIndex) + txstreams - 1;
1861  return groupId;
1862 }
1863 
1864 uint8_t
1865 MinstrelHtWifiManager::GetHeGroupId (uint8_t txstreams, uint16_t gi, uint16_t chWidth)
1866 {
1867  NS_LOG_FUNCTION (this << +txstreams << gi << chWidth);
1868  uint8_t giIndex;
1869  if (gi == 800)
1870  {
1871  giIndex = 2;
1872  }
1873  else if (gi == 1600)
1874  {
1875  giIndex = 1;
1876  }
1877  else //3200 ns
1878  {
1879  giIndex = 0;
1880  }
1881  uint8_t widthIndex;
1882  if (chWidth == 160)
1883  {
1884  widthIndex = 3;
1885  }
1886  else if (chWidth == 80)
1887  {
1888  widthIndex = 2;
1889  }
1890  else if (chWidth == 40)
1891  {
1892  widthIndex = 1;
1893  }
1894  else //20 MHz
1895  {
1896  widthIndex = 0;
1897  }
1898  uint8_t groupId = (MAX_HT_STREAM_GROUPS * MAX_HT_SUPPORTED_STREAMS);
1899  if (GetVhtSupported ())
1900  {
1902  }
1903  groupId += (MAX_HE_SUPPORTED_STREAMS * 3 * widthIndex) + (MAX_HE_SUPPORTED_STREAMS * giIndex) + txstreams - 1;
1904  return groupId;
1905 }
1906 
1907 uint16_t
1909 {
1910  NS_LOG_FUNCTION (this << station);
1911 
1912  uint8_t groupId = 0;
1913  uint8_t rateId = 0;
1914  while (groupId < m_numGroups && !station->m_groupsTable[groupId].m_supported)
1915  {
1916  groupId++;
1917  }
1918  while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1919  {
1920  rateId++;
1921  }
1922  NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported);
1923  return GetIndex (groupId, rateId);
1924 }
1925 
1926 uint16_t
1928 {
1929  NS_LOG_FUNCTION (this << station << +groupId);
1930 
1931  uint8_t rateId = 0;
1932  while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1933  {
1934  rateId++;
1935  }
1936  NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported);
1937  return GetIndex (groupId, rateId);
1938 }
1939 
1942 {
1943  WifiModeList heMcsList;
1944  for (const auto & mode : GetPhy ()->GetMcsList (WIFI_MOD_CLASS_HE))
1945  {
1946  heMcsList.push_back (mode);
1947  }
1948  return heMcsList;
1949 }
1950 
1953 {
1954  WifiModeList vhtMcsList;
1955  for (const auto & mode : GetPhy ()->GetMcsList (WIFI_MOD_CLASS_VHT))
1956  {
1957  vhtMcsList.push_back (mode);
1958  }
1959  return vhtMcsList;
1960 }
1961 
1964 {
1965  WifiModeList htMcsList;
1966  for (const auto & mode : GetPhy ()->GetMcsList (WIFI_MOD_CLASS_HT))
1967  {
1968  htMcsList.push_back (mode);
1969  }
1970  return htMcsList;
1971 }
1972 
1973 } // namespace ns3
ns3::TypeId
a unique identifier for an interface.
Definition: type-id.h:59
ns3::WifiRemoteStationManager::GetDefaultTxPowerLevel
uint8_t GetDefaultTxPowerLevel(void) const
Definition: wifi-remote-station-manager.cc:1206
NS_LOG_COMPONENT_DEFINE
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
ns3::MinstrelHtWifiManager::m_currentRate
TracedValue< uint64_t > m_currentRate
Trace rate changes.
Definition: minstrel-ht-wifi-manager.h:619
ns3::MinstrelHtWifiManager::CountRetries
uint32_t CountRetries(MinstrelHtWifiRemoteStation *station)
Count retries.
Definition: minstrel-ht-wifi-manager.cc:1033
ns3::MAX_HT_STREAM_GROUPS
static const uint8_t MAX_HT_STREAM_GROUPS
Maximal number of groups per stream in HT (2 possible channel widths and 2 possible GI configurations...
Definition: minstrel-ht-wifi-manager.h:168
ns3::MinstrelHtWifiRemoteStation::m_sampleCount
uint32_t m_sampleCount
Max number of samples per update interval.
Definition: minstrel-ht-wifi-manager.cc:60
NS_OBJECT_ENSURE_REGISTERED
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
NS_ASSERT
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
ns3::MakeTimeChecker
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
ns3::BooleanValue
AttributeValue implementation for Boolean.
Definition: boolean.h:37
ns3::MinstrelWifiRemoteStation::m_maxTpRate2
uint16_t m_maxTpRate2
second highest throughput rate in bps
Definition: minstrel-wifi-manager.h:96
ns3::WifiModeList
std::vector< WifiMode > WifiModeList
In various parts of the code, folk are interested in maintaining a list of transmission modes.
Definition: wifi-mode.h:254
ns3::McsGroup::gi
uint16_t gi
guard interval duration (nanoseconds)
Definition: minstrel-ht-wifi-manager.h:82
ns3::GroupInfo::m_maxTpRate
uint16_t m_maxTpRate
The max throughput rate of this group in bps.
Definition: minstrel-ht-wifi-manager.h:149
ns3::MinstrelHtWifiRemoteStation::m_ampduLen
uint32_t m_ampduLen
Number of MPDUs in an A-MPDU.
Definition: minstrel-ht-wifi-manager.cc:64
ns3::McsGroup
Data structure to contain the information that defines a group.
Definition: minstrel-ht-wifi-manager.h:80
ns3::WifiPhy::GetSlot
Time GetSlot(void) const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:922
ns3::MinstrelHtWifiManager::GetVhtDeviceMcsList
WifiModeList GetVhtDeviceMcsList(void) const
Returns a list of only the VHT MCS supported by the device.
Definition: minstrel-ht-wifi-manager.cc:1952
ns3::MinstrelHtWifiManager::FindRate
uint16_t FindRate(MinstrelHtWifiRemoteStation *station)
Find a rate to use from Minstrel Table.
Definition: minstrel-ht-wifi-manager.cc:1101
ns3::MinstrelHtWifiManager::DoReportRtsOk
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.
Definition: minstrel-ht-wifi-manager.cc:525
ns3::Simulator::Now
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::GROUP_HE
@ GROUP_HE
Definition: minstrel-ht-wifi-manager.h:48
ns3::MinstrelRate
std::vector< RateInfo > MinstrelRate
Data structure for a Minstrel Rate table A vector of a struct RateInfo.
Definition: minstrel-wifi-manager.h:70
ns3::MAX_VHT_WIDTH
static const uint8_t MAX_VHT_WIDTH
Maximal channel width in MHz.
Definition: minstrel-ht-wifi-manager.h:175
ns3::MinstrelHtWifiManager::GetVhtGroupId
uint8_t GetVhtGroupId(uint8_t txstreams, uint16_t gi, uint16_t chWidth)
Returns the groupId of a VHT MCS with the given number of streams, GI and channel width used.
Definition: minstrel-ht-wifi-manager.cc:1838
ns3::SampleRate
std::vector< std::vector< uint8_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint8_t.
Definition: minstrel-wifi-manager.h:75
ns3::WifiRemoteStationManager::GetShortGuardIntervalSupported
bool GetShortGuardIntervalSupported(void) const
Return whether the device has SGI support enabled.
Definition: wifi-remote-station-manager.cc:281
ns3::WIFI_MOD_CLASS_HT
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
Definition: wifi-phy-common.h:130
ns3::WIFI_MOD_CLASS_HE
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition: wifi-phy-common.h:132
ns3::MAX_HE_STREAM_GROUPS
static const uint8_t MAX_HE_STREAM_GROUPS
Maximal number of groups per stream in HE (4 possible channel widths and 3 possible GI configurations...
Definition: minstrel-ht-wifi-manager.h:170
ns3::MinstrelHtWifiManager::PrintTable
void PrintTable(MinstrelHtWifiRemoteStation *station)
Printing Minstrel Table.
Definition: minstrel-ht-wifi-manager.cc:1710
ns3::WifiTxVector::IsValid
bool IsValid(void) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
Definition: wifi-tx-vector.cc:334
ns3::WifiTxVector::SetGuardInterval
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
Definition: wifi-tx-vector.cc:260
ns3::McsGroup::chWidth
uint16_t chWidth
channel width (MHz)
Definition: minstrel-ht-wifi-manager.h:83
ns3::MinstrelHtWifiRemoteStation::m_groupsTable
McsGroupData m_groupsTable
Table of groups with stats.
Definition: minstrel-ht-wifi-manager.cc:67
ns3::WifiPhy::CalculatePhyPreambleAndHeaderDuration
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1604
ns3::MinstrelHtWifiManager::m_lookAroundRate
uint8_t m_lookAroundRate
The % to try other rates than our current rate.
Definition: minstrel-ht-wifi-manager.h:604
ns3::WifiMode::GetModulationClass
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:159
ns3::WifiTxVector::SetNss
void SetNss(uint8_t nss)
Sets the number of Nss.
Definition: wifi-tx-vector.cc:272
ns3::MinstrelHtWifiRemoteStation::m_statsFile
std::ofstream m_statsFile
File where statistics table is written.
Definition: minstrel-ht-wifi-manager.cc:70
ns3::WifiRemoteStationManager::GetNBasicModes
uint8_t GetNBasicModes(void) const
Return the number of basic modes we support.
Definition: wifi-remote-station-manager.cc:1508
ns3::MinstrelHtWifiManager::m_nSampleCol
uint8_t m_nSampleCol
Number of sample columns.
Definition: minstrel-ht-wifi-manager.h:606
ns3::MinstrelWifiRemoteStation::m_initialized
bool m_initialized
for initializing tables
Definition: minstrel-wifi-manager.h:109
ns3::WifiRemoteStationManager
hold a list of per-remote-station state.
Definition: wifi-remote-station-manager.h:121
ns3::MinstrelWifiRemoteStation::m_txrate
uint16_t m_txrate
current transmit rate in bps
Definition: minstrel-wifi-manager.h:108
ns3::WifiRemoteStationManager::GetHtSupported
bool GetHtSupported(void) const
Return whether the device has HT capability support enabled.
Definition: wifi-remote-station-manager.cc:232
ns3::WifiRemoteStationManager::GetVhtSupported
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
Definition: wifi-remote-station-manager.cc:244
ns3::WifiRemoteStationManager::GetGuardInterval
uint16_t GetGuardInterval(void) const
Return the supported HE guard interval duration (in nanoseconds).
Definition: wifi-remote-station-manager.cc:297
ns3::WifiTxVector::SetMode
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
Definition: wifi-tx-vector.cc:226
ns3::GroupInfo::m_maxProbRate
uint16_t m_maxProbRate
The highest success probability rate of this group in bps.
Definition: minstrel-ht-wifi-manager.h:151
ns3::WifiTxVector
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Definition: wifi-tx-vector.h:71
ns3::MinstrelHtWifiManager::DoReportFinalRtsFailed
void DoReportFinalRtsFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
Definition: minstrel-ht-wifi-manager.cc:531
third.mac
mac
Definition: third.py:99
ns3::MinstrelWifiRemoteStation::m_isSampling
bool m_isSampling
a flag to indicate we are currently sampling
Definition: minstrel-wifi-manager.h:102
ns3::MinstrelHtWifiManager::DoReportDataFailed
void DoReportDataFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
Definition: minstrel-ht-wifi-manager.cc:545
ns3::MinstrelWifiRemoteStation
hold per-remote-station state for Minstrel Wifi manager.
Definition: minstrel-wifi-manager.h:84
ns3::MAX_HT_SUPPORTED_STREAMS
static const uint8_t MAX_HT_SUPPORTED_STREAMS
Constants for maximum values.
Definition: minstrel-ht-wifi-manager.h:165
ns3::MakeBooleanAccessor
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:85
ns3::Min
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
ns3::MinstrelHtWifiManager::IsValidMcs
bool IsValidMcs(Ptr< WifiPhy > phy, uint8_t streams, uint16_t chWidth, WifiMode mode)
Check the validity of a combination of number of streams, chWidth and mode.
Definition: minstrel-ht-wifi-manager.cc:349
ns3::MAX_HE_GROUP_RATES
static const uint8_t MAX_HE_GROUP_RATES
Number of rates (or MCS) per HE group.
Definition: minstrel-ht-wifi-manager.h:173
ns3::UniformRandomVariable::GetInteger
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value, as an unsigned integer in the specified range .
Definition: random-variable-stream.cc:193
ns3::FIRST_MPDU_IN_AGGREGATE
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
Definition: wifi-mpdu-type.h:37
ns3::TypeId::SetParent
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
ns3::MinstrelHtWifiManager::GetIndex
uint16_t GetIndex(uint8_t groupId, uint8_t rateId)
Returns the global index corresponding to the groupId and rateId.
Definition: minstrel-ht-wifi-manager.cc:1804
ns3::WifiRemoteStationManager::GetShortPreambleEnabled
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PHY preambles.
Definition: wifi-remote-station-manager.cc:226
ns3::WifiPhy::GetPayloadDuration
static Time GetPayloadDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, MpduType mpdutype=NORMAL_MPDU, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1586
ns3::MinstrelWifiRemoteStation::m_minstrelTable
MinstrelRate m_minstrelTable
minstrel table
Definition: minstrel-wifi-manager.h:110
ns3::MakeTraceSourceAccessor
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Definition: trace-source-accessor.h:202
ns3::WifiPhy::GetBlockAckTxTime
Time GetBlockAckTxTime(void) const
Return the estimated BlockAck TX time for this PHY.
Definition: wifi-phy.cc:946
ns3::MinstrelHtWifiManager::MinstrelHtWifiManager
MinstrelHtWifiManager()
Definition: minstrel-ht-wifi-manager.cc:130
ns3::MinstrelHtWifiManager::DoGetDataTxVector
WifiTxVector DoGetDataTxVector(WifiRemoteStation *station) override
Definition: minstrel-ht-wifi-manager.cc:865
ns3::MinstrelHtWifiRemoteStation::m_numSamplesSlow
uint32_t m_numSamplesSlow
Number of times a slow rate was sampled.
Definition: minstrel-ht-wifi-manager.cc:61
ns3::WifiRemoteStationManager::GetPhy
Ptr< WifiPhy > GetPhy(void) const
Return the WifiPhy.
Definition: wifi-remote-station-manager.cc:1731
ns3::MinstrelWifiRemoteStation::m_totalPacketsCount
int m_totalPacketsCount
total number of packets as of now
Definition: minstrel-wifi-manager.h:99
ns3::MAX_HE_SUPPORTED_STREAMS
static const uint8_t MAX_HE_SUPPORTED_STREAMS
Maximal number of streams supported by the HE PHY layer.
Definition: minstrel-ht-wifi-manager.h:167
ns3::MAX_VHT_GROUP_RATES
static const uint8_t MAX_VHT_GROUP_RATES
Number of rates (or MCS) per VHT group.
Definition: minstrel-ht-wifi-manager.h:172
ns3::MinstrelHtWifiManager::SetupMac
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...
Definition: minstrel-ht-wifi-manager.cc:175
ns3::MinstrelHtWifiRemoteStation::m_sampleTries
uint32_t m_sampleTries
Number of sample tries after waiting sampleWait.
Definition: minstrel-ht-wifi-manager.cc:59
ns3::MinstrelWifiRemoteStation::m_sampleDeferred
bool m_sampleDeferred
a flag to indicate sample rate is on the second stage
Definition: minstrel-wifi-manager.h:104
ns3::Ptr< WifiPhy >
ns3::Max
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:230
ns3::MinstrelWifiRemoteStation::m_nModes
uint8_t m_nModes
number of modes supported
Definition: minstrel-wifi-manager.h:98
NS_FATAL_ERROR
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
ns3::MAX_VHT_STREAM_GROUPS
static const uint8_t MAX_VHT_STREAM_GROUPS
Maximal number of groups per stream in VHT (4 possible channel widths and 2 possible GI configuration...
Definition: minstrel-ht-wifi-manager.h:169
ns3::MIDDLE_MPDU_IN_AGGREGATE
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
Definition: wifi-mpdu-type.h:39
ns3::WifiRemoteStationManager::GetNumberOfSupportedStreams
uint8_t GetNumberOfSupportedStreams(Mac48Address address) const
Return the number of spatial streams supported by the station.
Definition: wifi-remote-station-manager.cc:1812
ns3::MinstrelHtWifiManager::InitSampleTable
void InitSampleTable(MinstrelHtWifiRemoteStation *station)
Initialize Sample Table.
Definition: minstrel-ht-wifi-manager.cc:1679
ns3::MinstrelWifiRemoteStation::m_longRetry
uint32_t m_longRetry
long retries such as data packets
Definition: minstrel-wifi-manager.h:106
ns3::MinstrelHtWifiRemoteStation::m_avgAmpduLen
uint32_t m_avgAmpduLen
Average number of MPDUs in an A-MPDU.
Definition: minstrel-ht-wifi-manager.cc:63
ns3::MinstrelHtWifiManager::GetHeGroupId
uint8_t GetHeGroupId(uint8_t txstreams, uint16_t gi, uint16_t chWidth)
Returns the groupId of an HE MCS with the given number of streams, GI and channel width used.
Definition: minstrel-ht-wifi-manager.cc:1865
ns3::MinstrelHtWifiManager::CalculateRetransmits
void CalculateRetransmits(MinstrelHtWifiRemoteStation *station, uint16_t index)
Calculate the number of retransmissions to set for the index rate.
Definition: minstrel-ht-wifi-manager.cc:1605
ns3::MAX_VHT_SUPPORTED_STREAMS
static const uint8_t MAX_VHT_SUPPORTED_STREAMS
Maximal number of streams supported by the VHT PHY layer.
Definition: minstrel-ht-wifi-manager.h:166
ns3::WifiMode
represent a single transmission mode
Definition: wifi-mode.h:48
ns3::MinstrelHtWifiManager::GetRateId
uint8_t GetRateId(uint16_t index)
Return the rateId inside a group, from the global index.
Definition: minstrel-ht-wifi-manager.cc:1813
ns3::MinstrelHtWifiManager::GetLowestIndex
uint16_t GetLowestIndex(MinstrelHtWifiRemoteStation *station)
Returns the lowest global index of the rates supported by the station.
Definition: minstrel-ht-wifi-manager.cc:1908
ns3::WifiTxVector::SetNess
void SetNess(uint8_t ness)
Sets the Ness number.
Definition: wifi-tx-vector.cc:286
ns3::MAX_HE_WIDTH
static const uint8_t MAX_HE_WIDTH
Maximal channel width in MHz.
Definition: minstrel-ht-wifi-manager.h:176
ns3::MinstrelWifiRemoteStation::m_maxTpRate
uint16_t m_maxTpRate
the current throughput rate in bps
Definition: minstrel-wifi-manager.h:95
ns3::MinstrelHtWifiManager::UpdateRetry
void UpdateRetry(MinstrelHtWifiRemoteStation *station)
Update the number of retries and reset accordingly.
Definition: minstrel-ht-wifi-manager.cc:833
ns3::MinstrelHtWifiManager::UpdatePacketCounters
void UpdatePacketCounters(MinstrelHtWifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus)
Update the number of sample count variables.
Definition: minstrel-ht-wifi-manager.cc:841
ns3::Time::GetMicroSeconds
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:388
ns3::MinstrelHtWifiManager::CalculateThroughput
double CalculateThroughput(MinstrelHtWifiRemoteStation *station, uint8_t groupId, uint8_t rateId, double ewmaProb)
Return the average throughput of the MCS defined by groupId and rateId.
Definition: minstrel-ht-wifi-manager.cc:1322
ns3::MinstrelHtWifiManager::DoReportDataOk
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.
Definition: minstrel-ht-wifi-manager.cc:572
ns3::MinstrelWifiRemoteStation::m_sampleTable
SampleRate m_sampleTable
sample table
Definition: minstrel-wifi-manager.h:111
ns3::MinstrelHtWifiManager::m_numRates
uint8_t m_numRates
Number of rates per group Minstrel should consider.
Definition: minstrel-ht-wifi-manager.h:609
NS_LOG_INFO
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
ns3::MinstrelHtWifiManager::SetNextSample
void SetNextSample(MinstrelHtWifiRemoteStation *station)
Set the next sample from Sample Table.
Definition: minstrel-ht-wifi-manager.cc:1070
ns3::MilliSeconds
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
ns3::MinstrelHtRateInfo::ewmaProb
double ewmaProb
Exponential weighted moving average of probability.
Definition: minstrel-ht-wifi-manager.h:122
ns3::WifiRemoteStationManager::GetNess
uint8_t GetNess(const WifiRemoteStation *station) const
Definition: wifi-remote-station-manager.cc:1725
ns3::MinstrelHtWifiManager::AddMpduTxTime
void AddMpduTxTime(uint8_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
Definition: minstrel-ht-wifi-manager.cc:402
ns3::WifiMode::GetNonHtReferenceRate
uint64_t GetNonHtReferenceRate(void) const
Definition: wifi-mode.cc:166
ns3::GROUP_HT
@ GROUP_HT
Definition: minstrel-ht-wifi-manager.h:46
ns3::MinstrelHtWifiManager::CalculateMpduTxDuration
Time CalculateMpduTxDuration(Ptr< WifiPhy > phy, uint8_t streams, uint16_t gi, uint16_t chWidth, WifiMode mode, MpduType mpduType)
Estimates the TxTime of a frame with a given mode and group (stream, guard interval and channel width...
Definition: minstrel-ht-wifi-manager.cc:360
ns3::MinstrelHtWifiManager::DoReportFinalDataFailed
void DoReportFinalDataFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
Definition: minstrel-ht-wifi-manager.cc:633
ns3::MinstrelHtWifiManager::AssignStreams
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
Definition: minstrel-ht-wifi-manager.cc:155
ns3::MakeBooleanChecker
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
ns3::MinstrelHtWifiManager::m_frameLength
uint32_t m_frameLength
Frame length used for calculate modes TxTime in bytes.
Definition: minstrel-ht-wifi-manager.h:607
ns3::MinstrelHtWifiManager::StatsDump
void StatsDump(MinstrelHtWifiRemoteStation *station, uint8_t groupId, std::ofstream &of)
Print group statistics.
Definition: minstrel-ht-wifi-manager.cc:1734
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
ns3::GetChannelWidthForTransmission
uint16_t GetChannelWidthForTransmission(WifiMode mode, uint16_t maxSupportedChannelWidth)
Return the channel width that corresponds to the selected mode (instead of letting the PHY's default ...
Definition: wifi-phy-common.cc:68
ns3::WifiTxVector::SetChannelWidth
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
Definition: wifi-tx-vector.cc:254
ns3::MinstrelHtWifiRemoteStation
MinstrelHtWifiRemoteStation structure.
Definition: minstrel-ht-wifi-manager.cc:55
ns3::WifiRemoteStationManager::SetupPhy
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...
Definition: wifi-remote-station-manager.cc:142
ns3::MinstrelHtWifiManager::~MinstrelHtWifiManager
virtual ~MinstrelHtWifiManager()
Definition: minstrel-ht-wifi-manager.cc:144
NS_ASSERT_MSG
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
ns3::GroupInfo::m_ratesTable
MinstrelHtRate m_ratesTable
Information about rates of this group.
Definition: minstrel-ht-wifi-manager.h:152
ns3::MinstrelWifiRemoteStation::m_shortRetry
uint32_t m_shortRetry
short retries such as control packets
Definition: minstrel-wifi-manager.h:105
ns3::MinstrelWifiRemoteStation::m_samplePacketsCount
int m_samplePacketsCount
how many packets we have sample so far
Definition: minstrel-wifi-manager.h:100
ns3::MinstrelHtWifiManager::m_uniformRandomVariable
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
Definition: minstrel-ht-wifi-manager.h:617
ns3::MinstrelHtRateInfo::numSamplesSkipped
uint32_t numSamplesSkipped
Number of times this rate statistics were not updated because no attempts have been made.
Definition: minstrel-ht-wifi-manager.h:126
ns3::MinstrelHtWifiRemoteStation::m_sampleGroup
uint8_t m_sampleGroup
The group that the sample rate belongs to.
Definition: minstrel-ht-wifi-manager.cc:56
ns3::MinstrelHtWifiManager::GetNextSample
uint16_t GetNextSample(MinstrelHtWifiRemoteStation *station)
Getting the next sample from Sample Table.
Definition: minstrel-ht-wifi-manager.cc:1056
ns3::MinstrelHtWifiManager::SetBestProbabilityRate
void SetBestProbabilityRate(MinstrelHtWifiRemoteStation *station, uint16_t index)
Set index rate as maxProbRate if it is better than current value.
Definition: minstrel-ht-wifi-manager.cc:1352
ns3::MinstrelHtWifiManager::DoNeedRetransmission
bool DoNeedRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally) override
Definition: minstrel-ht-wifi-manager.cc:997
ns3::GroupInfo::m_maxTpRate2
uint16_t m_maxTpRate2
The second max throughput rate of this group in bps.
Definition: minstrel-ht-wifi-manager.h:150
ns3::MinstrelHtWifiManager::SetupPhy
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...
Definition: minstrel-ht-wifi-manager.cc:166
ns3::GetPreambleForTransmission
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble)
Return the preamble to be used for the transmission.
Definition: wifi-phy-common.cc:87
ns3::MinstrelHtWifiManager::GetHtDeviceMcsList
WifiModeList GetHtDeviceMcsList(void) const
Returns a list of only the HT MCS supported by the device.
Definition: minstrel-ht-wifi-manager.cc:1963
ns3::McsGroupData
std::vector< struct GroupInfo > McsGroupData
Data structure for a table of groups.
Definition: minstrel-ht-wifi-manager.h:159
ns3::MinstrelHtRate
std::vector< MinstrelHtRateInfo > MinstrelHtRate
Data structure for a Minstrel Rate table.
Definition: minstrel-ht-wifi-manager.h:136
ns3::MinstrelHtWifiManager::m_numGroups
uint8_t m_numGroups
Number of groups Minstrel should consider.
Definition: minstrel-ht-wifi-manager.h:608
ns3::WifiRemoteStation
hold per-remote-station state.
Definition: wifi-remote-station-manager.h:62
ns3::MAX_HT_GROUP_RATES
static const uint8_t MAX_HT_GROUP_RATES
Number of rates (or MCS) per HT group.
Definition: minstrel-ht-wifi-manager.h:171
ns3::MinstrelHtWifiManager::GetHtGroupId
uint8_t GetHtGroupId(uint8_t txstreams, uint16_t gi, uint16_t chWidth)
Returns the groupId of an HT MCS with the given number of streams, GI and channel width used.
Definition: minstrel-ht-wifi-manager.cc:1829
ns3::GroupInfo
A struct to contain information of a group.
Definition: minstrel-ht-wifi-manager.h:142
ns3::MinstrelHtWifiManager::RateInit
void RateInit(MinstrelHtWifiRemoteStation *station)
Initialize Minstrel Table.
Definition: minstrel-ht-wifi-manager.cc:1472
ns3::WifiRemoteStationManager::GetAggregation
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
Definition: wifi-remote-station-manager.cc:1707
ns3::MinstrelWifiRemoteStation::m_sampleRate
uint16_t m_sampleRate
current sample rate in bps
Definition: minstrel-wifi-manager.h:103
ns3::MinstrelHtWifiRemoteStation::m_ampduPacketCount
uint32_t m_ampduPacketCount
Number of A-MPDUs transmitted.
Definition: minstrel-ht-wifi-manager.cc:65
ns3::MinstrelMcsGroups
std::vector< McsGroup > MinstrelMcsGroups
Data structure for a table of group definitions.
Definition: minstrel-ht-wifi-manager.h:96
ns3::MinstrelWifiRemoteStation::m_col
uint8_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
Definition: minstrel-wifi-manager.h:93
ns3::MinstrelHtWifiManager
Implementation of Minstrel-HT Rate Control Algorithm.
Definition: minstrel-ht-wifi-manager.h:223
ns3::MinstrelHtWifiManager::UpdateRate
void UpdateRate(MinstrelHtWifiRemoteStation *station)
Update rate.
Definition: minstrel-ht-wifi-manager.cc:732
NS_LOG_DEBUG
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
ns3::MinstrelHtWifiManager::DoInitialize
void DoInitialize(void) override
Initialize() implementation.
Definition: minstrel-ht-wifi-manager.cc:183
ns3::MinstrelWifiRemoteStation::m_maxProbRate
uint16_t m_maxProbRate
rate with highest probability of success in bps
Definition: minstrel-wifi-manager.h:97
ns3::WifiRemoteStationManager::GetNumberOfAntennas
uint8_t GetNumberOfAntennas(void) const
Definition: wifi-remote-station-manager.cc:1872
ns3::GROUP_VHT
@ GROUP_VHT
Definition: minstrel-ht-wifi-manager.h:47
ns3::MinstrelHtWifiManager::SetBestStationThRates
void SetBestStationThRates(MinstrelHtWifiRemoteStation *station, uint16_t index)
Set index rate as maxTpRate or maxTp2Rate if is better than current values.
Definition: minstrel-ht-wifi-manager.cc:1413
ns3::MinstrelHtRateInfo
A struct to contain all statistics information related to a data rate.
Definition: minstrel-ht-wifi-manager.h:103
ns3::MinstrelHtWifiManager::m_printStats
bool m_printStats
If statistics table should be printed.
Definition: minstrel-ht-wifi-manager.h:611
ns3::WifiRemoteStation::m_state
WifiRemoteStationState * m_state
Remote station state.
Definition: wifi-remote-station-manager.h:63
ns3::MinstrelHtWifiManager::GetTypeId
static TypeId GetTypeId(void)
Get the type ID.
Definition: minstrel-ht-wifi-manager.cc:76
ns3::MinstrelHtWifiManager::GetFirstMpduTxTime
Time GetFirstMpduTxTime(uint8_t groupId, WifiMode mode) const
Obtain the TxTime saved in the group information.
Definition: minstrel-ht-wifi-manager.cc:377
ns3::MinstrelHtWifiManager::m_legacyManager
Ptr< MinstrelWifiManager > m_legacyManager
Pointer to an instance of MinstrelWifiManager.
Definition: minstrel-ht-wifi-manager.h:615
ns3::MinstrelHtWifiManager::DoReportAmpduTxStatus
void DoReportAmpduTxStatus(WifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss) override
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
Definition: minstrel-ht-wifi-manager.cc:680
ns3::TimeValue
AttributeValue implementation for Time.
Definition: nstime.h:1353
NS_LOG_FUNCTION
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Definition: log-macros-enabled.h:244
ns3::MinstrelHtWifiManager::m_ewmaLevel
uint8_t m_ewmaLevel
Exponential weighted moving average level (or coefficient).
Definition: minstrel-ht-wifi-manager.h:605
ns3::MinstrelHtWifiManager::m_useLatestAmendmentOnly
bool m_useLatestAmendmentOnly
Flag if only the latest supported amendment by both peers should be used.
Definition: minstrel-ht-wifi-manager.h:610
ns3::WifiRemoteStationManager::GetNMcsSupported
uint8_t GetNMcsSupported(Mac48Address address) const
Return the number of MCS supported by the station.
Definition: wifi-remote-station-manager.cc:1824
ns3::MinstrelHtWifiRemoteStation::m_isHt
bool m_isHt
If the station is HT capable.
Definition: minstrel-ht-wifi-manager.cc:68
ns3::MAX_HT_WIDTH
static const uint8_t MAX_HT_WIDTH
Maximal channel width in MHz.
Definition: minstrel-ht-wifi-manager.h:174
ns3::WifiTxVector::SetStbc
void SetStbc(bool stbc)
Sets if STBC is being used.
Definition: wifi-tx-vector.cc:298
ns3::RandomVariableStream::SetStream
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
Definition: random-variable-stream.cc:100
ns3::UintegerValue
Hold an unsigned integer type.
Definition: uinteger.h:44
ns3::MinstrelHtWifiManager::CalculateEwmsd
double CalculateEwmsd(double oldEwmsd, double currentProb, double ewmaProb, double weight)
Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation.
Definition: minstrel-ht-wifi-manager.cc:1664
ns3::MinstrelHtWifiManager::m_updateStats
Time m_updateStats
How frequent do we calculate the stats.
Definition: minstrel-ht-wifi-manager.h:602
ns3::WifiRemoteStationState::m_address
Mac48Address m_address
Mac48Address of the remote station.
Definition: wifi-remote-station-manager.h:95
ns3::MinstrelHtWifiManager::GetGroupId
uint8_t GetGroupId(uint16_t index)
Return the groupId from the global index.
Definition: minstrel-ht-wifi-manager.cc:1822
ns3::WifiRemoteStationManager::GetChannelWidth
uint16_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
Definition: wifi-remote-station-manager.cc:1683
ns3::WifiRemoteStationManager::GetBasicMode
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
Definition: wifi-remote-station-manager.cc:1514
ns3::WifiMode::GetDataRate
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:100
ns3::MakeUintegerAccessor
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
ns3::WIFI_MOD_CLASS_VHT
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
Definition: wifi-phy-common.h:131
ns3::MinstrelHtWifiManager::GetMpduTxTime
Time GetMpduTxTime(uint8_t groupId, WifiMode mode) const
Obtain the TxTime saved in the group information.
Definition: minstrel-ht-wifi-manager.cc:393
ns3::MinstrelHtWifiManager::AddFirstMpduTxTime
void AddFirstMpduTxTime(uint8_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
Definition: minstrel-ht-wifi-manager.cc:386
ns3::McsGroup::streams
uint8_t streams
number of spatial streams
Definition: minstrel-ht-wifi-manager.h:81
ns3::MinstrelHtWifiRemoteStation::m_sampleWait
uint32_t m_sampleWait
How many transmission attempts to wait until a new sample.
Definition: minstrel-ht-wifi-manager.cc:58
ns3::MinstrelWifiRemoteStation::m_nextStatsUpdate
Time m_nextStatsUpdate
10 times every second
Definition: minstrel-wifi-manager.h:85
ns3::MinstrelHtWifiManager::GetHeDeviceMcsList
WifiModeList GetHeDeviceMcsList() const
Returns a list of only the HE MCS supported by the device.
Definition: minstrel-ht-wifi-manager.cc:1941
ns3::MinstrelHtWifiManager::m_legacyUpdateStats
Time m_legacyUpdateStats
How frequent do we calculate the stats for legacy MinstrelWifiManager.
Definition: minstrel-ht-wifi-manager.h:603
ns3::MinstrelHtWifiManager::UpdateStats
void UpdateStats(MinstrelHtWifiRemoteStation *station)
Update the Minstrel Table.
Definition: minstrel-ht-wifi-manager.cc:1206
ns3::WifiPhy::GetSifs
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:910
ns3::WifiRemoteStationManager::SetupMac
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...
Definition: wifi-remote-station-manager.cc:161
ns3::MinstrelHtRateInfo::perfectTxTime
Time perfectTxTime
Perfect transmission time calculation, or frame calculation.
Definition: minstrel-ht-wifi-manager.h:108
ns3::WIFI_PREAMBLE_HT_MF
@ WIFI_PREAMBLE_HT_MF
Definition: wifi-phy-common.h:71
ns3::MinstrelHtWifiManager::CheckInit
void CheckInit(MinstrelHtWifiRemoteStation *station)
Check for initializations.
Definition: minstrel-ht-wifi-manager.cc:462
ns3::WifiTxVector::SetPreambleType
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
Definition: wifi-tx-vector.cc:248
ns3::MinstrelHtWifiManager::DoGetRtsTxVector
WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station) override
Definition: minstrel-ht-wifi-manager.cc:922
ns3::MinstrelHtWifiManager::m_minstrelGroups
MinstrelMcsGroups m_minstrelGroups
Global array for groups information.
Definition: minstrel-ht-wifi-manager.h:613
ns3::Time::GetSeconds
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
ns3::WifiTxVector::GetMode
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
Definition: wifi-tx-vector.cc:112
ns3::MinstrelWifiRemoteStation::m_index
uint8_t m_index
vector index
Definition: minstrel-wifi-manager.h:94
ns3::WifiRemoteStationManager::GetHeSupported
bool GetHeSupported(void) const
Return whether the device has HE capability support enabled.
Definition: wifi-remote-station-manager.cc:256
third.phy
phy
Definition: third.py:93
ns3::McsGroup::type
McsGroupType type
identifies the group,
Definition: minstrel-ht-wifi-manager.h:84
ns3::MakeTimeAccessor
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:1354
ns3::MinstrelHtWifiManager::DoReportRtsFailed
void DoReportRtsFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
Definition: minstrel-ht-wifi-manager.cc:511
ns3::MpduType
MpduType
The type of an MPDU.
Definition: wifi-mpdu-type.h:31
ns3::MinstrelHtWifiManager::DoReportRxOk
void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode) override
This method is a pure virtual method that must be implemented by the sub-class.
Definition: minstrel-ht-wifi-manager.cc:504
ns3::MinstrelHtWifiManager::DoCreateStation
WifiRemoteStation * DoCreateStation(void) const override
Definition: minstrel-ht-wifi-manager.cc:409
ns3::WifiMode::GetMcsValue
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:137
minstrel-ht-wifi-manager.h
ns3::WifiRemoteStationManager::GetMcsSupported
WifiMode GetMcsSupported(const WifiRemoteStation *station, uint8_t i) const
Return the WifiMode supported by the specified station at the specified index.
Definition: wifi-remote-station-manager.cc:1642