A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  * Author: 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 
38 #include "wifi-phy.h"
39 #include "ns3/random-variable-stream.h"
40 #include "ns3/simulator.h"
41 #include "ns3/log.h"
42 #include "ns3/uinteger.h"
43 #include "ns3/double.h"
44 #include "ns3/wifi-mac.h"
45 #include "ns3/assert.h"
46 #include "ns3/boolean.h"
47 #include "ns3/string.h"
48 #include <vector>
49 #include <iomanip>
50 #include <fstream>
51 
52 #define Min(a,b) ((a < b) ? a : b)
53 #define Max(a,b) ((a > b) ? a : b)
54 
55 NS_LOG_COMPONENT_DEFINE ("MinstrelHtWifiManager");
56 
57 namespace ns3 {
58 
60 {
61  void DisposeStation ();
62 
63  uint32_t m_sampleGroup;
64 
65  uint32_t m_sampleWait;
66  uint32_t m_sampleTries;
67  uint32_t m_sampleCount;
68  uint32_t m_numSamplesSlow;
69 
70  double m_avgAmpduLen;
71  double m_ampduLen;
72  uint32_t m_ampduPacketCount;
73 
75  bool m_isHt;
76 
77  std::ofstream m_statsFile;
78 };
79 
80 void
82 {
83  if (m_isHt)
84  {
85  std::vector<std::vector<uint32_t> > ().swap (m_sampleTable);
86  for (uint8_t j = 0; j < m_groupsTable.size (); j++)
87  {
88  std::vector<struct HtRateInfo> ().swap (m_groupsTable[j].m_ratesTable);
89  }
90  std::vector<struct GroupInfo> ().swap (m_groupsTable);
91  m_statsFile.close ();
92  }
93 }
94 
96 
97 TypeId
99 {
100  static TypeId tid = TypeId ("ns3::MinstrelHtWifiManager")
102  .AddConstructor<MinstrelHtWifiManager> ()
103  .SetGroupName ("Wifi")
104  .AddAttribute ("UpdateStatistics",
105  "The interval between updating statistics table ",
106  TimeValue (MilliSeconds (100)),
108  MakeTimeChecker ())
109  .AddAttribute ("LookAroundRate",
110  "The percentage to try other rates (for legacy Minstrel)",
111  DoubleValue (10),
113  MakeDoubleChecker<double> (0, 100))
114  .AddAttribute ("EWMA",
115  "EWMA level",
116  DoubleValue (75),
118  MakeDoubleChecker<double> (0, 100))
119  .AddAttribute ("SampleColumn",
120  "The number of columns used for sampling",
121  UintegerValue (10),
123  MakeUintegerChecker <uint32_t> ())
124  .AddAttribute ("PacketLength",
125  "The packet length used for calculating mode TxTime",
126  UintegerValue (1200),
128  MakeUintegerChecker <uint32_t> ())
129  .AddAttribute ("UseVhtOnly",
130  "Use only VHT MCSs (and not HT) when VHT is available",
131  BooleanValue (true),
134  .AddAttribute ("PrintStats",
135  "Control the printing of the statistics table",
136  BooleanValue (false),
139  .AddTraceSource ("RateChange",
140  "The transmission rate has changed",
142  "ns3::MinstrelHtWifiManager::RateChangeTracedCallback")
143  ;
144  return tid;
145 }
146 
148  : m_numGroups (0),
149  m_numRates (0)
150 {
151  NS_LOG_FUNCTION (this);
152  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
157  m_legacyManager = CreateObject<MinstrelWifiManager> ();
158 }
159 
161 {
162  NS_LOG_FUNCTION (this);
163  if (HasHtSupported ())
164  {
165  for (uint32_t i = 0; i < m_numGroups; i++)
166  {
167  m_minstrelGroups[i].ratesFirstMpduTxTimeTable.clear ();
168  m_minstrelGroups[i].ratesTxTimeTable.clear ();
169  }
170  }
171 }
172 
173 int64_t
175 {
176  NS_LOG_FUNCTION (this << stream);
177  int64_t numStreamsAssigned = 0;
179  numStreamsAssigned++;
180  numStreamsAssigned += m_legacyManager->AssignStreams (stream);
181  return numStreamsAssigned;
182 }
183 
184 void
186 {
187  NS_LOG_FUNCTION (this << phy);
188  // Setup phy for legacy manager.
189  m_legacyManager->SetupPhy (phy);
191 }
192 
193 void
195 {
196  NS_LOG_FUNCTION (this);
197 
204  // Check if the device supports HT or VHT
205  if (HasHtSupported () || HasVhtSupported ())
206  {
209 
210  if (HasVhtSupported ())
211  {
214  }
215 
226  NS_LOG_DEBUG ("Initialize MCS Groups:");
228 
229  // Initialize all HT groups
230  for (uint32_t chWidth = 20; chWidth <= MAX_HT_WIDTH; chWidth *= 2)
231  {
232  for (uint8_t sgi = 0; sgi <= 1; sgi++)
233  {
234  for (uint8_t streams = 1; streams <= MAX_SUPPORTED_STREAMS; streams++)
235  {
236  uint32_t groupId = GetHtGroupId (streams, sgi, chWidth);
237 
238  m_minstrelGroups[groupId].streams = streams;
239  m_minstrelGroups[groupId].sgi = sgi;
240  m_minstrelGroups[groupId].chWidth = chWidth;
241  m_minstrelGroups[groupId].isVht = false;
242  m_minstrelGroups[groupId].isSupported = false;
243 
244  // Check capabilities of the device
245  if (!(!GetPhy ()->GetGuardInterval () && m_minstrelGroups[groupId].sgi)
246  && (GetPhy ()->GetChannelWidth () >= m_minstrelGroups[groupId].chWidth)
247  && (GetPhy ()->GetNumberOfTransmitAntennas () >= m_minstrelGroups[groupId].streams))
248  {
249  m_minstrelGroups[groupId].isSupported = true;
250 
251  // Calculate tx time for all rates of the group
252  WifiModeList htMcsList = GetHtDeviceMcsList ();
253  for (uint8_t i = 0; i < MAX_HT_GROUP_RATES; i++)
254  {
255  uint32_t deviceIndex = i + (m_minstrelGroups[groupId].streams - 1) * 8;
256  WifiMode mode = htMcsList[deviceIndex];
257  AddFirstMpduTxTime (groupId, mode, CalculateFirstMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
258  AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
259  }
260  NS_LOG_DEBUG ("Initialized group " << groupId << ": (" << (uint32_t)streams << "," << (uint32_t)sgi << "," << chWidth << ")");
261  }
262  }
263  }
264  }
265 
266  if (HasVhtSupported ())
267  {
268  // Initialize all VHT groups
269  for (uint32_t chWidth = 20; chWidth <= MAX_VHT_WIDTH; chWidth *= 2)
270  {
271  for (uint8_t sgi = 0; sgi <= 1; sgi++)
272  {
273  for (uint8_t streams = 1; streams <= MAX_SUPPORTED_STREAMS; streams++)
274  {
275  uint32_t groupId = GetVhtGroupId (streams, sgi, chWidth);
276 
277  m_minstrelGroups[groupId].streams = streams;
278  m_minstrelGroups[groupId].sgi = sgi;
279  m_minstrelGroups[groupId].chWidth = chWidth;
280  m_minstrelGroups[groupId].isVht = true;
281  m_minstrelGroups[groupId].isSupported = false;
282 
283  // Check capabilities of the device
284  if (!(!GetPhy ()->GetGuardInterval () && m_minstrelGroups[groupId].sgi)
285  && (GetPhy ()->GetChannelWidth () >= m_minstrelGroups[groupId].chWidth)
286  && (GetPhy ()->GetNumberOfTransmitAntennas () >= m_minstrelGroups[groupId].streams))
287  {
288  m_minstrelGroups[groupId].isSupported = true;
289 
290  // Calculate tx time for all rates of the group
291  WifiModeList vhtMcsList = GetVhtDeviceMcsList ();
292  for (uint8_t i = 0; i < MAX_VHT_GROUP_RATES; i++)
293  {
294  WifiMode mode = vhtMcsList[i];
295  // Check for invalid VHT MCSs and do not add time to array.
296  if (IsValidMcs (GetPhy (), streams, chWidth, mode))
297  {
298  AddFirstMpduTxTime (groupId, mode, CalculateFirstMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
299  AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
300  }
301  }
302  NS_LOG_DEBUG ("Initialized group " << groupId << ": (" << (uint32_t)streams << "," << (uint32_t)sgi << "," << chWidth << ")");
303  }
304  }
305  }
306  }
307  }
308  }
309 }
310 
311 void
313 {
314  NS_LOG_FUNCTION (this << mac);
315  m_legacyManager->SetupMac (mac);
317 }
318 
319 bool
320 MinstrelHtWifiManager::IsValidMcs (Ptr<WifiPhy> phy, uint8_t streams, uint32_t chWidth, WifiMode mode)
321 {
322  NS_LOG_FUNCTION (this << phy << (int)streams << chWidth << mode);
323 
324  WifiTxVector txvector;
325  txvector.SetNss (streams);
326  txvector.SetChannelWidth (chWidth);
327  txvector.SetMode (mode);
328  return phy->IsValidTxVector (txvector);
329 }
330 
331 Time
332 MinstrelHtWifiManager::CalculateFirstMpduTxDuration (Ptr<WifiPhy> phy, uint8_t streams, uint8_t sgi, uint32_t chWidth, WifiMode mode)
333 {
334  NS_LOG_FUNCTION (this << phy << (int)streams << (int)sgi << chWidth << mode);
335 
336  WifiTxVector txvector;
337  txvector.SetNss (streams);
338  txvector.SetShortGuardInterval (sgi);
339  txvector.SetChannelWidth (chWidth);
340  txvector.SetNess (0);
341  txvector.SetStbc (phy->GetStbc ());
342  txvector.SetMode (mode);
344 }
345 
346 Time
347 MinstrelHtWifiManager::CalculateMpduTxDuration (Ptr<WifiPhy> phy, uint8_t streams, uint8_t sgi, uint32_t chWidth, WifiMode mode)
348 {
349  NS_LOG_FUNCTION (this << phy << (int)streams << (int)sgi << chWidth << mode);
350 
351  WifiTxVector txvector;
352  txvector.SetNss (streams);
353  txvector.SetShortGuardInterval (sgi);
354  txvector.SetChannelWidth (chWidth);
355  txvector.SetNess (0);
356  txvector.SetStbc (phy->GetStbc ());
357  txvector.SetMode (mode);
359 }
360 
361 Time
363 {
364  NS_LOG_FUNCTION (this << groupId << mode);
365 
366  for (TxTime::const_iterator i = m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.begin (); i != m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.end (); i++)
367  {
368  if (mode == i->second)
369  {
370  return i->first;
371  }
372  }
373  NS_ASSERT (false);
374  return Seconds (0);
375 }
376 
377 void
379 {
380  NS_LOG_FUNCTION (this << groupId << mode << t);
381 
382  m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.push_back (std::make_pair (t, mode));
383 }
384 
385 Time
386 MinstrelHtWifiManager::GetMpduTxTime (uint32_t groupId, WifiMode mode) const
387 {
388  NS_LOG_FUNCTION (this << groupId << mode);
389 
390  for (TxTime::const_iterator i = m_minstrelGroups[groupId].ratesTxTimeTable.begin (); i != m_minstrelGroups[groupId].ratesTxTimeTable.end (); i++)
391  {
392  if (mode == i->second)
393  {
394  return i->first;
395  }
396  }
397  NS_ASSERT (false);
398  return Seconds (0);
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION (this << groupId << mode << t);
405 
406  m_minstrelGroups[groupId].ratesTxTimeTable.push_back (std::make_pair (t, mode));
407 }
408 
411 {
412  NS_LOG_FUNCTION (this);
413 
415 
416  // Initialize variables common to both stations.
418  station->m_col = 0;
419  station->m_index = 0;
420  station->m_maxTpRate = 0;
421  station->m_maxTpRate2 = 0;
422  station->m_maxProbRate = 0;
423  station->m_nModes = 0;
424  station->m_totalPacketsCount = 0;
425  station->m_samplePacketsCount = 0;
426  station->m_isSampling = false;
427  station->m_sampleRate = 0;
428  station->m_sampleDeferred = false;
429  station->m_shortRetry = 0;
430  station->m_longRetry = 0;
431  station->m_txrate = 0;
432  station->m_initialized = false;
433 
434  // Variables specific to HT station
435  station->m_sampleGroup = 0;
436  station->m_numSamplesSlow = 0;
437  station->m_sampleCount = 16;
438  station->m_sampleWait = 0;
439  station->m_sampleTries = 4;
440 
441  station->m_avgAmpduLen = 1;
442  station->m_ampduLen = 0;
443  station->m_ampduPacketCount = 0;
444 
445  // If the device supports HT
446  if (HasHtSupported () || HasVhtSupported ())
447  {
452  station->m_isHt = true;
453  }
454  // Use the variable in the station to indicate that the device do not support HT
455  else
456  {
457  station->m_isHt = false;
458  }
459 
460  return station;
461 }
462 
463 void
465 {
466  NS_LOG_FUNCTION (this << station);
467 
468  // Note: we appear to be doing late initialization of the table
469  // to make sure that the set of supported rates has been initialized
470  // before we perform our own initialization.
471  if (!station->m_initialized)
472  {
479  if (!GetHtSupported (station) && !GetVhtSupported (station))
480  {
481  NS_LOG_DEBUG ("Non-HT station " << station);
482  station->m_isHt = false;
483  // We will use non-HT minstrel for this station. Initialize the manager.
484  m_legacyManager->SetAttribute ("UpdateStatistics", TimeValue (m_updateStats));
485  m_legacyManager->SetAttribute ("LookAroundRate", DoubleValue (m_lookAroundRate));
486  m_legacyManager->SetAttribute ("EWMA", DoubleValue (m_ewmaLevel));
487  m_legacyManager->SetAttribute ("SampleColumn", UintegerValue (m_nSampleCol));
488  m_legacyManager->SetAttribute ("PacketLength", UintegerValue (m_frameLength));
489  m_legacyManager->SetAttribute ("PrintStats", BooleanValue (m_printStats));
490  m_legacyManager->CheckInit (station);
491  }
492  else
493  {
494  NS_LOG_DEBUG ("HT station " << station);
495  station->m_isHt = true;
496  station->m_nModes = GetNMcsSupported (station);
497  station->m_sampleTable = SampleRate (m_numRates, std::vector<uint32_t> (m_nSampleCol));
498  InitSampleTable (station);
499  RateInit (station);
500  std::ostringstream tmp;
501  tmp << "minstrel-ht-stats-" << station->m_state->m_address << ".txt";
502  station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
503  station->m_initialized = true;
504  }
505  }
506 }
507 
508 void
510  double rxSnr, WifiMode txMode)
511 {
512  NS_LOG_FUNCTION (this << st);
513 
514  NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelHtWifiRemoteStation *)st)->m_txrate);
515 }
516 
517 void
519 {
520  NS_LOG_FUNCTION (this << st);
521 
523 
524  CheckInit (station);
525  if (!station->m_initialized)
526  {
527  return;
528  }
529 
530  NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate);
531  station->m_shortRetry++;
532 }
533 
534 void
535 MinstrelHtWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
536 {
537  NS_LOG_FUNCTION (this << st);
538 
539  NS_LOG_DEBUG ("self=" << st << " rts ok");
540 }
541 
542 void
544 {
545  NS_LOG_FUNCTION (this << st);
546 
548  NS_LOG_DEBUG ("Final RTS failed");
549 
550  CheckInit (station);
551  if (!station->m_initialized)
552  {
553  return;
554  }
555 
556  UpdateRetry (station);
557 }
558 
559 void
561 {
562  NS_LOG_FUNCTION (this << st);
563 
565 
566  CheckInit (station);
567  if (!station->m_initialized)
568  {
569  return;
570  }
571 
572  if (!station->m_isHt)
573  {
574  m_legacyManager->UpdateRate (station);
575  }
576  else
577  {
578  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
579 
580  uint32_t rateId = GetRateId (station->m_txrate);
581  uint32_t groupId = GetGroupId (station->m_txrate);
582  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++; // Increment the attempts counter for the rate used.
583 
584  UpdateRate (station);
585  }
586 }
587 
588 void
590  double ackSnr, WifiMode ackMode, double dataSnr)
591 {
592  NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr);
594 
595  CheckInit (station);
596  if (!station->m_initialized)
597  {
598  return;
599  }
600 
601  NS_LOG_DEBUG ("Data OK - Txrate = " << station->m_txrate );
602 
603  if (!station->m_isHt)
604  {
605  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
606  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
607 
608  m_legacyManager->UpdatePacketCounters (station);
609 
610  UpdateRetry (station);
611  m_legacyManager->UpdateStats (station);
612 
613  if (station->m_nModes >= 1)
614  {
615  station->m_txrate = m_legacyManager->FindRate (station);
616  }
617  }
618  else
619  {
620  uint32_t rateId = GetRateId (station->m_txrate);
621  uint32_t groupId = GetGroupId (station->m_txrate);
622  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess++;
623  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++;
624 
625  UpdatePacketCounters (station, 1, 0);
626 
627  station->m_isSampling = false;
628  station->m_sampleDeferred = false;
629 
630  UpdateRetry (station);
631  if (Simulator::Now () >= station->m_nextStatsUpdate)
632  {
633  UpdateStats (station);
634  }
635 
636  if (station->m_nModes >= 1)
637  {
638  station->m_txrate = FindRate (station);
639  }
640  }
641 
642  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
643 }
644 
645 void
647 {
648  NS_LOG_FUNCTION (this << st);
650 
651  CheckInit (station);
652  if (!station->m_initialized)
653  {
654  return;
655  }
656 
657  NS_LOG_DEBUG ("DoReportFinalDataFailed - TxRate=" << station->m_txrate);
658 
659  if (!station->m_isHt)
660  {
661  m_legacyManager->UpdatePacketCounters (station);
662 
663  UpdateRetry (station);
664 
665  m_legacyManager->UpdateStats (station);
666  if (station->m_nModes >= 1)
667  {
668  station->m_txrate = m_legacyManager->FindRate (station);
669  }
670  }
671  else
672  {
673  UpdatePacketCounters (station, 0, 1);
674 
675  station->m_isSampling = false;
676  station->m_sampleDeferred = false;
677 
678  UpdateRetry (station);
679  if (Simulator::Now () >= station->m_nextStatsUpdate)
680  {
681  UpdateStats (station);
682  }
683 
684  if (station->m_nModes >= 1)
685  {
686  station->m_txrate = FindRate (station);
687  }
688  }
689  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
690 }
691 
692 void
693 MinstrelHtWifiManager::DoReportAmpduTxStatus (WifiRemoteStation *st, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus, double rxSnr, double dataSnr)
694 {
695  NS_LOG_FUNCTION (this << st << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr);
697 
698  CheckInit (station);
699  if (!station->m_initialized)
700  {
701  return;
702  }
703 
704  if (!station->m_isHt)
705  {
706  NS_ASSERT_MSG (false,"A-MPDU Tx Status called but no HT or VHT supported.");
707  }
708 
709  NS_LOG_DEBUG ("DoReportAmpduTxStatus. TxRate=" << station->m_txrate << " SuccMpdus= " <<
710  nSuccessfulMpdus << " FailedMpdus= " << nFailedMpdus);
711 
712  station->m_ampduPacketCount++;
713  station->m_ampduLen += nSuccessfulMpdus + nFailedMpdus;
714 
715  UpdatePacketCounters (station, nSuccessfulMpdus, nFailedMpdus);
716 
717  uint32_t rateId = GetRateId (station->m_txrate);
718  uint32_t groupId = GetGroupId (station->m_txrate);
719  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess += nSuccessfulMpdus;
720  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt += nSuccessfulMpdus + nFailedMpdus;
721 
722  if (nSuccessfulMpdus == 0 && station->m_longRetry < CountRetries (station))
723  {
724  // We do not receive a BlockAck. The entire AMPDU fail.
725  UpdateRate (station);
726  }
727  else
728  {
729  station->m_isSampling = false;
730  station->m_sampleDeferred = false;
731 
732  UpdateRetry (station);
733  if (Simulator::Now () >= station->m_nextStatsUpdate)
734  {
735  UpdateStats (station);
736  }
737 
738  if (station->m_nModes >= 1)
739  {
740  station->m_txrate = FindRate (station);
741  }
742  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate );
743  }
744 }
745 
746 void
748 {
749  NS_LOG_FUNCTION (this << station);
750 
772  CheckInit (station);
773  if (!station->m_initialized)
774  {
775  return;
776  }
777  station->m_longRetry++;
778 
782  uint32_t maxTpRateId = GetRateId (station->m_maxTpRate);
783  uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
784  uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
785  uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
786  uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
787  uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
788 
790  if (!station->m_isSampling)
791  {
793  if (station->m_longRetry < station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount)
794  {
795  NS_LOG_DEBUG ("Not Sampling; use the same rate again");
796  station->m_txrate = station->m_maxTpRate;
797  }
798 
800  else if (station->m_longRetry < ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
801  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount))
802  {
803  NS_LOG_DEBUG ("Not Sampling; use the Max TP2");
804  station->m_txrate = station->m_maxTpRate2;
805  }
806 
808  else if (station->m_longRetry <= ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
809  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
810  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount))
811  {
812  NS_LOG_DEBUG ("Not Sampling; use Max Prob");
813  station->m_txrate = station->m_maxProbRate;
814  }
815  else
816  {
817  NS_ASSERT_MSG (false,"Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry);
818  }
819  }
820 
822  else
823  {
826  if (station->m_longRetry < 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount)
827  {
828  NS_LOG_DEBUG ("Sampling use the MaxTP rate");
829  station->m_txrate = station->m_maxTpRate2;
830  }
831 
833  else if (station->m_longRetry <= 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
834  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount)
835  {
836  NS_LOG_DEBUG ("Sampling use the MaxProb rate");
837  station->m_txrate = station->m_maxProbRate;
838  }
839  else
840  {
841  NS_ASSERT_MSG (false,"Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry);
842  }
843  }
844  NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate);
845 }
846 
847 void
849 {
850  NS_LOG_FUNCTION (this << station);
851  station->m_shortRetry = 0;
852  station->m_longRetry = 0;
853 
854 }
855 
856 void
857 MinstrelHtWifiManager::UpdatePacketCounters (MinstrelHtWifiRemoteStation *station, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus)
858 {
859  NS_LOG_FUNCTION (this << station << nSuccessfulMpdus << nFailedMpdus);
860 
861  station->m_totalPacketsCount += nSuccessfulMpdus + nFailedMpdus;
862  if (station->m_isSampling)
863  {
864  station->m_samplePacketsCount += nSuccessfulMpdus + nFailedMpdus;
865  }
866  if (station->m_totalPacketsCount == ~0)
867  {
868  station->m_samplePacketsCount = 0;
869  station->m_totalPacketsCount = 0;
870  }
871 
872  if (!station->m_sampleWait && !station->m_sampleTries && station->m_sampleCount > 0)
873  {
874  station->m_sampleWait = 16 + 2 * station->m_avgAmpduLen;
875  station->m_sampleTries = 1;
876  station->m_sampleCount--;
877  }
878 
879 }
880 void
882 {
883  NS_LOG_FUNCTION (this << st);
885  station->DisposeStation ();
886 }
887 
890 {
891  NS_LOG_FUNCTION (this << st);
893 
894  if (!station->m_initialized)
895  {
896  CheckInit (station);
897  }
898 
899  if (!station->m_isHt)
900  {
901  WifiTxVector vector = m_legacyManager->GetDataTxVector (station);
902 
903  uint64_t dataRate = vector.GetMode ().GetDataRate (vector.GetChannelWidth (), vector.IsShortGuardInterval (), vector.GetNss ());
904  if (!station->m_isSampling)
905  {
906  m_rateChange (dataRate, station->m_state->m_address);
907  }
908 
909  return vector;
910  }
911  else
912  {
913  NS_LOG_DEBUG ("DoGetDataMode m_txrate= " << station->m_txrate);
914 
915  uint32_t rateId = GetRateId (station->m_txrate);
916  uint32_t groupId = GetGroupId (station->m_txrate);
917  uint32_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
918 
919  NS_LOG_DEBUG ("DoGetDataMode rateId= " << rateId << " groupId= " << groupId << " mode= " << GetMcsSupported (station, mcsIndex));
920 
921  McsGroup group = m_minstrelGroups[groupId];
922 
923  // Check consistency of rate selected.
924  if ((group.sgi && !GetShortGuardInterval (station)) || group.chWidth > GetChannelWidth (station) || (uint32_t) group.streams > GetNumberOfSupportedRxAntennas (station))
925  {
926  NS_ASSERT_MSG (false,"Inconsistent group selected. Group: (" << (uint32_t)group.streams << "," << (uint32_t)group.sgi << "," << group.chWidth << ")" <<
927  " Station capabilities: (" << GetNumberOfSupportedRxAntennas (station) << "," << GetShortGuardInterval (station) << "," << GetChannelWidth (station) << ")");
928  }
929 
930  uint64_t dataRate = GetMcsSupported (station, mcsIndex).GetDataRate (group.chWidth, group.sgi, group.streams);
931  if (!station->m_isSampling)
932  {
933  m_rateChange (dataRate, station->m_state->m_address);
934  }
935 
936  return WifiTxVector (GetMcsSupported (station, mcsIndex), GetDefaultTxPowerLevel (), GetLongRetryCount (station),
937  group.sgi, group.streams, GetNess (station), group.chWidth, GetAggregation (station) && !station->m_isSampling, GetStbc (station));
938  }
939 }
940 
943 {
944  NS_LOG_FUNCTION (this << st);
946 
947  if (!station->m_initialized)
948  {
949  CheckInit (station);
950  }
951 
952  if (!station->m_isHt)
953  {
954  return m_legacyManager->GetRtsTxVector (station);
955  }
956  else
957  {
958  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
959 
960  /* RTS is sent in a non-HT frame. RTS with HT is not supported yet in NS3.
961  * When supported, decision of using HT has to follow rules in Section 9.7.6 from 802.11-2012.
962  * From Sec. 9.7.6.5: "A frame other than a BlockAckReq or BlockAck that is carried in a
963  * non-HT PPDU shall be transmitted by the STA using a rate no higher than the highest
964  * rate in the BSSBasicRateSet parameter that is less than or equal to the rate or
965  * non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
966  * directed to the same receiving STA. If no rate in the BSSBasicRateSet parameter meets
967  * these conditions, the control frame shall be transmitted at a rate no higher than the
968  * highest mandatory rate of the attached PHY that is less than or equal to the rate
969  * or non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
970  * directed to the same receiving STA."
971  */
972 
973  // As we are in Minstrel HT, assume the last rate was an HT rate.
974  uint32_t rateId = GetRateId (station->m_txrate);
975  uint32_t groupId = GetGroupId (station->m_txrate);
976  uint32_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
977 
978  WifiMode lastRate = GetMcsSupported (station, mcsIndex);
979  uint64_t lastDataRate = lastRate.GetNonHtReferenceRate ();
980  uint32_t nBasicRates = GetNBasicModes ();
981 
982  WifiMode rtsRate;
983  bool rateFound = false;
984 
985  for (uint32_t i = 0; i < nBasicRates; i++)
986  {
987  uint64_t rate = GetBasicMode (i).GetDataRate (20,false,1);
988  if (rate <= lastDataRate)
989  {
990  rtsRate = GetBasicMode (i);
991  rateFound = true;
992  }
993  }
994 
995  if (!rateFound)
996  {
997  Ptr<WifiPhy> phy = GetPhy ();
998  uint32_t nSupportRates = phy->GetNModes ();
999  for (uint32_t i = 0; i < nSupportRates; i++)
1000  {
1001  uint64_t rate = phy->GetMode (i).GetDataRate (20,false,1);
1002  if (rate <= lastDataRate)
1003  {
1004  rtsRate = phy->GetMode (i);
1005  rateFound = true;
1006  }
1007  }
1008  }
1009 
1010  NS_ASSERT (rateFound);
1011 
1012  return WifiTxVector (rtsRate, GetDefaultTxPowerLevel (), GetShortRetryCount (station),
1013  false, 1, 0, GetChannelWidth (station), GetAggregation (station), false);
1014  }
1015 }
1016 
1017 bool
1019 {
1020  NS_LOG_FUNCTION (this << st << packet << normally);
1021 
1023 
1024  CheckInit (station);
1025  if (!station->m_initialized)
1026  {
1027  return normally;
1028  }
1029 
1030  uint32_t maxRetries;
1031 
1032  if (!station->m_isHt)
1033  {
1034  maxRetries = m_legacyManager->CountRetries (station);
1035  }
1036  else
1037  {
1038  maxRetries = CountRetries (station);
1039  }
1040 
1041  if (station->m_longRetry >= maxRetries)
1042  {
1043  NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << maxRetries);
1044  return false;
1045  }
1046  else
1047  {
1048  NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << maxRetries);
1049  return true;
1050  }
1051 }
1052 
1053 uint32_t
1055 {
1056  uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
1057  uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1058  uint32_t maxTpRateId = GetRateId (station->m_maxTpRate);
1059  uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1060  uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1061  uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1062 
1063  if (!station->m_isSampling)
1064  {
1065  return station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
1066  station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
1067  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1068  }
1069  else
1070  {
1071  return 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
1072  station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1073  }
1074 }
1075 
1076 bool
1078 {
1079  NS_LOG_FUNCTION (this);
1080  return true;
1081 }
1082 
1083 uint32_t
1085 {
1086  NS_LOG_FUNCTION (this << station);
1087 
1088  uint32_t sampleGroup = station->m_sampleGroup;
1089 
1090  uint32_t index = station->m_groupsTable[sampleGroup].m_index;
1091  uint32_t col = station->m_groupsTable[sampleGroup].m_col;
1092 
1093  uint32_t sampleIndex = station->m_sampleTable[index][col];
1094 
1095  uint32_t rateIndex = GetIndex (sampleGroup, sampleIndex);
1096  NS_LOG_DEBUG ("Next Sample is " << rateIndex );
1097 
1098  SetNextSample (station); //Calculate the next sample rate.
1099 
1100  return rateIndex;
1101 }
1102 
1103 void
1105 {
1106  NS_LOG_FUNCTION (this << station);
1107  do
1108  {
1109  station->m_sampleGroup++;
1110  station->m_sampleGroup %= m_numGroups;
1111  }
1112  while (!station->m_groupsTable[station->m_sampleGroup].m_supported);
1113 
1114  station->m_groupsTable[station->m_sampleGroup].m_index++;
1115 
1116  uint32_t sampleGroup = station->m_sampleGroup;
1117  uint8_t index = station->m_groupsTable[station->m_sampleGroup].m_index;
1118  uint8_t col = station->m_groupsTable[sampleGroup].m_col;
1119 
1120  if (index >= m_numRates)
1121  {
1122  station->m_groupsTable[station->m_sampleGroup].m_index = 0;
1123  station->m_groupsTable[station->m_sampleGroup].m_col++;
1124  if (station->m_groupsTable[station->m_sampleGroup].m_col >= m_nSampleCol)
1125  {
1126  station->m_groupsTable[station->m_sampleGroup].m_col = 0;
1127  }
1128  index = station->m_groupsTable[station->m_sampleGroup].m_index;
1129  col = station->m_groupsTable[sampleGroup].m_col;
1130  }
1131  NS_LOG_DEBUG ("New sample set: group= " << sampleGroup << " index= " << station->m_sampleTable[index][col]);
1132 }
1133 
1134 uint32_t
1136 {
1137  NS_LOG_FUNCTION (this << station);
1138  NS_LOG_DEBUG ("FindRate " << "packet=" << station->m_totalPacketsCount );
1139 
1140  if ((station->m_samplePacketsCount + station->m_totalPacketsCount) == 0)
1141  {
1142  return station->m_maxTpRate;
1143  }
1144 
1145  // If we have waited enough, then sample.
1146  if (station->m_sampleWait == 0 && station->m_sampleTries != 0)
1147  {
1148  //SAMPLING
1149  NS_LOG_DEBUG ("Obtaining a sampling rate");
1151  uint32_t sampleIdx = GetNextSample (station);
1152  NS_LOG_DEBUG ("Sampling rate = " << sampleIdx);
1153 
1154  //Evaluate if the sampling rate selected should be used.
1155  uint32_t sampleGroupId = GetGroupId (sampleIdx);
1156  uint32_t sampleRateId = GetRateId (sampleIdx);
1157 
1158  // If the rate selected is not supported, then don't sample.
1159  if (station->m_groupsTable[sampleGroupId].m_supported && station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId].supported)
1160  {
1168  HtRateInfo sampleRateInfo = station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId];
1169 
1170  NS_LOG_DEBUG ("Use sample rate? MaxTpRate= " << station->m_maxTpRate << " CurrentRate= " << station->m_txrate <<
1171  " SampleRate= " << sampleIdx << " SampleProb= " << sampleRateInfo.ewmaProb);
1172 
1173  if (sampleIdx != station->m_maxTpRate && sampleIdx != station->m_maxTpRate2
1174  && sampleIdx != station->m_maxProbRate && sampleRateInfo.ewmaProb <= 95)
1175  {
1176 
1182  uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1183  uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1184  uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1185  uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1186  uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
1187 
1188  uint8_t maxTpStreams = m_minstrelGroups[maxTpGroupId].streams;
1189  uint8_t sampleStreams = m_minstrelGroups[sampleGroupId].streams;
1190 
1191  Time sampleDuration = sampleRateInfo.perfectTxTime;
1192  Time maxTp2Duration = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].perfectTxTime;
1193  Time maxProbDuration = station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].perfectTxTime;
1194 
1195  NS_LOG_DEBUG ("Use sample rate? SampleDuration= " << sampleDuration << " maxTp2Duration= " << maxTp2Duration <<
1196  " maxProbDuration= " << maxProbDuration << " sampleStreams= " << (uint32_t)sampleStreams <<
1197  " maxTpStreams= " << (uint32_t)maxTpStreams);
1198  if (sampleDuration < maxTp2Duration || (sampleStreams <= maxTpStreams - 1 && sampleDuration < maxProbDuration))
1199  {
1201  station->m_isSampling = true;
1202 
1204  station->m_sampleRate = sampleIdx;
1205 
1206  NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx);
1207  station->m_sampleTries--;
1208  return sampleIdx;
1209  }
1210  else
1211  {
1212  station->m_numSamplesSlow++;
1213  if (sampleRateInfo.numSamplesSkipped >= 20 && station->m_numSamplesSlow <= 2)
1214  {
1216  station->m_isSampling = true;
1217 
1219  station->m_sampleRate = sampleIdx;
1220 
1221  NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx);
1222  station->m_sampleTries--;
1223  return sampleIdx;
1224  }
1225  }
1226  }
1227  }
1228  }
1229  if (station->m_sampleWait > 0)
1230  {
1231  station->m_sampleWait--;
1232  }
1233 
1235 
1236  NS_LOG_DEBUG ("FindRate " << "maxTpRrate=" << station->m_maxTpRate);
1237  return station->m_maxTpRate;
1238 }
1239 void
1241 {
1242  NS_LOG_FUNCTION (this << station);
1243 
1244  NS_LOG_DEBUG ("Updating stats=" << this);
1245 
1247 
1248  station->m_numSamplesSlow = 0;
1249  station->m_sampleCount = 0;
1250 
1251  double tempProb;
1252 
1253  if (station->m_ampduPacketCount > 0)
1254  {
1255  double newLen = station->m_ampduLen / station->m_ampduPacketCount;
1256  station->m_avgAmpduLen = ( newLen * (100 - m_ewmaLevel) + (station->m_avgAmpduLen * m_ewmaLevel) ) / 100;
1257  station->m_ampduLen = 0;
1258  station->m_ampduPacketCount = 0;
1259  }
1260 
1261  /* Initialize global rate indexes */
1262  station->m_maxTpRate = GetLowestIndex (station);
1263  station->m_maxTpRate2 = GetLowestIndex (station);
1264  station->m_maxProbRate = GetLowestIndex (station);
1265 
1267  for (uint32_t j = 0; j < m_numGroups; j++)
1268  {
1269  if (station->m_groupsTable[j].m_supported)
1270  {
1271  station->m_sampleCount++;
1272 
1273  /* (re)Initialize group rate indexes */
1274  station->m_groupsTable[j].m_maxTpRate = GetLowestIndex (station, j);
1275  station->m_groupsTable[j].m_maxTpRate2 = GetLowestIndex (station, j);
1276  station->m_groupsTable[j].m_maxProbRate = GetLowestIndex (station, j);
1277 
1278  for (uint32_t i = 0; i < m_numRates; i++)
1279  {
1280  if (station->m_groupsTable[j].m_ratesTable[i].supported)
1281  {
1282  station->m_groupsTable[j].m_ratesTable[i].retryUpdated = false;
1283 
1284  NS_LOG_DEBUG (i << " " << GetMcsSupported (station, station->m_groupsTable[j].m_ratesTable[i].mcsIndex) <<
1285  "\t attempt=" << station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<
1286  "\t success=" << station->m_groupsTable[j].m_ratesTable[i].numRateSuccess);
1287 
1289  if (station->m_groupsTable[j].m_ratesTable[i].numRateAttempt > 0)
1290  {
1291  station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped = 0;
1296  tempProb = (100 * station->m_groupsTable[j].m_ratesTable[i].numRateSuccess) / station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1297 
1299  station->m_groupsTable[j].m_ratesTable[i].prob = tempProb;
1300 
1301  if (station->m_groupsTable[j].m_ratesTable[i].successHist == 0)
1302  {
1303  station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1304  }
1305  else
1306  {
1307  station->m_groupsTable[j].m_ratesTable[i].ewmsdProb = CalculateEwmsd (station->m_groupsTable[j].m_ratesTable[i].ewmsdProb,
1308  tempProb, station->m_groupsTable[j].m_ratesTable[i].ewmaProb,
1309  m_ewmaLevel);
1311  tempProb = (tempProb * (100 - m_ewmaLevel) + station->m_groupsTable[j].m_ratesTable[i].ewmaProb * m_ewmaLevel) / 100;
1312  station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1313  }
1314 
1315  station->m_groupsTable[j].m_ratesTable[i].throughput = CalculateThroughput (station, j, i, tempProb);
1316 
1317  station->m_groupsTable[j].m_ratesTable[i].successHist += station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1318  station->m_groupsTable[j].m_ratesTable[i].attemptHist += station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1319  }
1320  else
1321  {
1322  station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped++;
1323  }
1324 
1326  station->m_groupsTable[j].m_ratesTable[i].prevNumRateSuccess = station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1327  station->m_groupsTable[j].m_ratesTable[i].prevNumRateAttempt = station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1328  station->m_groupsTable[j].m_ratesTable[i].numRateSuccess = 0;
1329  station->m_groupsTable[j].m_ratesTable[i].numRateAttempt = 0;
1330 
1331  if (station->m_groupsTable[j].m_ratesTable[i].throughput != 0)
1332  {
1333  SetBestStationThRates (station, GetIndex (j, i));
1334  SetBestProbabilityRate (station, GetIndex (j, i));
1335  }
1336 
1337  }
1338  }
1339  }
1340  }
1341 
1342  //Try to sample all available rates during each interval.
1343  station->m_sampleCount *= 8;
1344 
1345  //Recalculate retries for the rates selected.
1346  CalculateRetransmits (station, station->m_maxTpRate);
1347  CalculateRetransmits (station, station->m_maxTpRate2);
1348  CalculateRetransmits (station, station->m_maxProbRate);
1349 
1350  NS_LOG_DEBUG ("max tp=" << station->m_maxTpRate << "\nmax tp2=" << station->m_maxTpRate2 << "\nmax prob=" << station->m_maxProbRate);
1351  if (m_printStats)
1352  {
1353  PrintTable (station);
1354  }
1355 }
1356 
1357 double
1358 MinstrelHtWifiManager::CalculateThroughput (MinstrelHtWifiRemoteStation *station, uint32_t groupId, uint32_t rateId, double ewmaProb)
1359 {
1365  if (ewmaProb < 10)
1366  {
1367  return 0;
1368  }
1369  else
1370  {
1375  Time txTime = station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime;
1376  if (ewmaProb > 90)
1377  {
1378  return 90 / txTime.GetSeconds ();
1379  }
1380  else
1381  {
1382  return ewmaProb / txTime.GetSeconds ();
1383  }
1384  }
1385 }
1386 
1387 void
1389 {
1390  GroupInfo *group;
1391  HtRateInfo rate;
1392  uint32_t tmpGroupId, tmpRateId;
1393  double tmpTh, tmpProb;
1394  uint32_t groupId, rateId;
1395  double currentTh;
1396  // maximum group probability (GP) variables
1397  uint32_t maxGPGroupId, maxGPRateId;
1398  double maxGPTh;
1399 
1400  groupId = GetGroupId (index);
1401  rateId = GetRateId (index);
1402  group = &station->m_groupsTable[groupId];
1403  rate = group->m_ratesTable[rateId];
1404 
1405  tmpGroupId = GetGroupId (station->m_maxProbRate);
1406  tmpRateId = GetRateId (station->m_maxProbRate);
1407  tmpProb = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].ewmaProb;
1408  tmpTh = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].throughput;
1409 
1410  if (rate.ewmaProb > 75)
1411  {
1412  currentTh = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1413  if (currentTh > tmpTh)
1414  {
1415  station->m_maxProbRate = index;
1416  }
1417 
1418  maxGPGroupId = GetGroupId (group->m_maxProbRate);
1419  maxGPRateId = GetRateId (group->m_maxProbRate);
1420  maxGPTh = station->m_groupsTable[maxGPGroupId].m_ratesTable[maxGPRateId].throughput;
1421 
1422  if (currentTh > maxGPTh)
1423  {
1424  group->m_maxProbRate = index;
1425  }
1426  }
1427  else
1428  {
1429  if (rate.ewmaProb > tmpProb)
1430  {
1431  station->m_maxProbRate = index;
1432  }
1433  if (rate.ewmaProb > group->m_ratesTable[group->m_maxProbRate].ewmaProb)
1434  {
1435  group->m_maxProbRate = index;
1436  }
1437  }
1438 }
1439 
1440 /*
1441  * Find & sort topmost throughput rates
1442  *
1443  * If multiple rates provide equal throughput the sorting is based on their
1444  * current success probability. Higher success probability is preferred among
1445  * MCS groups.
1446  */
1447 void
1449 {
1450  uint32_t groupId, rateId;
1451  double th, prob;
1452  uint32_t maxTpGroupId, maxTpRateId;
1453  uint32_t maxTp2GroupId, maxTp2RateId;
1454  double maxTpTh, maxTpProb;
1455  double maxTp2Th, maxTp2Prob;
1456 
1457  groupId = GetGroupId (index);
1458  rateId = GetRateId (index);
1459  prob = station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb;
1460  th = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1461 
1462  maxTpGroupId = GetGroupId (station->m_maxTpRate);
1463  maxTpRateId = GetRateId (station->m_maxTpRate);
1464  maxTpProb = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].ewmaProb;
1465  maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1466 
1467  maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1468  maxTp2RateId = GetRateId (station->m_maxTpRate2);
1469  maxTp2Prob = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].ewmaProb;
1470  maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1471 
1472  if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1473  {
1474  station->m_maxTpRate2 = station->m_maxTpRate;
1475  station->m_maxTpRate = index;
1476  }
1477  else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1478  {
1479  station->m_maxTpRate2 = index;
1480  }
1481 
1482  //Find best rates per group
1483 
1484  GroupInfo *group = &station->m_groupsTable[groupId];
1485  maxTpGroupId = GetGroupId (group->m_maxTpRate);
1486  maxTpRateId = GetRateId (group->m_maxTpRate);
1487  maxTpProb = group->m_ratesTable[maxTpRateId].ewmaProb;
1488  maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1489 
1490  maxTp2GroupId = GetGroupId (group->m_maxTpRate2);
1491  maxTp2RateId = GetRateId (group->m_maxTpRate2);
1492  maxTp2Prob = group->m_ratesTable[maxTp2RateId].ewmaProb;
1493  maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1494 
1495  if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1496  {
1497  group->m_maxTpRate2 = group->m_maxTpRate;
1498  group->m_maxTpRate = index;
1499  }
1500  else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1501  {
1502  group->m_maxTpRate2 = index;
1503  }
1504 }
1505 
1506 void
1508 {
1509  NS_LOG_FUNCTION (this << station);
1510  NS_LOG_DEBUG ("RateInit=" << station);
1511 
1512  station->m_groupsTable = McsGroupData (m_numGroups);
1513 
1517  NS_LOG_DEBUG ("Supported groups by station:");
1518  for (uint32_t groupId = 0; groupId < m_numGroups; groupId++)
1519  {
1520  if (m_minstrelGroups[groupId].isSupported)
1521  {
1522  station->m_groupsTable[groupId].m_supported = false;
1523  if (!(!GetVhtSupported (station) && m_minstrelGroups[groupId].isVht)
1524  && (m_minstrelGroups[groupId].isVht || !GetVhtSupported (station) || !m_useVhtOnly)
1525  && !(!GetShortGuardInterval (station) && m_minstrelGroups[groupId].sgi)
1526  && (GetChannelWidth (station) >= m_minstrelGroups[groupId].chWidth)
1527  && (GetNumberOfSupportedRxAntennas (station) >= m_minstrelGroups[groupId].streams))
1528  {
1529  NS_LOG_DEBUG ("Group " << groupId << ": (" << (uint32_t)m_minstrelGroups[groupId].streams <<
1530  "," << (uint32_t)m_minstrelGroups[groupId].sgi << "," << m_minstrelGroups[groupId].chWidth << ")");
1531 
1532  station->m_groupsTable[groupId].m_supported = true;
1533  station->m_groupsTable[groupId].m_col = 0;
1534  station->m_groupsTable[groupId].m_index = 0;
1535 
1536  station->m_groupsTable[groupId].m_ratesTable = HtMinstrelRate (m_numRates);
1537  for (uint32_t i = 0; i < m_numRates; i++)
1538  {
1539  station->m_groupsTable[groupId].m_ratesTable[i].supported = false;
1540  }
1541 
1542  // Initialize all modes supported by the remote station that belong to the current group.
1543  for (uint32_t i = 0; i < station->m_nModes; i++)
1544  {
1545  WifiMode mode = GetMcsSupported (station, i);
1546 
1549  uint32_t rateId = mode.GetMcsValue ();
1550  if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1551  {
1552  rateId %= MAX_HT_GROUP_RATES;
1553  }
1554 
1555  if ((m_minstrelGroups[groupId].isVht && mode.GetModulationClass () == WIFI_MOD_CLASS_VHT
1556  && IsValidMcs (GetPhy (), m_minstrelGroups[groupId].streams, m_minstrelGroups[groupId].chWidth, mode))
1557  || (!m_minstrelGroups[groupId].isVht && mode.GetModulationClass () == WIFI_MOD_CLASS_HT
1558  && mode.GetMcsValue () < (m_minstrelGroups[groupId].streams * 8)
1559  && mode.GetMcsValue () >= ((m_minstrelGroups[groupId].streams - 1) * 8)))
1560  {
1561  NS_LOG_DEBUG ("Mode " << i << ": " << mode << " isVht: " << m_minstrelGroups[groupId].isVht);
1562 
1563  station->m_groupsTable[groupId].m_ratesTable[rateId].supported = true;
1564  station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex = i;
1565  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt = 0;
1566  station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess = 0;
1567  station->m_groupsTable[groupId].m_ratesTable[rateId].prob = 0;
1568  station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb = 0;
1569  station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateAttempt = 0;
1570  station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateSuccess = 0;
1571  station->m_groupsTable[groupId].m_ratesTable[rateId].numSamplesSkipped = 0;
1572  station->m_groupsTable[groupId].m_ratesTable[rateId].successHist = 0;
1573  station->m_groupsTable[groupId].m_ratesTable[rateId].attemptHist = 0;
1574  station->m_groupsTable[groupId].m_ratesTable[rateId].throughput = 0;
1575  station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, i));
1576  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 0;
1577  station->m_groupsTable[groupId].m_ratesTable[rateId].adjustedRetryCount = 0;
1578  CalculateRetransmits (station, groupId, rateId);
1579  }
1580  }
1581  }
1582  }
1583  }
1584  SetNextSample (station);
1585  UpdateStats (station);
1586  station->m_txrate = FindRate (station);
1587 }
1588 
1589 void
1591 {
1592  NS_LOG_FUNCTION (this << station << index);
1593  uint32_t groupId = GetGroupId (index);
1594  uint32_t rateId = GetRateId (index);
1595  if (!station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated)
1596  {
1597  CalculateRetransmits (station, groupId, rateId);
1598  }
1599 }
1600 
1601 void
1603 {
1604  NS_LOG_FUNCTION (this << station << groupId << groupId);
1605  NS_LOG_DEBUG (" Calculating the number of retries");
1606 
1607  uint32_t cw = 15; // Is an approximation.
1608  uint32_t cwMax = 1023;
1609  Time cwTime, txTime, dataTxTime;
1610  Time slotTime = GetMac ()->GetSlot ();
1611  Time ackTime = GetMac ()->GetBasicBlockAckTimeout ();
1612 
1613  if (station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb < 1)
1614  {
1615  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 1;
1616  }
1617  else
1618  {
1619  station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 2;
1620  station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated = true;
1621 
1622  dataTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) +
1623  GetMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) * (station->m_avgAmpduLen - 1);
1624 
1625  /* Contention time for first 2 tries */
1626  cwTime = (cw / 2) * slotTime;
1627  cw = Min ((cw + 1) * 2, cwMax);
1628  cwTime += (cw / 2) * slotTime;
1629  cw = Min ((cw + 1) * 2, cwMax);
1630 
1631  /* Total TX time for data and Contention after first 2 tries */
1632  txTime = cwTime + 2 * (dataTxTime + ackTime);
1633 
1634  /* See how many more tries we can fit inside segment size */
1635  do
1636  {
1637  /* Contention time for this try */
1638  cwTime = (cw / 2) * slotTime;
1639  cw = Min ((cw + 1) * 2, cwMax);
1640 
1641  /* Total TX time after this try */
1642  txTime += cwTime + ackTime + dataTxTime;
1643  }
1644  while ((txTime < MilliSeconds (6))
1645  && (++station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount < 7));
1646  }
1647 }
1648 
1649 double
1650 MinstrelHtWifiManager::CalculateEwmsd (double oldEwmsd, double currentProb, double ewmaProb, uint32_t weight)
1651 {
1652  double diff, incr, tmp;
1653 
1654  /* calculate exponential weighted moving variance */
1655  diff = currentProb - ewmaProb;
1656  incr = (100 - weight) * diff / 100;
1657  tmp = oldEwmsd * oldEwmsd;
1658  tmp = weight * (tmp + diff * incr) / 100;
1659 
1660  /* return standard deviation */
1661  return sqrt (tmp);
1662 }
1663 
1664 void
1666 {
1667  NS_LOG_DEBUG ("InitSampleTable=" << this);
1668 
1669  station->m_col = station->m_index = 0;
1670 
1671  //for off-setting to make rates fall between 0 and nModes
1672  uint32_t numSampleRates = m_numRates;
1673 
1674  uint32_t newIndex;
1675  for (uint32_t col = 0; col < m_nSampleCol; col++)
1676  {
1677  for (uint32_t i = 0; i < numSampleRates; i++ )
1678  {
1683  int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
1684  newIndex = (i + uv) % numSampleRates;
1685 
1686  //this loop is used for filling in other uninitialized places
1687  while (station->m_sampleTable[newIndex][col] != 0)
1688  {
1689  newIndex = (newIndex + 1) % m_numRates;
1690  }
1691  station->m_sampleTable[newIndex][col] = i;
1692  }
1693  }
1694 }
1695 
1696 void
1698 {
1699  NS_LOG_FUNCTION (this << station);
1700  NS_LOG_DEBUG ("PrintTable=" << station);
1701 
1702  station->m_statsFile << " best ____________rate__________ ________statistics________ ________last_______ ______sum-of________\n" <<
1703  " mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1704  for (uint32_t i = 0; i < m_numGroups; i++)
1705  {
1706  StatsDump (station, i, station->m_statsFile);
1707  }
1708 
1709  station->m_statsFile << "\nTotal packet count:: ideal " << Max (0, station->m_totalPacketsCount - station->m_samplePacketsCount) <<
1710  " lookaround " << station->m_samplePacketsCount << "\n";
1711  station->m_statsFile << "Average # of aggregated frames per A-MPDU: " << station->m_avgAmpduLen << "\n\n";
1712 
1713  station->m_statsFile.flush ();
1714 }
1715 
1716 void
1717 MinstrelHtWifiManager::StatsDump (MinstrelHtWifiRemoteStation *station, uint32_t groupId, std::ofstream &of)
1718 {
1719  uint32_t numRates = m_numRates;
1720  McsGroup group = m_minstrelGroups[groupId];
1721  Time txTime;
1722  char giMode;
1723  if (group.sgi)
1724  {
1725  giMode = 'S';
1726  }
1727  else
1728  {
1729  giMode = 'L';
1730  }
1731  for (uint32_t i = 0; i < numRates; i++)
1732  {
1733  if (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[i].supported)
1734  {
1735  if (!group.isVht)
1736  {
1737  of << "HT" << group.chWidth << " " << giMode << "GI " << (int)group.streams << " ";
1738  }
1739  else
1740  {
1741  of << "VHT" << group.chWidth << " " << giMode << "GI " << (int)group.streams << " ";
1742  }
1743 
1744  uint32_t maxTpRate = station->m_maxTpRate;
1745  uint32_t maxTpRate2 = station->m_maxTpRate2;
1746  uint32_t maxProbRate = station->m_maxProbRate;
1747 
1748  uint32_t idx = GetIndex (groupId, i);
1749  if (idx == maxTpRate)
1750  {
1751  of << 'A';
1752  }
1753  else
1754  {
1755  of << ' ';
1756  }
1757  if (idx == maxTpRate2)
1758  {
1759  of << 'B';
1760  }
1761  else
1762  {
1763  of << ' ';
1764  }
1765  if (idx == maxProbRate)
1766  {
1767  of << 'P';
1768  }
1769  else
1770  {
1771  of << ' ';
1772  }
1773 
1774  if (!group.isVht)
1775  {
1776  of << std::setw (4) << " MCS" << (group.streams - 1) * 8 + i;
1777  }
1778  else
1779  {
1780  of << std::setw (7) << " MCS" << i << "/" << (int) group.streams;
1781  }
1782 
1783  of << " " << std::setw (3) << idx << " ";
1784 
1785  /* tx_time[rate(i)] in usec */
1786  txTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[i].mcsIndex));
1787  of << std::setw (6) << txTime.GetMicroSeconds () << " ";
1788 
1789  of << std::setw (7) << CalculateThroughput (station, groupId, i, 100) / 100 << " " <<
1790  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].throughput / 100 << " " <<
1791  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmaProb << " " <<
1792  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmsdProb << " " <<
1793  std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].prob << " " <<
1794  std::setw (2) << station->m_groupsTable[groupId].m_ratesTable[i].retryCount << " " <<
1795  std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateSuccess << " " <<
1796  std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt << " " <<
1797  std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].successHist << " " <<
1798  std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].attemptHist << "\n";
1799  }
1800  }
1801 }
1802 uint32_t
1803 MinstrelHtWifiManager::GetIndex (uint32_t groupId, uint32_t rateId)
1804 {
1805  NS_LOG_FUNCTION (this << groupId << rateId);
1806  uint32_t index;
1807  index = groupId * m_numRates + rateId;
1808  return index;
1809 }
1810 
1811 uint32_t
1813 {
1814  NS_LOG_FUNCTION (this << index);
1815 
1816  uint32_t id;
1817  id = index % m_numRates;
1818  return id;
1819 }
1820 
1821 uint32_t
1823 {
1824  NS_LOG_FUNCTION (this << index);
1825 
1826  return index / m_numRates;
1827 }
1828 
1829 uint32_t
1830 MinstrelHtWifiManager::GetHtGroupId (uint8_t txstreams, uint8_t sgi, uint32_t chWidth)
1831 {
1832  NS_LOG_FUNCTION (this << (int)txstreams << (int)sgi << chWidth);
1833 
1834  return MAX_SUPPORTED_STREAMS * 2 * (chWidth == 40 ? 1 : 0) + MAX_SUPPORTED_STREAMS * sgi + txstreams - 1;
1835 }
1836 
1837 uint32_t
1838 MinstrelHtWifiManager::GetVhtGroupId (uint8_t txstreams, uint8_t sgi, uint32_t chWidth)
1839 {
1840  NS_LOG_FUNCTION (this << (int)txstreams << (int)sgi << chWidth);
1841 
1842  return MAX_HT_STREAM_GROUPS * MAX_SUPPORTED_STREAMS + MAX_SUPPORTED_STREAMS * 2 * (chWidth == 160 ? 3 : chWidth == 80 ? 2 : chWidth == 40 ? 1 : 0) + MAX_SUPPORTED_STREAMS * sgi + txstreams - 1;
1843 }
1844 
1845 uint32_t
1847 {
1848  NS_LOG_FUNCTION (this << station);
1849 
1850  uint32_t groupId = 0;
1851  uint32_t rateId = 0;
1852  while (groupId < m_numGroups && !station->m_groupsTable[groupId].m_supported)
1853  {
1854  groupId++;
1855  }
1856  while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1857  {
1858  rateId++;
1859  }
1860  NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported);
1861  return GetIndex (groupId, rateId);
1862 }
1863 
1864 uint32_t
1866 {
1867  NS_LOG_FUNCTION (this << station);
1868 
1869  uint32_t rateId = 0;
1870  while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1871  {
1872  rateId++;
1873  }
1874  NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported);
1875  return GetIndex (groupId, rateId);
1876 }
1877 
1878 
1881 {
1882  WifiModeList vhtMcsList;
1883  Ptr<WifiPhy> phy = GetPhy ();
1884  for (uint32_t i = 0; i < phy->GetNMcs (); i++)
1885  {
1886  WifiMode mode = phy->GetMcs (i);
1887  if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)
1888  {
1889  vhtMcsList.push_back (mode);
1890  }
1891  }
1892  return vhtMcsList;
1893 }
1894 
1897 {
1898  WifiModeList htMcsList;
1899  Ptr<WifiPhy> phy = GetPhy ();
1900  for (uint32_t i = 0; i < phy->GetNMcs (); i++)
1901  {
1902  WifiMode mode = phy->GetMcs (i);
1903  if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1904  {
1905  htMcsList.push_back (mode);
1906  }
1907  }
1908  return htMcsList;
1909 }
1910 
1911 } // namespace ns3
1912 
1913 
1914 
1915 
1916 
virtual void DoReportRtsOk(WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr)
This method is a pure virtual method that must be implemented by the sub-class.
virtual uint32_t GetFrequency(void) const =0
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
void SetShortGuardInterval(bool guardinterval)
Sets if short gurad interval is being used.
A struct to contain information of a group.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
AttributeValue implementation for Boolean.
Definition: boolean.h:34
double CalculateThroughput(MinstrelHtWifiRemoteStation *station, uint32_t groupId, uint32_t rateId, double ewmaProb)
Return the average throughput of the MCS defined by groupId and rateId.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
static const uint8_t MAX_SUPPORTED_STREAMS
Constants for maximum values.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
WifiModeList GetHtDeviceMcsList(void) const
Returns a list of only the HT MCS supported by the device.
void PrintTable(MinstrelHtWifiRemoteStation *station)
Printing Minstrel Table.
uint32_t GetHtGroupId(uint8_t txstreams, uint8_t sgi, uint32_t chWidth)
Returns the groupId of a HT MCS with the given number of streams, if using sgi and the channel width ...
virtual uint32_t GetNModes(void) const =0
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
uint32_t GetLowestIndex(MinstrelHtWifiRemoteStation *station)
Returns the lowest global index of the rates supported by the station.
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:81
uint32_t m_maxProbRate
The highest success probability rate of this group.
double CalculateEwmsd(double oldEwmsd, double currentProb, double ewmaProb, uint32_t weight)
Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation.
virtual WifiTxVector DoGetDataTxVector(WifiRemoteStation *station)
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:384
virtual uint8_t GetNMcs(void) const =0
The WifiPhy::GetNMcs() method is used (e.g., by a WifiRemoteStationManager) to determine the set of t...
hold per-remote-station state for Minstrel Wifi manager.
uint32_t m_ampduPacketCount
Number of A-MPDUs transmitted.
uint32_t GetIndex(uint32_t groupId, uint32_t rateId)
Returns the global index corresponding to the groupId and rateId.
static const uint8_t MAX_VHT_STREAM_GROUPS
Maximal number of groups per stream in VHT (4 possible channel widths and 2 possible SGI configuratio...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t m_sampleRate
current sample rate
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:903
uint32_t m_maxTpRate
The max throughput rate of this group.
void SetStbc(bool stbc)
Sets if STBC is being used.
bool IsShortGuardInterval(void) const
std::vector< struct McsGroup > MinstrelMcsGroups
Data structure for a table of group definitions.
virtual void DoReportFinalRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
Mac48Address m_address
Mac48Address of the remote station.
void StatsDump(MinstrelHtWifiRemoteStation *station, uint32_t index, std::ofstream &of)
Print group statistics.
HtMinstrelRate m_ratesTable
Information about rates of this group.
uint32_t m_txrate
current transmit rate
virtual void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode)
This method is a pure virtual method that must be implemented by the sub-class.
WifiMode GetMcsSupported(const WifiRemoteStation *station, uint32_t i) const
Return the WifiMode supported by the specified station at the specified index.
virtual bool DoNeedDataRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally)
VHT PHY (Clause 22)
Definition: wifi-mode.h:64
MinstrelRate m_minstrelTable
minstrel table
uint32_t m_frameLength
Frame length used for calculate modes TxTime.
MinstrelMcsGroups m_minstrelGroups
Global array for groups information.
bool m_isHt
If the station is HT capable.
bool m_sampleDeferred
a flag to indicate sample rate is on the second stage
uint32_t m_maxTpRate2
The second max throughput rate of this group.
void UpdatePacketCounters(MinstrelHtWifiRemoteStation *station, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus)
Update the number of sample count variables.
virtual void SetupPhy(Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:99
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
virtual WifiMode GetMcs(uint8_t mcs) const =0
The WifiPhy::GetMcs() method is used (e.g., by a WifiRemoteStationManager) to determine the set of tr...
WifiRemoteStationState * m_state
Remote station state.
bool m_printStats
If statistics table should be printed.
void SetChannelWidth(uint32_t channelWidth)
Sets the selected channelWidth (in MHz)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
Ptr< WifiPhy > GetPhy(void) const
Return the WifiPhy.
bool GetStbc(const WifiRemoteStation *station) const
Return whether the given station supports space-time block coding (STBC).
uint32_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:341
virtual bool GetStbc(void) const =0
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:197
Time CalculateFirstMpduTxDuration(Ptr< WifiPhy > phy, uint8_t streams, uint8_t sgi, uint32_t chWidth, WifiMode mode)
Estimates the TxTime of a frame with a given mode and group (stream, guard interval and channel width...
void AddFirstMpduTxTime(uint32_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
tuple phy
Definition: third.py:86
bool m_isSampling
a flag to indicate we are currently sampling
virtual WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:349
AttributeValue implementation for Time.
Definition: nstime.h:957
double m_ewmaLevel
Exponential weighted moving average level (or coefficient).
void CalculateRetransmits(MinstrelHtWifiRemoteStation *station, uint32_t index)
Calculate the number of retransmissions to set for the index rate.
SampleRate m_sampleTable
sample table
Hold an unsigned integer type.
Definition: uinteger.h:44
static const uint8_t MAX_VHT_GROUP_RATES
Number of rates (or MCS) per VHT group.
Time GetMpduTxTime(uint32_t groupId, WifiMode mode) const
Obtain the TXtime saved in the group information.
static const uint8_t MAX_HT_WIDTH
Maximal channel width.
WifiMode GetBasicMode(uint32_t i) const
Return a basic mode from the set of basic modes.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:209
static const uint8_t MAX_HT_STREAM_GROUPS
Maximal number of groups per stream in HT (2 possible channel widths and 2 possible SGI configuration...
uint32_t GetChannelWidth(void) const
virtual void DoDisposeStation(WifiRemoteStation *station)
HT PHY (Clause 20)
Definition: wifi-mode.h:62
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:362
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, enum WifiPreamble preamble, double frequency)
Definition: wifi-phy.cc:717
uint32_t GetRateId(uint32_t index)
For managing rates from different groups, a global index for all rates in all groups is used...
uint32_t m_sampleWait
How many transmission attempts to wait until a new sample.
virtual void SetupPhy(Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
tuple mac
Definition: third.py:92
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
hold a list of per-remote-station state.
bool m_useVhtOnly
If only VHT MCS should be used, instead of HT and VHT.
std::vector< struct GroupInfo > McsGroupData
Data structure for a table of groups.
uint32_t m_longRetry
long retries such as data packets
static const uint8_t MAX_VHT_WIDTH
Maximal channel width.
The MPDU is part of an A-MPDU, but is not the last aggregate.
Definition: wifi-phy.h:50
uint32_t GetNess(const WifiRemoteStation *station) const
void SetNss(uint8_t nss)
Sets the number of Nss refer to IEEE 802.11n Table 20-28 for explanation and range.
bool m_initialized
for initializing tables
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
virtual WifiRemoteStation * DoCreateStation(void) const
uint32_t GetVhtGroupId(uint8_t txstreams, uint8_t sgi, uint32_t chWidth)
Returns the groupId of a VHT MCS with the given number of streams, if using sgi and the channel width...
double ewmaProb
Exponential weighted moving average of probability.
Time perfectTxTime
Perfect transmission time calculation, or frame calculation.
uint8_t m_numRates
Number of rates per group Minstrel should consider.
uint32_t m_maxTpRate2
second highest throughput rate
void SetBestStationThRates(MinstrelHtWifiRemoteStation *station, uint32_t index)
Set index rate as maxTpRate or maxTp2Rate if is better than current values.
void InitSampleTable(MinstrelHtWifiRemoteStation *station)
Initialize Sample Table.
static bool IsValidTxVector(WifiTxVector txVector)
The standard disallows certain combinations of WifiMode, number of spatial streams, and channel widths.
Definition: wifi-phy.cc:1563
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
virtual void DoReportRtsFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
void UpdateRetry(MinstrelHtWifiRemoteStation *station)
Update the number of retries and reset accordingly.
uint32_t m_nSampleCol
Number of sample columns.
uint32_t m_sampleCount
Max number of samples per update interval.
virtual void DoReportFinalDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
uint8_t m_numGroups
Number of groups Minstrel should consider.
virtual void SetupMac(Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
Time m_updateStats
How frequent do we calculate the stats (1/10 seconds).
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
uint64_t GetDataRate(uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
Definition: wifi-mode.cc:109
static const uint8_t MAX_HT_GROUP_RATES
Number of rates (or MCS) per HT group.
virtual void DoReportDataFailed(WifiRemoteStation *station)
This method is a pure virtual method that must be implemented by the sub-class.
virtual WifiMode GetMode(uint32_t mode) const =0
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
void UpdateStats(MinstrelHtWifiRemoteStation *station)
Updating the Minstrel Table every 1/10 seconds.
McsGroupData m_groupsTable
Table of groups with stats.
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:958
std::vector< WifiMode > WifiModeList
In various parts of the code, folk are interested in maintaining a list of transmission modes...
Definition: wifi-mode.h:233
bool GetShortGuardInterval(const WifiRemoteStation *station) const
Return whether the given station supports short guard interval.
WifiModeList GetVhtDeviceMcsList(void) const
Returns a list of only the VHT MCS supported by the device.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
double m_ampduLen
Number of MPDUs in an A-MPDU.
std::ofstream m_statsFile
File where statistics table is written.
void RateInit(MinstrelHtWifiRemoteStation *station)
Initialize Minstrel Table.
int m_totalPacketsCount
total number of packets as of now
uint64_t GetNonHtReferenceRate(void) const
Definition: wifi-mode.cc:391
virtual void SetupMac(Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
Implementation of Minstrel HT Rate Control AlgorithmMinstrel-HT is a rate adaptation mechanism for th...
uint32_t FindRate(MinstrelHtWifiRemoteStation *station)
Find a rate to use from Minstrel Table.
uint8_t GetNumberOfSupportedRxAntennas(const WifiRemoteStation *station) const
Return the number of receive antennas the station has.
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
Data structure to contain the information that defines a group.
#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:90
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
virtual void DoInitialize(void)
Initialize() implementation.
int m_samplePacketsCount
how many packets we have sample so far
double m_lookAroundRate
The % to try other rates than our current rate.
uint32_t m_maxProbRate
rate with highest prob of success
uint8_t GetNss(void) const
uint32_t GetNBasicModes(void) const
Return the number of basic modes we support.
uint32_t GetLongRetryCount(const WifiRemoteStation *station) const
Return the long retry limit of the given station.
uint32_t GetNMcsSupported(const WifiRemoteStation *station) const
Return the number of MCS supported by the given station.
uint32_t m_nModes
number of modes supported
void AddMpduTxTime(uint32_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
A struct to contain all statistics information related to a data rate.
bool GetVhtSupported(const WifiRemoteStation *station) const
Return whether the given station is VHT capable.
void SetNextSample(MinstrelHtWifiRemoteStation *station)
Set the next sample from Sample Table.
uint32_t m_maxTpRate
the current throughput rate
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
uint32_t m_numSamplesSlow
Number of times a slow rate was sampled.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
Ptr< MinstrelWifiManager > m_legacyManager
Pointer to an instance of MinstrelWifiManager.
uint32_t numSamplesSkipped
Number of times this rate statistics were not updated because no attempts have been made...
uint32_t GetGroupId(uint32_t index)
Return the groupId from the global index.
void SetBestProbabilityRate(MinstrelHtWifiRemoteStation *station, uint32_t index)
Set index rate as maxProbRate if it is better than current value.
uint32_t m_sampleTries
Number of sample tries after waiting sampleWait.
void SetNess(uint8_t ness)
Sets the Ness number refer to IEEE 802.11n Table 20-6 for explanation.
std::vector< struct HtRateInfo > HtMinstrelRate
Data structure for a Minstrel Rate table.
uint32_t GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
virtual bool IsLowLatency(void) const
Time GetFirstMpduTxTime(uint32_t groupId, WifiMode mode) const
Obtain the TXtime saved in the group information.
uint32_t GetShortRetryCount(const WifiRemoteStation *station) const
Return the short retry limit of the given station.
Time CalculateMpduTxDuration(Ptr< WifiPhy > phy, uint8_t streams, uint8_t sgi, uint32_t chWidth, WifiMode mode)
Estimates the TxTime of a frame with a given mode and group (stream, guard interval and channel width...
uint32_t CountRetries(MinstrelHtWifiRemoteStation *station)
TracedCallback< uint64_t, Mac48Address > m_rateChange
The trace source fired when the transmission rate change.
WifiMode GetMode(void) const
void UpdateRate(MinstrelHtWifiRemoteStation *station)
uint32_t GetNextSample(MinstrelHtWifiRemoteStation *station)
Getting the next sample from Sample Table.
double m_avgAmpduLen
Average number of MPDUs in an A-MPDU.
uint32_t m_shortRetry
short retries such as control packts
virtual void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr)
This method is a pure virtual method that must be implemented by the sub-class.
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
virtual void DoReportAmpduTxStatus(WifiRemoteStation *station, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus, double rxSnr, double dataSnr)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
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
a unique identifier for an interface.
Definition: type-id.h:58
bool IsValidMcs(Ptr< WifiPhy > phy, uint8_t streams, uint32_t chWidth, WifiMode mode)
Check the validity of a combination of number of streams, chWidth and mode.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:827
std::vector< std::vector< uint32_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint32_t.
void CheckInit(MinstrelHtWifiRemoteStation *station)
Check for initializations.
uint32_t m_sampleGroup
The group that the sample rate belongs to.
hold per-remote-station state.
bool GetHtSupported(const WifiRemoteStation *station) const
Return whether the given station is HT capable.
Ptr< WifiMac > GetMac(void) const
Return the WifiMac.
Time m_nextStatsUpdate
10 times every second