Bug Summary

File:/tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/wifi/model/minstrel-ht-wifi-manager.cc
Location:line 1108, column 30
Description:Division by zero

Annotated Source Code

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 "minstrel-ht-wifi-manager.h"
38#include "ns3/simulator.h"
39#include "ns3/log.h"
40#include "ns3/double.h"
41#include "ns3/boolean.h"
42#include "wifi-mac.h"
43#include "wifi-phy.h"
44#include <iomanip>
45
46#define Min(a,b)((a < b) ? a : b) ((a < b) ? a : b)
47#define Max(a,b)((a > b) ? a : b) ((a > b) ? a : b)
48
49NS_LOG_COMPONENT_DEFINE ("MinstrelHtWifiManager")static ns3::LogComponent g_log = ns3::LogComponent ("MinstrelHtWifiManager"
, "../src/wifi/model/minstrel-ht-wifi-manager.cc")
;
50
51namespace ns3 {
52
53///MinstrelHtWifiRemoteStation structure
54struct MinstrelHtWifiRemoteStation : MinstrelWifiRemoteStation
55{
56 /// Dispose station function
57 void DisposeStation ();
58
59 uint32_t m_sampleGroup; //!< The group that the sample rate belongs to.
60
61 uint32_t m_sampleWait; //!< How many transmission attempts to wait until a new sample.
62 uint32_t m_sampleTries; //!< Number of sample tries after waiting sampleWait.
63 uint32_t m_sampleCount; //!< Max number of samples per update interval.
64 uint32_t m_numSamplesSlow; //!< Number of times a slow rate was sampled.
65
66 double m_avgAmpduLen; //!< Average number of MPDUs in an A-MPDU.
67 double m_ampduLen; //!< Number of MPDUs in an A-MPDU.
68 uint32_t m_ampduPacketCount; //!< Number of A-MPDUs transmitted.
69
70 McsGroupData m_groupsTable; //!< Table of groups with stats.
71 bool m_isHt; //!< If the station is HT capable.
72
73 std::ofstream m_statsFile; //!< File where statistics table is written.
74};
75
76void
77MinstrelHtWifiRemoteStation::DisposeStation ()
78{
79 if (m_isHt)
80 {
81 std::vector<std::vector<uint32_t> > ().swap (m_sampleTable);
82 for (uint8_t j = 0; j < m_groupsTable.size (); j++)
83 {
84 std::vector<HtRateInfo> ().swap (m_groupsTable[j].m_ratesTable);
85 }
86 std::vector<GroupInfo> ().swap (m_groupsTable);
87 m_statsFile.close ();
88 }
89}
90
91NS_OBJECT_ENSURE_REGISTERED (MinstrelHtWifiManager)static struct ObjectMinstrelHtWifiManagerRegistrationClass { ObjectMinstrelHtWifiManagerRegistrationClass
() { ns3::TypeId tid = MinstrelHtWifiManager::GetTypeId (); tid
.SetSize (sizeof (MinstrelHtWifiManager)); tid.GetParent (); }
} ObjectMinstrelHtWifiManagerRegistrationVariable
;
92
93TypeId
94MinstrelHtWifiManager::GetTypeId (void)
95{
96 static TypeId tid = TypeId ("ns3::MinstrelHtWifiManager")
97 .SetParent<WifiRemoteStationManager> ()
98 .AddConstructor<MinstrelHtWifiManager> ()
99 .SetGroupName ("Wifi")
100 .AddAttribute ("UpdateStatistics",
101 "The interval between updating statistics table ",
102 TimeValue (MilliSeconds (100)),
103 MakeTimeAccessor (&MinstrelHtWifiManager::m_updateStats),
104 MakeTimeChecker ())
105 .AddAttribute ("LookAroundRate",
106 "The percentage to try other rates (for legacy Minstrel)",
107 DoubleValue (10),
108 MakeDoubleAccessor (&MinstrelHtWifiManager::m_lookAroundRate),
109 MakeDoubleChecker<double> (0, 100))
110 .AddAttribute ("EWMA",
111 "EWMA level",
112 DoubleValue (75),
113 MakeDoubleAccessor (&MinstrelHtWifiManager::m_ewmaLevel),
114 MakeDoubleChecker<double> (0, 100))
115 .AddAttribute ("SampleColumn",
116 "The number of columns used for sampling",
117 UintegerValue (10),
118 MakeUintegerAccessor (&MinstrelHtWifiManager::m_nSampleCol),
119 MakeUintegerChecker <uint32_t> ())
120 .AddAttribute ("PacketLength",
121 "The packet length used for calculating mode TxTime",
122 UintegerValue (1200),
123 MakeUintegerAccessor (&MinstrelHtWifiManager::m_frameLength),
124 MakeUintegerChecker <uint32_t> ())
125 .AddAttribute ("UseVhtOnly",
126 "Use only VHT MCSs (and not HT) when VHT is available",
127 BooleanValue (true),
128 MakeBooleanAccessor (&MinstrelHtWifiManager::m_useVhtOnly),
129 MakeBooleanChecker ())
130 .AddAttribute ("PrintStats",
131 "Control the printing of the statistics table",
132 BooleanValue (false),
133 MakeBooleanAccessor (&MinstrelHtWifiManager::m_printStats),
134 MakeBooleanChecker ())
135 .AddTraceSource ("RateChange",
136 "The transmission rate has changed",
137 MakeTraceSourceAccessor (&MinstrelHtWifiManager::m_rateChange),
138 "ns3::MinstrelHtWifiManager::RateChangeTracedCallback")
139 ;
140 return tid;
141}
142
143MinstrelHtWifiManager::MinstrelHtWifiManager ()
144 : m_numGroups (0),
145 m_numRates (0)
146{
147 NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
148 m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
149 /**
150 * Create the legacy Minstrel manager in case HT is not supported by the device
151 * or non-HT stations want to associate.
152 */
153 m_legacyManager = CreateObject<MinstrelWifiManager> ();
154}
155
156MinstrelHtWifiManager::~MinstrelHtWifiManager ()
157{
158 NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
159 if (HasHtSupported ())
160 {
161 for (uint32_t i = 0; i < m_numGroups; i++)
162 {
163 m_minstrelGroups[i].ratesFirstMpduTxTimeTable.clear ();
164 m_minstrelGroups[i].ratesTxTimeTable.clear ();
165 }
166 }
167}
168
169int64_t
170MinstrelHtWifiManager::AssignStreams (int64_t stream)
171{
172 NS_LOG_FUNCTION (this << stream)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << stream; std::clog << ")" << std::endl
; } } while (false)
;
173 int64_t numStreamsAssigned = 0;
174 m_uniformRandomVariable->SetStream (stream);
175 numStreamsAssigned++;
176 numStreamsAssigned += m_legacyManager->AssignStreams (stream);
177 return numStreamsAssigned;
178}
179
180void
181MinstrelHtWifiManager::SetupPhy (Ptr<WifiPhy> phy)
182{
183 NS_LOG_FUNCTION (this << phy)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << phy; std::clog << ")" << std::endl
; } } while (false)
;
184 // Setup phy for legacy manager.
185 m_legacyManager->SetupPhy (phy);
186 WifiRemoteStationManager::SetupPhy (phy);
187}
188
189void
190MinstrelHtWifiManager::DoInitialize ()
191{
192 NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
193
194 /**
195 * Here we initialize m_minstrelGroups with all the possible groups.
196 * If a group is not supported by the device, then it is marked as not supported.
197 * Then, after all initializations are finished, we check actual support for each receiving station.
198 */
199
200 // Check if the device supports HT or VHT
201 if (HasHtSupported () || HasVhtSupported ())
202 {
203 m_numGroups = MAX_SUPPORTED_STREAMS * MAX_HT_STREAM_GROUPS;
204 m_numRates = MAX_HT_GROUP_RATES;
205
206 if (HasVhtSupported ())
207 {
208 m_numGroups += MAX_SUPPORTED_STREAMS * MAX_VHT_STREAM_GROUPS;
209 m_numRates = MAX_VHT_GROUP_RATES;
210 }
211
212 /**
213 * Initialize the groups array.
214 * The HT groups come first, then the VHT ones.
215 * Minstrel maintains different types of indexes:
216 * - A global continuous index, which identifies all rates within all groups, in [0, m_numGroups * m_numRates]
217 * - A groupId, which indexes a group in the array, in [0, m_numGroups]
218 * - A rateId, which identifies a rate within a group, in [0, m_numRates]
219 * - A deviceIndex, which indexes a MCS in the phy MCS array.
220 * - A mcsIndex, which indexes a MCS in the wifi-remote-station-manager supported MCSs array.
221 */
222 NS_LOG_DEBUG ("Initialize MCS Groups:")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Initialize MCS Groups:"
<< std::endl; } } while (false)
;
223 m_minstrelGroups = MinstrelMcsGroups (m_numGroups);
224
225 // Initialize all HT groups
226 for (uint8_t chWidth = 20; chWidth <= MAX_HT_WIDTH; chWidth *= 2)
227 {
228 for (uint8_t sgi = 0; sgi <= 1; sgi++)
229 {
230 for (uint8_t streams = 1; streams <= MAX_SUPPORTED_STREAMS; streams++)
231 {
232 uint32_t groupId = GetHtGroupId (streams, sgi, chWidth);
233
234 m_minstrelGroups[groupId].streams = streams;
235 m_minstrelGroups[groupId].sgi = sgi;
236 m_minstrelGroups[groupId].chWidth = chWidth;
237 m_minstrelGroups[groupId].isVht = false;
238 m_minstrelGroups[groupId].isSupported = false;
239
240 // Check capabilities of the device
241 if (!(!GetPhy ()->GetShortGuardInterval () && m_minstrelGroups[groupId].sgi) ///Is SGI supported by the transmitter?
242 && (GetPhy ()->GetChannelWidth () >= m_minstrelGroups[groupId].chWidth) ///Is channel width supported by the transmitter?
243 && (GetPhy ()->GetMaxSupportedTxSpatialStreams () >= m_minstrelGroups[groupId].streams)) ///Are streams supported by the transmitter?
244 {
245 m_minstrelGroups[groupId].isSupported = true;
246
247 // Calculate tx time for all rates of the group
248 WifiModeList htMcsList = GetHtDeviceMcsList ();
249 for (uint8_t i = 0; i < MAX_HT_GROUP_RATES; i++)
250 {
251 uint32_t deviceIndex = i + (m_minstrelGroups[groupId].streams - 1) * 8;
252 WifiMode mode = htMcsList[deviceIndex];
253 AddFirstMpduTxTime (groupId, mode, CalculateFirstMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
254 AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
255 }
256 NS_LOG_DEBUG ("Initialized group " << groupId << ": (" << (uint16_t)streams << "," << (uint16_t)sgi << "," << (uint16_t)chWidth << ")")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Initialized group "
<< groupId << ": (" << (uint16_t)streams <<
"," << (uint16_t)sgi << "," << (uint16_t)chWidth
<< ")" << std::endl; } } while (false)
;
257 }
258 }
259 }
260 }
261
262 if (HasVhtSupported ())
263 {
264 // Initialize all VHT groups
265 for (uint16_t chWidth = 20; chWidth <= MAX_VHT_WIDTH; chWidth *= 2)
266 {
267 for (uint8_t sgi = 0; sgi <= 1; sgi++)
268 {
269 for (uint8_t streams = 1; streams <= MAX_SUPPORTED_STREAMS; streams++)
270 {
271 uint32_t groupId = GetVhtGroupId (streams, sgi, chWidth);
272
273 m_minstrelGroups[groupId].streams = streams;
274 m_minstrelGroups[groupId].sgi = sgi;
275 m_minstrelGroups[groupId].chWidth = chWidth;
276 m_minstrelGroups[groupId].isVht = true;
277 m_minstrelGroups[groupId].isSupported = false;
278
279 // Check capabilities of the device
280 if (!(!GetPhy ()->GetShortGuardInterval () && m_minstrelGroups[groupId].sgi) ///Is SGI supported by the transmitter?
281 && (GetPhy ()->GetChannelWidth () >= m_minstrelGroups[groupId].chWidth) ///Is channel width supported by the transmitter?
282 && (GetPhy ()->GetMaxSupportedTxSpatialStreams () >= m_minstrelGroups[groupId].streams)) ///Are streams supported by the transmitter?
283 {
284 m_minstrelGroups[groupId].isSupported = true;
285
286 // Calculate tx time for all rates of the group
287 WifiModeList vhtMcsList = GetVhtDeviceMcsList ();
288 for (uint8_t i = 0; i < MAX_VHT_GROUP_RATES; i++)
289 {
290 WifiMode mode = vhtMcsList[i];
291 // Check for invalid VHT MCSs and do not add time to array.
292 if (IsValidMcs (GetPhy (), streams, chWidth, mode))
293 {
294 AddFirstMpduTxTime (groupId, mode, CalculateFirstMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
295 AddMpduTxTime (groupId, mode, CalculateMpduTxDuration (GetPhy (), streams, sgi, chWidth, mode));
296 }
297 }
298 NS_LOG_DEBUG ("Initialized group " << groupId << ": (" << (uint16_t)streams << "," << (uint16_t)sgi << "," << (uint16_t)chWidth << ")")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Initialized group "
<< groupId << ": (" << (uint16_t)streams <<
"," << (uint16_t)sgi << "," << (uint16_t)chWidth
<< ")" << std::endl; } } while (false)
;
299 }
300 }
301 }
302 }
303 }
304 }
305}
306
307void
308MinstrelHtWifiManager::SetupMac (Ptr<WifiMac> mac)
309{
310 NS_LOG_FUNCTION (this << mac)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << mac; std::clog << ")" << std::endl
; } } while (false)
;
311 m_legacyManager->SetupMac (mac);
312 WifiRemoteStationManager::SetupMac (mac);
313}
314
315bool
316MinstrelHtWifiManager::IsValidMcs (Ptr<WifiPhy> phy, uint8_t streams, uint8_t chWidth, WifiMode mode)
317{
318 NS_LOG_FUNCTION (this << phy << (uint16_t)streams << (uint16_t)chWidth << mode)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << phy << (uint16_t)streams << (uint16_t
)chWidth << mode; std::clog << ")" << std::
endl; } } while (false)
;
319
320 WifiTxVector txvector;
321 txvector.SetNss (streams);
322 txvector.SetChannelWidth (chWidth);
323 txvector.SetMode (mode);
324 return phy->IsValidTxVector (txvector);
325}
326
327Time
328MinstrelHtWifiManager::CalculateFirstMpduTxDuration (Ptr<WifiPhy> phy, uint8_t streams, uint8_t sgi, uint8_t chWidth, WifiMode mode)
329{
330 NS_LOG_FUNCTION (this << phy << (uint16_t)streams << (uint16_t)sgi << (uint16_t)chWidth << mode)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << phy << (uint16_t)streams << (uint16_t
)sgi << (uint16_t)chWidth << mode; std::clog <<
")" << std::endl; } } while (false)
;
331
332 WifiTxVector txvector;
333 txvector.SetNss (streams);
334 txvector.SetGuardInterval (sgi ? 400 : 800);
335 txvector.SetChannelWidth (chWidth);
336 txvector.SetNess (0);
337 txvector.SetStbc (phy->GetStbc ());
338 txvector.SetMode (mode);
339 txvector.SetPreambleType (WIFI_PREAMBLE_HT_MF);
340 return phy->CalculateTxDuration (m_frameLength, txvector, phy->GetFrequency (), MPDU_IN_AGGREGATE, 0);
341}
342
343Time
344MinstrelHtWifiManager::CalculateMpduTxDuration (Ptr<WifiPhy> phy, uint8_t streams, uint8_t sgi, uint8_t chWidth, WifiMode mode)
345{
346 NS_LOG_FUNCTION (this << phy << (uint16_t)streams << (uint16_t)sgi << (uint16_t)chWidth << mode)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << phy << (uint16_t)streams << (uint16_t
)sgi << (uint16_t)chWidth << mode; std::clog <<
")" << std::endl; } } while (false)
;
347
348 WifiTxVector txvector;
349 txvector.SetNss (streams);
350 txvector.SetGuardInterval (sgi ? 400 : 800);
351 txvector.SetChannelWidth (chWidth);
352 txvector.SetNess (0);
353 txvector.SetStbc (phy->GetStbc ());
354 txvector.SetMode (mode);
355 txvector.SetPreambleType (WIFI_PREAMBLE_NONE);
356 return phy->CalculateTxDuration (m_frameLength, txvector, phy->GetFrequency (), MPDU_IN_AGGREGATE, 0);
357}
358
359Time
360MinstrelHtWifiManager::GetFirstMpduTxTime (uint32_t groupId, WifiMode mode) const
361{
362 NS_LOG_FUNCTION (this << groupId << mode)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << groupId << mode; std::clog << ")" <<
std::endl; } } while (false)
;
363
364 for (TxTime::const_iterator i = m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.begin (); i != m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.end (); i++)
365 {
366 if (mode == i->second)
367 {
368 return i->first;
369 }
370 }
371 NS_ASSERT (false)do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "file="
<< "../src/wifi/model/minstrel-ht-wifi-manager.cc" <<
", line=" << 371 << std::endl; ::ns3::FatalImpl::
FlushStreams (); if (true) std::terminate (); } while (false)
; } } while (false)
;
372 return Seconds (0);
373}
374
375void
376MinstrelHtWifiManager::AddFirstMpduTxTime (uint32_t groupId, WifiMode mode, Time t)
377{
378 NS_LOG_FUNCTION (this << groupId << mode << t)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << groupId << mode << t; std::clog <<
")" << std::endl; } } while (false)
;
379
380 m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.push_back (std::make_pair (t, mode));
381}
382
383Time
384MinstrelHtWifiManager::GetMpduTxTime (uint32_t groupId, WifiMode mode) const
385{
386 NS_LOG_FUNCTION (this << groupId << mode)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << groupId << mode; std::clog << ")" <<
std::endl; } } while (false)
;
387
388 for (TxTime::const_iterator i = m_minstrelGroups[groupId].ratesTxTimeTable.begin (); i != m_minstrelGroups[groupId].ratesTxTimeTable.end (); i++)
389 {
390 if (mode == i->second)
391 {
392 return i->first;
393 }
394 }
395 NS_ASSERT (false)do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "file="
<< "../src/wifi/model/minstrel-ht-wifi-manager.cc" <<
", line=" << 395 << std::endl; ::ns3::FatalImpl::
FlushStreams (); if (true) std::terminate (); } while (false)
; } } while (false)
;
396 return Seconds (0);
397}
398
399void
400MinstrelHtWifiManager::AddMpduTxTime (uint32_t groupId, WifiMode mode, Time t)
401{
402 NS_LOG_FUNCTION (this << groupId << mode << t)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << groupId << mode << t; std::clog <<
")" << std::endl; } } while (false)
;
403
404 m_minstrelGroups[groupId].ratesTxTimeTable.push_back (std::make_pair (t, mode));
405}
406
407WifiRemoteStation *
408MinstrelHtWifiManager::DoCreateStation (void) const
409{
410 NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
411
412 MinstrelHtWifiRemoteStation *station = new MinstrelHtWifiRemoteStation ();
413
414 // Initialize variables common to both stations.
415 station->m_nextStatsUpdate = Simulator::Now () + m_updateStats;
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 (HasHtSupported () || HasVhtSupported ())
445 {
446 /**
447 * Assume the station is HT.
448 * When correct information available it will be checked.
449 */
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
461void
462MinstrelHtWifiManager::CheckInit (MinstrelHtWifiRemoteStation *station)
463{
464 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
465
466 // Note: we appear to be doing late initialization of the table
467 // to make sure that the set of supported rates has been initialized
468 // before we perform our own initialization.
469 if (!station->m_initialized)
470 {
471 /**
472 * Check if the station supports HT.
473 * Assume that if the device do not supports HT then
474 * the station will not support HT either.
475 * We save from using another check and variable.
476 */
477 if (!GetHtSupported (station) && !GetVhtSupported (station))
478 {
479 NS_LOG_DEBUG ("Non-HT station " << station)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Non-HT station "
<< station << std::endl; } } while (false)
;
480 station->m_isHt = false;
481 // We will use non-HT minstrel for this station. Initialize the manager.
482 m_legacyManager->SetAttribute ("UpdateStatistics", TimeValue (m_updateStats));
483 m_legacyManager->SetAttribute ("LookAroundRate", DoubleValue (m_lookAroundRate));
484 m_legacyManager->SetAttribute ("EWMA", DoubleValue (m_ewmaLevel));
485 m_legacyManager->SetAttribute ("SampleColumn", UintegerValue (m_nSampleCol));
486 m_legacyManager->SetAttribute ("PacketLength", UintegerValue (m_frameLength));
487 m_legacyManager->SetAttribute ("PrintStats", BooleanValue (m_printStats));
488 m_legacyManager->CheckInit (station);
489 }
490 else
491 {
492 NS_LOG_DEBUG ("HT station " << station)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "HT station "
<< station << std::endl; } } while (false)
;
493 station->m_isHt = true;
494 station->m_nModes = GetNMcsSupported (station);
495 station->m_sampleTable = SampleRate (m_numRates, std::vector<uint32_t> (m_nSampleCol));
496 InitSampleTable (station);
497 RateInit (station);
498 std::ostringstream tmp;
499 tmp << "minstrel-ht-stats-" << station->m_state->m_address << ".txt";
500 station->m_statsFile.open (tmp.str ().c_str (), std::ios::out);
501 station->m_initialized = true;
502 }
503 }
504}
505
506void
507MinstrelHtWifiManager::DoReportRxOk (WifiRemoteStation *st,
508 double rxSnr, WifiMode txMode)
509{
510 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
511
512 NS_LOG_DEBUG ("DoReportRxOk m_txrate=" << ((MinstrelHtWifiRemoteStation *)st)->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportRxOk m_txrate="
<< ((MinstrelHtWifiRemoteStation *)st)->m_txrate <<
std::endl; } } while (false)
;
513}
514
515void
516MinstrelHtWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
517{
518 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
519
520 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *)st;
521
522 CheckInit (station);
523 if (!station->m_initialized)
524 {
525 return;
526 }
527
528 NS_LOG_DEBUG ("DoReportRtsFailed m_txrate=" << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportRtsFailed m_txrate="
<< station->m_txrate << std::endl; } } while (
false)
;
529 station->m_shortRetry++;
530}
531
532void
533MinstrelHtWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
534{
535 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
536
537 NS_LOG_DEBUG ("self=" << st << " rts ok")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "self=" <<
st << " rts ok" << std::endl; } } while (false)
;
538}
539
540void
541MinstrelHtWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
542{
543 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
544
545 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *)st;
546 NS_LOG_DEBUG ("Final RTS failed")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Final RTS failed"
<< std::endl; } } while (false)
;
547
548 CheckInit (station);
549 if (!station->m_initialized)
550 {
551 return;
552 }
553
554 UpdateRetry (station);
555}
556
557void
558MinstrelHtWifiManager::DoReportDataFailed (WifiRemoteStation *st)
559{
560 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
561
562 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *)st;
563
564 CheckInit (station);
565 if (!station->m_initialized)
566 {
567 return;
568 }
569
570 if (!station->m_isHt)
571 {
572 m_legacyManager->UpdateRate (station);
573 }
574 else
575 {
576 NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportDataFailed "
<< station << "\t rate " << station->m_txrate
<< "\tlongRetry \t" << station->m_longRetry <<
std::endl; } } while (false)
;
577
578 uint32_t rateId = GetRateId (station->m_txrate);
579 uint32_t groupId = GetGroupId (station->m_txrate);
580 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++; // Increment the attempts counter for the rate used.
581
582 UpdateRate (station);
583 }
584}
585
586void
587MinstrelHtWifiManager::DoReportDataOk (WifiRemoteStation *st,
588 double ackSnr, WifiMode ackMode, double dataSnr)
589{
590 NS_LOG_FUNCTION (this << st << ackSnr << ackMode << dataSnr)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st << ackSnr << ackMode << dataSnr
; std::clog << ")" << std::endl; } } while (false
)
;
591 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
592
593 CheckInit (station);
594 if (!station->m_initialized)
595 {
596 return;
597 }
598
599 NS_LOG_DEBUG ("Data OK - Txrate = " << station->m_txrate )do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Data OK - Txrate = "
<< station->m_txrate << std::endl; } } while (
false)
;
600
601 if (!station->m_isHt)
602 {
603 station->m_minstrelTable[station->m_txrate].numRateSuccess++;
604 station->m_minstrelTable[station->m_txrate].numRateAttempt++;
605
606 m_legacyManager->UpdatePacketCounters (station);
607
608 UpdateRetry (station);
609 m_legacyManager->UpdateStats (station);
610
611 if (station->m_nModes >= 1)
612 {
613 station->m_txrate = m_legacyManager->FindRate (station);
614 }
615 }
616 else
617 {
618 uint32_t rateId = GetRateId (station->m_txrate);
619 uint32_t groupId = GetGroupId (station->m_txrate);
620 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess++;
621 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++;
622
623 UpdatePacketCounters (station, 1, 0);
624
625 station->m_isSampling = false;
626 station->m_sampleDeferred = false;
627
628 UpdateRetry (station);
629 if (Simulator::Now () >= station->m_nextStatsUpdate)
630 {
631 UpdateStats (station);
632 }
633
634 if (station->m_nModes >= 1)
635 {
636 station->m_txrate = FindRate (station);
637 }
638 }
639
640 NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate )do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Next rate to use TxRate = "
<< station->m_txrate << std::endl; } } while (
false)
;
641}
642
643void
644MinstrelHtWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
645{
646 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
647 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
648
649 CheckInit (station);
650 if (!station->m_initialized)
651 {
652 return;
653 }
654
655 NS_LOG_DEBUG ("DoReportFinalDataFailed - TxRate=" << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportFinalDataFailed - TxRate="
<< station->m_txrate << std::endl; } } while (
false)
;
656
657 if (!station->m_isHt)
658 {
659 m_legacyManager->UpdatePacketCounters (station);
660
661 UpdateRetry (station);
662
663 m_legacyManager->UpdateStats (station);
664 if (station->m_nModes >= 1)
665 {
666 station->m_txrate = m_legacyManager->FindRate (station);
667 }
668 }
669 else
670 {
671 UpdatePacketCounters (station, 0, 1);
672
673 station->m_isSampling = false;
674 station->m_sampleDeferred = false;
675
676 UpdateRetry (station);
677 if (Simulator::Now () >= station->m_nextStatsUpdate)
678 {
679 UpdateStats (station);
680 }
681
682 if (station->m_nModes >= 1)
683 {
684 station->m_txrate = FindRate (station);
685 }
686 }
687 NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate )do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Next rate to use TxRate = "
<< station->m_txrate << std::endl; } } while (
false)
;
688}
689
690void
691MinstrelHtWifiManager::DoReportAmpduTxStatus (WifiRemoteStation *st, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr)
692{
693 NS_LOG_FUNCTION (this << st << (uint16_t)nSuccessfulMpdus << (uint16_t)nFailedMpdus << rxSnr << dataSnr)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st << (uint16_t)nSuccessfulMpdus <<
(uint16_t)nFailedMpdus << rxSnr << dataSnr; std::
clog << ")" << std::endl; } } while (false)
;
694 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
695
696 CheckInit (station);
697 if (!station->m_initialized)
698 {
699 return;
700 }
701
702 if (!station->m_isHt)
703 {
704 NS_ASSERT_MSG (false,"A-MPDU Tx Status called but no HT or VHT supported.")do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "msg=\""
<< "A-MPDU Tx Status called but no HT or VHT supported."
<< "\", "; do { std::cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 704 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false); } } while (false)
;
705 }
706
707 NS_LOG_DEBUG ("DoReportAmpduTxStatus. TxRate=" << station->m_txrate << " SuccMpdus= " <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportAmpduTxStatus. TxRate="
<< station->m_txrate << " SuccMpdus= " <<
(uint16_t)nSuccessfulMpdus << " FailedMpdus= " <<
(uint16_t)nFailedMpdus << std::endl; } } while (false)
708 (uint16_t)nSuccessfulMpdus << " FailedMpdus= " << (uint16_t)nFailedMpdus)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoReportAmpduTxStatus. TxRate="
<< station->m_txrate << " SuccMpdus= " <<
(uint16_t)nSuccessfulMpdus << " FailedMpdus= " <<
(uint16_t)nFailedMpdus << std::endl; } } while (false)
;
709
710 station->m_ampduPacketCount++;
711 station->m_ampduLen += nSuccessfulMpdus + nFailedMpdus;
712
713 UpdatePacketCounters (station, nSuccessfulMpdus, nFailedMpdus);
714
715 uint32_t rateId = GetRateId (station->m_txrate);
716 uint32_t groupId = GetGroupId (station->m_txrate);
717 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess += nSuccessfulMpdus;
718 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt += nSuccessfulMpdus + nFailedMpdus;
719
720 if (nSuccessfulMpdus == 0 && station->m_longRetry < CountRetries (station))
721 {
722 // We do not receive a BlockAck. The entire AMPDU fail.
723 UpdateRate (station);
724 }
725 else
726 {
727 station->m_isSampling = false;
728 station->m_sampleDeferred = false;
729
730 UpdateRetry (station);
731 if (Simulator::Now () >= station->m_nextStatsUpdate)
732 {
733 UpdateStats (station);
734 }
735
736 if (station->m_nModes >= 1)
737 {
738 station->m_txrate = FindRate (station);
739 }
740 NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Next rate to use TxRate = "
<< station->m_txrate << std::endl; } } while (
false)
;
741 }
742}
743
744void
745MinstrelHtWifiManager::UpdateRate (MinstrelHtWifiRemoteStation *station)
746{
747 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
748
749 /**
750 * Retry Chain table is implemented here.
751 *
752 * FIXME
753 * Currently, NS3 does not retransmit an entire A-MPDU when BACK is missing
754 * but retransmits each MPDU until MPDUs lifetime expires (or a BACK is received).
755 * Then, there is no way to control A-MPDU retries (no call to NeedDataRetransmission).
756 * So, it is possible that the A-MPDU keeps retrying after longRetry reaches its limit.
757 *
758 *
759 * Try | LOOKAROUND RATE | NORMAL RATE
760 * -------------------------------------------------------
761 * 1 | Random rate | Best throughput
762 * 2 | Next best throughput | Next best throughput
763 * 3 | Best probability | Best probability
764 *
765 * Note: For clarity, multiple blocks of if's and else's are used
766 * Following implementation in Linux, in MinstrelHT Lowest baserate is not used.
767 * Explanation can be found here: http://marc.info/?l=linux-wireless&m=144602778611966&w=2
768 */
769
770 CheckInit (station);
771 if (!station->m_initialized)
772 {
773 return;
774 }
775 station->m_longRetry++;
776
777 /**
778 * Get the ids for all rates.
779 */
780 uint32_t maxTpRateId = GetRateId (station->m_maxTpRate);
781 uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
782 uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
783 uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
784 uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
785 uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
786
787 /// For normal rate, we're not currently sampling random rates.
788 if (!station->m_isSampling)
789 {
790 /// Use best throughput rate.
791 if (station->m_longRetry < station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount)
792 {
793 NS_LOG_DEBUG ("Not Sampling; use the same rate again")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Not Sampling; use the same rate again"
<< std::endl; } } while (false)
;
794 station->m_txrate = station->m_maxTpRate; //!< There are still a few retries.
795 }
796
797 /// Use second best throughput rate.
798 else if (station->m_longRetry < ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
799 station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount))
800 {
801 NS_LOG_DEBUG ("Not Sampling; use the Max TP2")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Not Sampling; use the Max TP2"
<< std::endl; } } while (false)
;
802 station->m_txrate = station->m_maxTpRate2;
803 }
804
805 /// Use best probability rate.
806 else if (station->m_longRetry <= ( station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
807 station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
808 station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount))
809 {
810 NS_LOG_DEBUG ("Not Sampling; use Max Prob")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Not Sampling; use Max Prob"
<< std::endl; } } while (false)
;
811 station->m_txrate = station->m_maxProbRate;
812 }
813 else
814 {
815 NS_ASSERT_MSG (false,"Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry)do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "msg=\""
<< "Max retries reached and m_longRetry not cleared properly. longRetry= "
<< station->m_longRetry << "\", "; do { std::
cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 815 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false); } } while (false)
;
816 }
817 }
818
819 /// We're currently sampling random rates.
820 else
821 {
822 /// Sample rate is used only once
823 /// Use the best rate.
824 if (station->m_longRetry < 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount)
825 {
826 NS_LOG_DEBUG ("Sampling use the MaxTP rate")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Sampling use the MaxTP rate"
<< std::endl; } } while (false)
;
827 station->m_txrate = station->m_maxTpRate2;
828 }
829
830 /// Use the best probability rate.
831 else if (station->m_longRetry <= 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
832 station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount)
833 {
834 NS_LOG_DEBUG ("Sampling use the MaxProb rate")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Sampling use the MaxProb rate"
<< std::endl; } } while (false)
;
835 station->m_txrate = station->m_maxProbRate;
836 }
837 else
838 {
839 NS_ASSERT_MSG (false,"Max retries reached and m_longRetry not cleared properly. longRetry= " << station->m_longRetry)do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "msg=\""
<< "Max retries reached and m_longRetry not cleared properly. longRetry= "
<< station->m_longRetry << "\", "; do { std::
cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 839 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false); } } while (false)
;
840 }
841 }
842 NS_LOG_DEBUG ("Next rate to use TxRate = " << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Next rate to use TxRate = "
<< station->m_txrate << std::endl; } } while (
false)
;
843}
844
845void
846MinstrelHtWifiManager::UpdateRetry (MinstrelHtWifiRemoteStation *station)
847{
848 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
849 station->m_shortRetry = 0;
850 station->m_longRetry = 0;
851
852}
853
854void
855MinstrelHtWifiManager::UpdatePacketCounters (MinstrelHtWifiRemoteStation *station, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus)
856{
857 NS_LOG_FUNCTION (this << station << (uint16_t)nSuccessfulMpdus << (uint16_t)nFailedMpdus)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station << (uint16_t)nSuccessfulMpdus <<
(uint16_t)nFailedMpdus; std::clog << ")" << std::
endl; } } while (false)
;
858
859 station->m_totalPacketsCount += nSuccessfulMpdus + nFailedMpdus;
860 if (station->m_isSampling)
861 {
862 station->m_samplePacketsCount += nSuccessfulMpdus + nFailedMpdus;
863 }
864 if (station->m_totalPacketsCount == ~0)
865 {
866 station->m_samplePacketsCount = 0;
867 station->m_totalPacketsCount = 0;
868 }
869
870 if (!station->m_sampleWait && !station->m_sampleTries && station->m_sampleCount > 0)
871 {
872 station->m_sampleWait = 16 + 2 * station->m_avgAmpduLen;
873 station->m_sampleTries = 1;
874 station->m_sampleCount--;
875 }
876
877}
878void
879MinstrelHtWifiManager::DoDisposeStation (WifiRemoteStation *st)
880{
881 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
882 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
883 station->DisposeStation ();
884}
885
886WifiTxVector
887MinstrelHtWifiManager::DoGetDataTxVector (WifiRemoteStation *st)
888{
889 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
890 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
891
892 if (!station->m_initialized)
893 {
894 CheckInit (station);
895 }
896
897 if (!station->m_isHt)
898 {
899 WifiTxVector vector = m_legacyManager->GetDataTxVector (station);
900
901 uint64_t dataRate = vector.GetMode ().GetDataRate (vector);
902 if (!station->m_isSampling)
903 {
904 m_rateChange (dataRate, station->m_state->m_address);
905 }
906
907 return vector;
908 }
909 else
910 {
911 NS_LOG_DEBUG ("DoGetDataMode m_txrate= " << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoGetDataMode m_txrate= "
<< station->m_txrate << std::endl; } } while (
false)
;
912
913 uint32_t rateId = GetRateId (station->m_txrate);
914 uint32_t groupId = GetGroupId (station->m_txrate);
915 uint32_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
916
917 NS_LOG_DEBUG ("DoGetDataMode rateId= " << rateId << " groupId= " << groupId << " mode= " << GetMcsSupported (station, mcsIndex))do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoGetDataMode rateId= "
<< rateId << " groupId= " << groupId <<
" mode= " << GetMcsSupported (station, mcsIndex) <<
std::endl; } } while (false)
;
918
919 McsGroup group = m_minstrelGroups[groupId];
920
921 // Check consistency of rate selected.
922 if ((group.sgi && !GetShortGuardInterval (station)) || group.chWidth > GetChannelWidth (station) || group.streams > GetNumberOfSupportedStreams (station))
923 {
924 NS_ASSERT_MSG (false,"Inconsistent group selected. Group: (" << (uint16_t)group.streams << "," << (uint16_t)group.sgi << "," << (uint16_t)group.chWidth << ")" <<do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "msg=\""
<< "Inconsistent group selected. Group: (" << (uint16_t
)group.streams << "," << (uint16_t)group.sgi <<
"," << (uint16_t)group.chWidth << ")" << " Station capabilities: ("
<< GetNumberOfSupportedStreams (station) << "," <<
GetShortGuardInterval (station) << "," << GetChannelWidth
(station) << ")" << "\", "; do { std::cerr <<
"file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 925 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false); } } while (false)
925 " Station capabilities: (" << GetNumberOfSupportedStreams (station) << "," << GetShortGuardInterval (station) << "," << GetChannelWidth (station) << ")")do { if (!(false)) { std::cerr << "assert failed. cond=\""
<< "false" << "\", "; do { std::cerr << "msg=\""
<< "Inconsistent group selected. Group: (" << (uint16_t
)group.streams << "," << (uint16_t)group.sgi <<
"," << (uint16_t)group.chWidth << ")" << " Station capabilities: ("
<< GetNumberOfSupportedStreams (station) << "," <<
GetShortGuardInterval (station) << "," << GetChannelWidth
(station) << ")" << "\", "; do { std::cerr <<
"file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 925 << std::endl; ::ns3::FatalImpl
::FlushStreams (); if (true) std::terminate (); } while (false
); } while (false); } } while (false)
;
926 }
927
928 uint64_t dataRate = GetMcsSupported (station, mcsIndex).GetDataRate (group.chWidth, group.sgi ? 400 : 800, group.streams);
929 if (!station->m_isSampling)
930 {
931 m_rateChange (dataRate, station->m_state->m_address);
932 }
933 WifiMode mode = GetMcsSupported (station, mcsIndex);
934 return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetLongRetryCount (station),
935 GetPreambleForTransmission (mode, GetAddress (station)), group.sgi ? 400 : 800, GetNumberOfAntennas (), group.streams, GetNess (station), group.chWidth, GetAggregation (station) && !station->m_isSampling, GetStbc (station));
936 }
937}
938
939WifiTxVector
940MinstrelHtWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
941{
942 NS_LOG_FUNCTION (this << st)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st; std::clog << ")" << std::endl;
} } while (false)
;
943 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *) st;
944
945 if (!station->m_initialized)
946 {
947 CheckInit (station);
948 }
949
950 if (!station->m_isHt)
951 {
952 return m_legacyManager->GetRtsTxVector (station);
953 }
954 else
955 {
956 NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "DoGetRtsMode m_txrate="
<< station->m_txrate << std::endl; } } while (
false)
;
957
958 /* RTS is sent in a non-HT frame. RTS with HT is not supported yet in NS3.
959 * When supported, decision of using HT has to follow rules in Section 9.7.6 from 802.11-2012.
960 * From Sec. 9.7.6.5: "A frame other than a BlockAckReq or BlockAck that is carried in a
961 * non-HT PPDU shall be transmitted by the STA using a rate no higher than the highest
962 * rate in the BSSBasicRateSet parameter that is less than or equal to the rate or
963 * non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
964 * directed to the same receiving STA. If no rate in the BSSBasicRateSet parameter meets
965 * these conditions, the control frame shall be transmitted at a rate no higher than the
966 * highest mandatory rate of the attached PHY that is less than or equal to the rate
967 * or non-HT reference rate (see 9.7.9) of the previously transmitted frame that was
968 * directed to the same receiving STA."
969 */
970
971 // As we are in Minstrel HT, assume the last rate was an HT rate.
972 uint32_t rateId = GetRateId (station->m_txrate);
973 uint32_t groupId = GetGroupId (station->m_txrate);
974 uint32_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
975
976 WifiMode lastRate = GetMcsSupported (station, mcsIndex);
977 uint64_t lastDataRate = lastRate.GetNonHtReferenceRate ();
978 uint32_t nBasicRates = GetNBasicModes ();
979
980 WifiMode rtsRate;
981 bool rateFound = false;
982
983 for (uint32_t i = 0; i < nBasicRates; i++)
984 {
985 uint64_t rate = GetBasicMode (i).GetDataRate (20);
986 if (rate <= lastDataRate)
987 {
988 rtsRate = GetBasicMode (i);
989 rateFound = true;
990 }
991 }
992
993 if (!rateFound)
994 {
995 Ptr<WifiPhy> phy = GetPhy ();
996 uint32_t nSupportRates = phy->GetNModes ();
997 for (uint32_t i = 0; i < nSupportRates; i++)
998 {
999 uint64_t rate = phy->GetMode (i).GetDataRate (20);
1000 if (rate <= lastDataRate)
1001 {
1002 rtsRate = phy->GetMode (i);
1003 rateFound = true;
1004 }
1005 }
1006 }
1007
1008 NS_ASSERT (rateFound)do { if (!(rateFound)) { std::cerr << "assert failed. cond=\""
<< "rateFound" << "\", "; do { std::cerr <<
"file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 1008 << std::endl; ::ns3::
FatalImpl::FlushStreams (); if (true) std::terminate (); } while
(false); } } while (false)
;
1009
1010 return WifiTxVector (rtsRate, GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetPreambleForTransmission (rtsRate, GetAddress (station)),
1011 800, 1, 1, 0, GetChannelWidth (station), GetAggregation (station), false);
1012 }
1013}
1014
1015bool
1016MinstrelHtWifiManager::DoNeedDataRetransmission (WifiRemoteStation *st, Ptr<const Packet> packet, bool normally)
1017{
1018 NS_LOG_FUNCTION (this << st << packet << normally)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << st << packet << normally; std::clog
<< ")" << std::endl; } } while (false)
;
1019
1020 MinstrelHtWifiRemoteStation *station = (MinstrelHtWifiRemoteStation *)st;
1021
1022 CheckInit (station);
1023 if (!station->m_initialized)
1024 {
1025 return normally;
1026 }
1027
1028 uint32_t maxRetries;
1029
1030 if (!station->m_isHt)
1031 {
1032 maxRetries = m_legacyManager->CountRetries (station);
1033 }
1034 else
1035 {
1036 maxRetries = CountRetries (station);
1037 }
1038
1039 if (station->m_longRetry >= maxRetries)
1040 {
1041 NS_LOG_DEBUG ("No re-transmission allowed. Retries: " << station->m_longRetry << " Max retries: " << maxRetries)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "No re-transmission allowed. Retries: "
<< station->m_longRetry << " Max retries: " <<
maxRetries << std::endl; } } while (false)
;
1042 return false;
1043 }
1044 else
1045 {
1046 NS_LOG_DEBUG ("Re-transmit. Retries: " << station->m_longRetry << " Max retries: " << maxRetries)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Re-transmit. Retries: "
<< station->m_longRetry << " Max retries: " <<
maxRetries << std::endl; } } while (false)
;
1047 return true;
1048 }
1049}
1050
1051uint32_t
1052MinstrelHtWifiManager::CountRetries (MinstrelHtWifiRemoteStation *station)
1053{
1054 uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
1055 uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1056 uint32_t maxTpRateId = GetRateId (station->m_maxTpRate);
1057 uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1058 uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1059 uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1060
1061 if (!station->m_isSampling)
1062 {
1063 return station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
1064 station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
1065 station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1066 }
1067 else
1068 {
1069 return 1 + station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
1070 station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1071 }
1072}
1073
1074bool
1075MinstrelHtWifiManager::IsLowLatency (void) const
1076{
1077 NS_LOG_FUNCTION (this)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this; std::clog << ")" << std::endl; } } while (
false)
;
1078 return true;
1079}
1080
1081uint32_t
1082MinstrelHtWifiManager::GetNextSample (MinstrelHtWifiRemoteStation *station)
1083{
1084 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1085
1086 uint32_t sampleGroup = station->m_sampleGroup;
1087
1088 uint32_t index = station->m_groupsTable[sampleGroup].m_index;
1089 uint32_t col = station->m_groupsTable[sampleGroup].m_col;
1090
1091 uint32_t sampleIndex = station->m_sampleTable[index][col];
1092
1093 uint32_t rateIndex = GetIndex (sampleGroup, sampleIndex);
1094 NS_LOG_DEBUG ("Next Sample is " << rateIndex)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Next Sample is "
<< rateIndex << std::endl; } } while (false)
;
1095
1096 SetNextSample (station); //Calculate the next sample rate.
1097
1098 return rateIndex;
1099}
1100
1101void
1102MinstrelHtWifiManager::SetNextSample (MinstrelHtWifiRemoteStation *station)
1103{
1104 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1105 do
1106 {
1107 station->m_sampleGroup++;
1108 station->m_sampleGroup %= m_numGroups;
3
Division by zero
1109 }
1110 while (!station->m_groupsTable[station->m_sampleGroup].m_supported);
1111
1112 station->m_groupsTable[station->m_sampleGroup].m_index++;
1113
1114 uint32_t sampleGroup = station->m_sampleGroup;
1115 uint8_t index = station->m_groupsTable[station->m_sampleGroup].m_index;
1116 uint8_t col = station->m_groupsTable[sampleGroup].m_col;
1117
1118 if (index >= m_numRates)
1119 {
1120 station->m_groupsTable[station->m_sampleGroup].m_index = 0;
1121 station->m_groupsTable[station->m_sampleGroup].m_col++;
1122 if (station->m_groupsTable[station->m_sampleGroup].m_col >= m_nSampleCol)
1123 {
1124 station->m_groupsTable[station->m_sampleGroup].m_col = 0;
1125 }
1126 index = station->m_groupsTable[station->m_sampleGroup].m_index;
1127 col = station->m_groupsTable[sampleGroup].m_col;
1128 }
1129 NS_LOG_DEBUG ("New sample set: group= " << sampleGroup << " index= " << station->m_sampleTable[index][col])do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "New sample set: group= "
<< sampleGroup << " index= " << station->
m_sampleTable[index][col] << std::endl; } } while (false
)
;
1130}
1131
1132uint32_t
1133MinstrelHtWifiManager::FindRate (MinstrelHtWifiRemoteStation *station)
1134{
1135 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1136 NS_LOG_DEBUG ("FindRate " << "packet=" << station->m_totalPacketsCount )do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "FindRate "
<< "packet=" << station->m_totalPacketsCount <<
std::endl; } } while (false)
;
1137
1138 if ((station->m_samplePacketsCount + station->m_totalPacketsCount) == 0)
1139 {
1140 return station->m_maxTpRate;
1141 }
1142
1143 // If we have waited enough, then sample.
1144 if (station->m_sampleWait == 0 && station->m_sampleTries != 0)
1145 {
1146 //SAMPLING
1147 NS_LOG_DEBUG ("Obtaining a sampling rate")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Obtaining a sampling rate"
<< std::endl; } } while (false)
;
1148 /// Now go through the table and find an index rate.
1149 uint32_t sampleIdx = GetNextSample (station);
1150 NS_LOG_DEBUG ("Sampling rate = " << sampleIdx)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Sampling rate = "
<< sampleIdx << std::endl; } } while (false)
;
1151
1152 //Evaluate if the sampling rate selected should be used.
1153 uint32_t sampleGroupId = GetGroupId (sampleIdx);
1154 uint32_t sampleRateId = GetRateId (sampleIdx);
1155
1156 // If the rate selected is not supported, then don't sample.
1157 if (station->m_groupsTable[sampleGroupId].m_supported && station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId].supported)
1158 {
1159 /**
1160 * Sampling might add some overhead to the frame.
1161 * Hence, don't use sampling for the currently used rates.
1162 *
1163 * Also do not sample if the probability is already higher than 95%
1164 * to avoid wasting airtime.
1165 */
1166 HtRateInfo sampleRateInfo = station->m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId];
1167
1168 NS_LOG_DEBUG ("Use sample rate? MaxTpRate= " << station->m_maxTpRate << " CurrentRate= " << station->m_txrate <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Use sample rate? MaxTpRate= "
<< station->m_maxTpRate << " CurrentRate= " <<
station->m_txrate << " SampleRate= " << sampleIdx
<< " SampleProb= " << sampleRateInfo.ewmaProb <<
std::endl; } } while (false)
1169 " SampleRate= " << sampleIdx << " SampleProb= " << sampleRateInfo.ewmaProb)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Use sample rate? MaxTpRate= "
<< station->m_maxTpRate << " CurrentRate= " <<
station->m_txrate << " SampleRate= " << sampleIdx
<< " SampleProb= " << sampleRateInfo.ewmaProb <<
std::endl; } } while (false)
;
1170
1171 if (sampleIdx != station->m_maxTpRate && sampleIdx != station->m_maxTpRate2
1172 && sampleIdx != station->m_maxProbRate && sampleRateInfo.ewmaProb <= 95)
1173 {
1174
1175 /**
1176 * Make sure that lower rates get sampled only occasionally,
1177 * if the link is working perfectly.
1178 */
1179
1180 uint32_t maxTpGroupId = GetGroupId (station->m_maxTpRate);
1181 uint32_t maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1182 uint32_t maxTp2RateId = GetRateId (station->m_maxTpRate2);
1183 uint32_t maxProbGroupId = GetGroupId (station->m_maxProbRate);
1184 uint32_t maxProbRateId = GetRateId (station->m_maxProbRate);
1185
1186 uint8_t maxTpStreams = m_minstrelGroups[maxTpGroupId].streams;
1187 uint8_t sampleStreams = m_minstrelGroups[sampleGroupId].streams;
1188
1189 Time sampleDuration = sampleRateInfo.perfectTxTime;
1190 Time maxTp2Duration = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].perfectTxTime;
1191 Time maxProbDuration = station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].perfectTxTime;
1192
1193 NS_LOG_DEBUG ("Use sample rate? SampleDuration= " << sampleDuration << " maxTp2Duration= " << maxTp2Duration <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Use sample rate? SampleDuration= "
<< sampleDuration << " maxTp2Duration= " <<
maxTp2Duration << " maxProbDuration= " << maxProbDuration
<< " sampleStreams= " << (uint16_t)sampleStreams
<< " maxTpStreams= " << (uint16_t)maxTpStreams <<
std::endl; } } while (false)
1194 " maxProbDuration= " << maxProbDuration << " sampleStreams= " << (uint16_t)sampleStreams <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Use sample rate? SampleDuration= "
<< sampleDuration << " maxTp2Duration= " <<
maxTp2Duration << " maxProbDuration= " << maxProbDuration
<< " sampleStreams= " << (uint16_t)sampleStreams
<< " maxTpStreams= " << (uint16_t)maxTpStreams <<
std::endl; } } while (false)
1195 " maxTpStreams= " << (uint16_t)maxTpStreams)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Use sample rate? SampleDuration= "
<< sampleDuration << " maxTp2Duration= " <<
maxTp2Duration << " maxProbDuration= " << maxProbDuration
<< " sampleStreams= " << (uint16_t)sampleStreams
<< " maxTpStreams= " << (uint16_t)maxTpStreams <<
std::endl; } } while (false)
;
1196 if (sampleDuration < maxTp2Duration || (sampleStreams < maxTpStreams && sampleDuration < maxProbDuration))
1197 {
1198 /// Set flag that we are currently sampling.
1199 station->m_isSampling = true;
1200
1201 /// set the rate that we're currently sampling
1202 station->m_sampleRate = sampleIdx;
1203
1204 NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "FindRate "
<< "sampleRate=" << sampleIdx << std::endl
; } } while (false)
;
1205 station->m_sampleTries--;
1206 return sampleIdx;
1207 }
1208 else
1209 {
1210 station->m_numSamplesSlow++;
1211 if (sampleRateInfo.numSamplesSkipped >= 20 && station->m_numSamplesSlow <= 2)
1212 {
1213 /// Set flag that we are currently sampling.
1214 station->m_isSampling = true;
1215
1216 /// set the rate that we're currently sampling
1217 station->m_sampleRate = sampleIdx;
1218
1219 NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "FindRate "
<< "sampleRate=" << sampleIdx << std::endl
; } } while (false)
;
1220 station->m_sampleTries--;
1221 return sampleIdx;
1222 }
1223 }
1224 }
1225 }
1226 }
1227 if (station->m_sampleWait > 0)
1228 {
1229 station->m_sampleWait--;
1230 }
1231
1232 /// Continue using the best rate.
1233
1234 NS_LOG_DEBUG ("FindRate " << "maxTpRrate=" << station->m_maxTpRate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "FindRate "
<< "maxTpRrate=" << station->m_maxTpRate <<
std::endl; } } while (false)
;
1235 return station->m_maxTpRate;
1236}
1237void
1238MinstrelHtWifiManager::UpdateStats (MinstrelHtWifiRemoteStation *station)
1239{
1240 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1241
1242 NS_LOG_DEBUG ("Updating stats=" << this)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Updating stats="
<< this << std::endl; } } while (false)
;
1243
1244 station->m_nextStatsUpdate = Simulator::Now () + m_updateStats;
1245
1246 station->m_numSamplesSlow = 0;
1247 station->m_sampleCount = 0;
1248
1249 double tempProb;
1250
1251 if (station->m_ampduPacketCount > 0)
1252 {
1253 double newLen = station->m_ampduLen / station->m_ampduPacketCount;
1254 station->m_avgAmpduLen = ( newLen * (100 - m_ewmaLevel) + (station->m_avgAmpduLen * m_ewmaLevel) ) / 100;
1255 station->m_ampduLen = 0;
1256 station->m_ampduPacketCount = 0;
1257 }
1258
1259 /* Initialize global rate indexes */
1260 station->m_maxTpRate = GetLowestIndex (station);
1261 station->m_maxTpRate2 = GetLowestIndex (station);
1262 station->m_maxProbRate = GetLowestIndex (station);
1263
1264 /// Update throughput and EWMA for each rate inside each group.
1265 for (uint32_t j = 0; j < m_numGroups; j++)
1266 {
1267 if (station->m_groupsTable[j].m_supported)
1268 {
1269 station->m_sampleCount++;
1270
1271 /* (re)Initialize group rate indexes */
1272 station->m_groupsTable[j].m_maxTpRate = GetLowestIndex (station, j);
1273 station->m_groupsTable[j].m_maxTpRate2 = GetLowestIndex (station, j);
1274 station->m_groupsTable[j].m_maxProbRate = GetLowestIndex (station, j);
1275
1276 for (uint32_t i = 0; i < m_numRates; i++)
1277 {
1278 if (station->m_groupsTable[j].m_ratesTable[i].supported)
1279 {
1280 station->m_groupsTable[j].m_ratesTable[i].retryUpdated = false;
1281
1282 NS_LOG_DEBUG (i << " " << GetMcsSupported (station, station->m_groupsTable[j].m_ratesTable[i].mcsIndex) <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << i << " "
<< GetMcsSupported (station, station->m_groupsTable
[j].m_ratesTable[i].mcsIndex) << "\t attempt=" <<
station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<
"\t success=" << station->m_groupsTable[j].m_ratesTable
[i].numRateSuccess << std::endl; } } while (false)
1283 "\t attempt=" << station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << i << " "
<< GetMcsSupported (station, station->m_groupsTable
[j].m_ratesTable[i].mcsIndex) << "\t attempt=" <<
station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<
"\t success=" << station->m_groupsTable[j].m_ratesTable
[i].numRateSuccess << std::endl; } } while (false)
1284 "\t success=" << station->m_groupsTable[j].m_ratesTable[i].numRateSuccess)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << i << " "
<< GetMcsSupported (station, station->m_groupsTable
[j].m_ratesTable[i].mcsIndex) << "\t attempt=" <<
station->m_groupsTable[j].m_ratesTable[i].numRateAttempt <<
"\t success=" << station->m_groupsTable[j].m_ratesTable
[i].numRateSuccess << std::endl; } } while (false)
;
1285
1286 /// If we've attempted something.
1287 if (station->m_groupsTable[j].m_ratesTable[i].numRateAttempt > 0)
1288 {
1289 station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped = 0;
1290 /**
1291 * Calculate the probability of success.
1292 * Assume probability scales from 0 to 100.
1293 */
1294 tempProb = (100 * station->m_groupsTable[j].m_ratesTable[i].numRateSuccess) / station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1295
1296 /// Bookeeping.
1297 station->m_groupsTable[j].m_ratesTable[i].prob = tempProb;
1298
1299 if (station->m_groupsTable[j].m_ratesTable[i].successHist == 0)
1300 {
1301 station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1302 }
1303 else
1304 {
1305 station->m_groupsTable[j].m_ratesTable[i].ewmsdProb = CalculateEwmsd (station->m_groupsTable[j].m_ratesTable[i].ewmsdProb,
1306 tempProb, station->m_groupsTable[j].m_ratesTable[i].ewmaProb,
1307 m_ewmaLevel);
1308 /// EWMA probability
1309 tempProb = (tempProb * (100 - m_ewmaLevel) + station->m_groupsTable[j].m_ratesTable[i].ewmaProb * m_ewmaLevel) / 100;
1310 station->m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1311 }
1312
1313 station->m_groupsTable[j].m_ratesTable[i].throughput = CalculateThroughput (station, j, i, tempProb);
1314
1315 station->m_groupsTable[j].m_ratesTable[i].successHist += station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1316 station->m_groupsTable[j].m_ratesTable[i].attemptHist += station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1317 }
1318 else
1319 {
1320 station->m_groupsTable[j].m_ratesTable[i].numSamplesSkipped++;
1321 }
1322
1323 /// Bookeeping.
1324 station->m_groupsTable[j].m_ratesTable[i].prevNumRateSuccess = station->m_groupsTable[j].m_ratesTable[i].numRateSuccess;
1325 station->m_groupsTable[j].m_ratesTable[i].prevNumRateAttempt = station->m_groupsTable[j].m_ratesTable[i].numRateAttempt;
1326 station->m_groupsTable[j].m_ratesTable[i].numRateSuccess = 0;
1327 station->m_groupsTable[j].m_ratesTable[i].numRateAttempt = 0;
1328
1329 if (station->m_groupsTable[j].m_ratesTable[i].throughput != 0)
1330 {
1331 SetBestStationThRates (station, GetIndex (j, i));
1332 SetBestProbabilityRate (station, GetIndex (j, i));
1333 }
1334
1335 }
1336 }
1337 }
1338 }
1339
1340 //Try to sample all available rates during each interval.
1341 station->m_sampleCount *= 8;
1342
1343 //Recalculate retries for the rates selected.
1344 CalculateRetransmits (station, station->m_maxTpRate);
1345 CalculateRetransmits (station, station->m_maxTpRate2);
1346 CalculateRetransmits (station, station->m_maxProbRate);
1347
1348 NS_LOG_DEBUG ("max tp=" << station->m_maxTpRate << "\nmax tp2=" << station->m_maxTpRate2 << "\nmax prob=" << station->m_maxProbRate)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "max tp=" <<
station->m_maxTpRate << "\nmax tp2=" << station
->m_maxTpRate2 << "\nmax prob=" << station->
m_maxProbRate << std::endl; } } while (false)
;
1349 if (m_printStats)
1350 {
1351 PrintTable (station);
1352 }
1353}
1354
1355double
1356MinstrelHtWifiManager::CalculateThroughput (MinstrelHtWifiRemoteStation *station, uint32_t groupId, uint32_t rateId, double ewmaProb)
1357{
1358 /**
1359 * Calculating throughput.
1360 * Do not account throughput if sucess prob is below 10%
1361 * (as done in minstrel_ht linux implementation).
1362 */
1363 if (ewmaProb < 10)
1364 {
1365 return 0;
1366 }
1367 else
1368 {
1369 /**
1370 * For the throughput calculation, limit the probability value to 90% to
1371 * account for collision related packet error rate fluctuation.
1372 */
1373 Time txTime = station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime;
1374 if (ewmaProb > 90)
1375 {
1376 return 90 / txTime.GetSeconds ();
1377 }
1378 else
1379 {
1380 return ewmaProb / txTime.GetSeconds ();
1381 }
1382 }
1383}
1384
1385void
1386MinstrelHtWifiManager::SetBestProbabilityRate (MinstrelHtWifiRemoteStation *station, uint32_t index)
1387{
1388 GroupInfo *group;
1389 HtRateInfo rate;
1390 uint32_t tmpGroupId, tmpRateId;
1391 double tmpTh, tmpProb;
1392 uint32_t groupId, rateId;
1393 double currentTh;
1394 // maximum group probability (GP) variables
1395 uint32_t maxGPGroupId, maxGPRateId;
1396 double maxGPTh;
1397
1398 groupId = GetGroupId (index);
1399 rateId = GetRateId (index);
1400 group = &station->m_groupsTable[groupId];
1401 rate = group->m_ratesTable[rateId];
1402
1403 tmpGroupId = GetGroupId (station->m_maxProbRate);
1404 tmpRateId = GetRateId (station->m_maxProbRate);
1405 tmpProb = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].ewmaProb;
1406 tmpTh = station->m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].throughput;
1407
1408 if (rate.ewmaProb > 75)
1409 {
1410 currentTh = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1411 if (currentTh > tmpTh)
1412 {
1413 station->m_maxProbRate = index;
1414 }
1415
1416 maxGPGroupId = GetGroupId (group->m_maxProbRate);
1417 maxGPRateId = GetRateId (group->m_maxProbRate);
1418 maxGPTh = station->m_groupsTable[maxGPGroupId].m_ratesTable[maxGPRateId].throughput;
1419
1420 if (currentTh > maxGPTh)
1421 {
1422 group->m_maxProbRate = index;
1423 }
1424 }
1425 else
1426 {
1427 if (rate.ewmaProb > tmpProb)
1428 {
1429 station->m_maxProbRate = index;
1430 }
1431 maxGPRateId = GetRateId (group->m_maxProbRate);
1432 if (rate.ewmaProb > group->m_ratesTable[maxGPRateId].ewmaProb)
1433 {
1434 group->m_maxProbRate = index;
1435 }
1436 }
1437}
1438
1439/*
1440 * Find & sort topmost throughput rates
1441 *
1442 * If multiple rates provide equal throughput the sorting is based on their
1443 * current success probability. Higher success probability is preferred among
1444 * MCS groups.
1445 */
1446void
1447MinstrelHtWifiManager::SetBestStationThRates (MinstrelHtWifiRemoteStation *station, uint32_t index)
1448{
1449 uint32_t groupId, rateId;
1450 double th, prob;
1451 uint32_t maxTpGroupId, maxTpRateId;
1452 uint32_t maxTp2GroupId, maxTp2RateId;
1453 double maxTpTh, maxTpProb;
1454 double maxTp2Th, maxTp2Prob;
1455
1456 groupId = GetGroupId (index);
1457 rateId = GetRateId (index);
1458 prob = station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb;
1459 th = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1460
1461 maxTpGroupId = GetGroupId (station->m_maxTpRate);
1462 maxTpRateId = GetRateId (station->m_maxTpRate);
1463 maxTpProb = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].ewmaProb;
1464 maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1465
1466 maxTp2GroupId = GetGroupId (station->m_maxTpRate2);
1467 maxTp2RateId = GetRateId (station->m_maxTpRate2);
1468 maxTp2Prob = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].ewmaProb;
1469 maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1470
1471 if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1472 {
1473 station->m_maxTpRate2 = station->m_maxTpRate;
1474 station->m_maxTpRate = index;
1475 }
1476 else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1477 {
1478 station->m_maxTpRate2 = index;
1479 }
1480
1481 //Find best rates per group
1482
1483 GroupInfo *group = &station->m_groupsTable[groupId];
1484 maxTpGroupId = GetGroupId (group->m_maxTpRate);
1485 maxTpRateId = GetRateId (group->m_maxTpRate);
1486 maxTpProb = group->m_ratesTable[maxTpRateId].ewmaProb;
1487 maxTpTh = station->m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1488
1489 maxTp2GroupId = GetGroupId (group->m_maxTpRate2);
1490 maxTp2RateId = GetRateId (group->m_maxTpRate2);
1491 maxTp2Prob = group->m_ratesTable[maxTp2RateId].ewmaProb;
1492 maxTp2Th = station->m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1493
1494 if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1495 {
1496 group->m_maxTpRate2 = group->m_maxTpRate;
1497 group->m_maxTpRate = index;
1498 }
1499 else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1500 {
1501 group->m_maxTpRate2 = index;
1502 }
1503}
1504
1505void
1506MinstrelHtWifiManager::RateInit (MinstrelHtWifiRemoteStation *station)
1507{
1508 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1509 NS_LOG_DEBUG ("RateInit=" << station)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "RateInit="
<< station << std::endl; } } while (false)
;
1510
1511 station->m_groupsTable = McsGroupData (m_numGroups);
1512
1513 /**
1514 * Initialize groups supported by the receiver.
1515 */
1516 NS_LOG_DEBUG ("Supported groups by station:")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Supported groups by station:"
<< std::endl; } } while (false)
;
1517 for (uint32_t groupId = 0; groupId < m_numGroups; groupId++)
1
Loop condition is false. Execution continues on line 1583
1518 {
1519 if (m_minstrelGroups[groupId].isSupported)
1520 {
1521 station->m_groupsTable[groupId].m_supported = false;
1522 if (!(!GetVhtSupported (station) && m_minstrelGroups[groupId].isVht) ///Is VHT supported by the receiver?
1523 && (m_minstrelGroups[groupId].isVht || !GetVhtSupported (station) || !m_useVhtOnly) ///If it is an HT MCS, check if VHT only is disabled
1524 && !(!GetShortGuardInterval (station) && m_minstrelGroups[groupId].sgi) ///Is SGI supported by the receiver?
1525 && (GetChannelWidth (station) >= m_minstrelGroups[groupId].chWidth) ///Is channel width supported by the receiver?
1526 && (GetNumberOfSupportedStreams (station) >= m_minstrelGroups[groupId].streams)) ///Are streams supported by the receiver?
1527 {
1528 NS_LOG_DEBUG ("Group " << groupId << ": (" << (uint16_t)m_minstrelGroups[groupId].streams <<do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Group " <<
groupId << ": (" << (uint16_t)m_minstrelGroups[groupId
].streams << "," << (uint16_t)m_minstrelGroups[groupId
].sgi << "," << (uint16_t)m_minstrelGroups[groupId
].chWidth << ")" << std::endl; } } while (false)
1529 "," << (uint16_t)m_minstrelGroups[groupId].sgi << "," << (uint16_t)m_minstrelGroups[groupId].chWidth << ")")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Group " <<
groupId << ": (" << (uint16_t)m_minstrelGroups[groupId
].streams << "," << (uint16_t)m_minstrelGroups[groupId
].sgi << "," << (uint16_t)m_minstrelGroups[groupId
].chWidth << ")" << std::endl; } } while (false)
;
1530
1531 station->m_groupsTable[groupId].m_supported = true; ///Group supported.
1532 station->m_groupsTable[groupId].m_col = 0;
1533 station->m_groupsTable[groupId].m_index = 0;
1534
1535 station->m_groupsTable[groupId].m_ratesTable = HtMinstrelRate (m_numRates); ///Create the rate list for the group.
1536 for (uint32_t i = 0; i < m_numRates; i++)
1537 {
1538 station->m_groupsTable[groupId].m_ratesTable[i].supported = false;
1539 }
1540
1541 // Initialize all modes supported by the remote station that belong to the current group.
1542 for (uint32_t i = 0; i < station->m_nModes; i++)
1543 {
1544 WifiMode mode = GetMcsSupported (station, i);
1545
1546 ///Use the McsValue as the index in the rate table.
1547 ///This way, MCSs not supported are not initialized.
1548 uint32_t rateId = mode.GetMcsValue ();
1549 if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1550 {
1551 rateId %= MAX_HT_GROUP_RATES;
1552 }
1553
1554 if ((m_minstrelGroups[groupId].isVht && mode.GetModulationClass () == WIFI_MOD_CLASS_VHT ///If it is a VHT MCS only add to a VHT group.
1555 && IsValidMcs (GetPhy (), m_minstrelGroups[groupId].streams, m_minstrelGroups[groupId].chWidth, mode)) ///Check validity of the VHT MCS
1556 || (!m_minstrelGroups[groupId].isVht && mode.GetModulationClass () == WIFI_MOD_CLASS_HT ///If it is a HT MCS only add to a HT group.
1557 && mode.GetMcsValue () < (m_minstrelGroups[groupId].streams * 8) ///Check if the HT MCS corresponds to groups number of streams.
1558 && mode.GetMcsValue () >= ((m_minstrelGroups[groupId].streams - 1) * 8)))
1559 {
1560 NS_LOG_DEBUG ("Mode " << i << ": " << mode << " isVht: " << m_minstrelGroups[groupId].isVht)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "Mode " <<
i << ": " << mode << " isVht: " << m_minstrelGroups
[groupId].isVht << std::endl; } } while (false)
;
1561
1562 station->m_groupsTable[groupId].m_ratesTable[rateId].supported = true;
1563 station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex = i; ///Mapping between rateId and operationalMcsSet
1564 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt = 0;
1565 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess = 0;
1566 station->m_groupsTable[groupId].m_ratesTable[rateId].prob = 0;
1567 station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb = 0;
1568 station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateAttempt = 0;
1569 station->m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateSuccess = 0;
1570 station->m_groupsTable[groupId].m_ratesTable[rateId].numSamplesSkipped = 0;
1571 station->m_groupsTable[groupId].m_ratesTable[rateId].successHist = 0;
1572 station->m_groupsTable[groupId].m_ratesTable[rateId].attemptHist = 0;
1573 station->m_groupsTable[groupId].m_ratesTable[rateId].throughput = 0;
1574 station->m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, i));
1575 station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 0;
1576 station->m_groupsTable[groupId].m_ratesTable[rateId].adjustedRetryCount = 0;
1577 CalculateRetransmits (station, groupId, rateId);
1578 }
1579 }
1580 }
1581 }
1582 }
1583 SetNextSample (station); /// Select the initial sample index.
2
Calling 'MinstrelHtWifiManager::SetNextSample'
1584 UpdateStats (station); /// Calculate the initial high throughput rates.
1585 station->m_txrate = FindRate (station); /// Select the rate to use.
1586}
1587
1588void
1589MinstrelHtWifiManager::CalculateRetransmits (MinstrelHtWifiRemoteStation *station, uint32_t index)
1590{
1591 NS_LOG_FUNCTION (this << station << index)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station << index; std::clog << ")"
<< std::endl; } } while (false)
;
1592 uint32_t groupId = GetGroupId (index);
1593 uint32_t rateId = GetRateId (index);
1594 if (!station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated)
1595 {
1596 CalculateRetransmits (station, groupId, rateId);
1597 }
1598}
1599
1600void
1601MinstrelHtWifiManager::CalculateRetransmits (MinstrelHtWifiRemoteStation *station, uint32_t groupId, uint32_t rateId)
1602{
1603 NS_LOG_FUNCTION (this << station << groupId << groupId)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station << groupId << groupId; std
::clog << ")" << std::endl; } } while (false)
;
1604 NS_LOG_DEBUG (" Calculating the number of retries")do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << " Calculating the number of retries"
<< std::endl; } } while (false)
;
1605
1606 uint32_t cw = 15; // Is an approximation.
1607 uint32_t cwMax = 1023;
1608 Time cwTime, txTime, dataTxTime;
1609 Time slotTime = GetMac ()->GetSlot ();
1610 Time ackTime = GetMac ()->GetBasicBlockAckTimeout ();
1611
1612 if (station->m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb < 1)
1613 {
1614 station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 1;
1615 }
1616 else
1617 {
1618 station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 2;
1619 station->m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated = true;
1620
1621 dataTxTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) +
1622 GetMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) * (station->m_avgAmpduLen - 1);
1623
1624 /* Contention time for first 2 tries */
1625 cwTime = (cw / 2) * slotTime;
1626 cw = Min ((cw + 1) * 2, cwMax)(((cw + 1) * 2 < cwMax) ? (cw + 1) * 2 : cwMax);
1627 cwTime += (cw / 2) * slotTime;
1628 cw = Min ((cw + 1) * 2, cwMax)(((cw + 1) * 2 < cwMax) ? (cw + 1) * 2 : cwMax);
1629
1630 /* Total TX time for data and Contention after first 2 tries */
1631 txTime = cwTime + 2 * (dataTxTime + ackTime);
1632
1633 /* See how many more tries we can fit inside segment size */
1634 do
1635 {
1636 /* Contention time for this try */
1637 cwTime = (cw / 2) * slotTime;
1638 cw = Min ((cw + 1) * 2, cwMax)(((cw + 1) * 2 < cwMax) ? (cw + 1) * 2 : cwMax);
1639
1640 /* Total TX time after this try */
1641 txTime += cwTime + ackTime + dataTxTime;
1642 }
1643 while ((txTime < MilliSeconds (6))
1644 && (++station->m_groupsTable[groupId].m_ratesTable[rateId].retryCount < 7));
1645 }
1646}
1647
1648double
1649MinstrelHtWifiManager::CalculateEwmsd (double oldEwmsd, double currentProb, double ewmaProb, uint32_t weight)
1650{
1651 double diff, incr, tmp;
1652
1653 /* calculate exponential weighted moving variance */
1654 diff = currentProb - ewmaProb;
1655 incr = (100 - weight) * diff / 100;
1656 tmp = oldEwmsd * oldEwmsd;
1657 tmp = weight * (tmp + diff * incr) / 100;
1658
1659 /* return standard deviation */
1660 return sqrt (tmp);
1661}
1662
1663void
1664MinstrelHtWifiManager::InitSampleTable (MinstrelHtWifiRemoteStation *station)
1665{
1666 NS_LOG_DEBUG ("InitSampleTable=" << this)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "InitSampleTable="
<< this << std::endl; } } while (false)
;
1667
1668 station->m_col = station->m_index = 0;
1669
1670 //for off-setting to make rates fall between 0 and nModes
1671 uint32_t numSampleRates = m_numRates;
1672
1673 uint32_t newIndex;
1674 for (uint32_t col = 0; col < m_nSampleCol; col++)
1675 {
1676 for (uint32_t i = 0; i < numSampleRates; i++ )
1677 {
1678 /**
1679 * The next two lines basically tries to generate a random number
1680 * between 0 and the number of available rates
1681 */
1682 int uv = m_uniformRandomVariable->GetInteger (0, numSampleRates);
1683 newIndex = (i + uv) % numSampleRates;
1684
1685 //this loop is used for filling in other uninitialized places
1686 while (station->m_sampleTable[newIndex][col] != 0)
1687 {
1688 newIndex = (newIndex + 1) % m_numRates;
1689 }
1690 station->m_sampleTable[newIndex][col] = i;
1691 }
1692 }
1693}
1694
1695void
1696MinstrelHtWifiManager::PrintTable (MinstrelHtWifiRemoteStation *station)
1697{
1698 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1699 NS_LOG_DEBUG ("PrintTable=" << station)do { if (g_log.IsEnabled (ns3::LOG_DEBUG)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC)) { std
::clog << g_log.Name () << ":" << __FUNCTION__
<< "(): "; }; if (g_log.IsEnabled (ns3::LOG_PREFIX_LEVEL
)) { std::clog << "[" << g_log.GetLevelLabel (ns3
::LOG_DEBUG) << "] "; }; std::clog << "PrintTable="
<< station << std::endl; } } while (false)
;
1700
1701 station->m_statsFile << " best ____________rate__________ ________statistics________ ________last_______ ______sum-of________\n" <<
1702 " mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n";
1703 for (uint32_t i = 0; i < m_numGroups; i++)
1704 {
1705 StatsDump (station, i, station->m_statsFile);
1706 }
1707
1708 station->m_statsFile << "\nTotal packet count:: ideal " << Max (0, station->m_totalPacketsCount - station->m_samplePacketsCount)((0 > station->m_totalPacketsCount - station->m_samplePacketsCount
) ? 0 : station->m_totalPacketsCount - station->m_samplePacketsCount
)
<<
1709 " lookaround " << station->m_samplePacketsCount << "\n";
1710 station->m_statsFile << "Average # of aggregated frames per A-MPDU: " << station->m_avgAmpduLen << "\n\n";
1711
1712 station->m_statsFile.flush ();
1713}
1714
1715void
1716MinstrelHtWifiManager::StatsDump (MinstrelHtWifiRemoteStation *station, uint32_t groupId, std::ofstream &of)
1717{
1718 uint32_t numRates = m_numRates;
1719 McsGroup group = m_minstrelGroups[groupId];
1720 Time txTime;
1721 char giMode;
1722 if (group.sgi)
1723 {
1724 giMode = 'S';
1725 }
1726 else
1727 {
1728 giMode = 'L';
1729 }
1730 for (uint32_t i = 0; i < numRates; i++)
1731 {
1732 if (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[i].supported)
1733 {
1734 if (!group.isVht)
1735 {
1736 of << "HT" << group.chWidth << " " << giMode << "GI " << (int)group.streams << " ";
1737 }
1738 else
1739 {
1740 of << "VHT" << group.chWidth << " " << giMode << "GI " << (int)group.streams << " ";
1741 }
1742
1743 uint32_t maxTpRate = station->m_maxTpRate;
1744 uint32_t maxTpRate2 = station->m_maxTpRate2;
1745 uint32_t maxProbRate = station->m_maxProbRate;
1746
1747 uint32_t idx = GetIndex (groupId, i);
1748 if (idx == maxTpRate)
1749 {
1750 of << 'A';
1751 }
1752 else
1753 {
1754 of << ' ';
1755 }
1756 if (idx == maxTpRate2)
1757 {
1758 of << 'B';
1759 }
1760 else
1761 {
1762 of << ' ';
1763 }
1764 if (idx == maxProbRate)
1765 {
1766 of << 'P';
1767 }
1768 else
1769 {
1770 of << ' ';
1771 }
1772
1773 if (!group.isVht)
1774 {
1775 of << std::setw (4) << " MCS" << (group.streams - 1) * 8 + i;
1776 }
1777 else
1778 {
1779 of << std::setw (7) << " MCS" << i << "/" << (int) group.streams;
1780 }
1781
1782 of << " " << std::setw (3) << idx << " ";
1783
1784 /* tx_time[rate(i)] in usec */
1785 txTime = GetFirstMpduTxTime (groupId, GetMcsSupported (station, station->m_groupsTable[groupId].m_ratesTable[i].mcsIndex));
1786 of << std::setw (6) << txTime.GetMicroSeconds () << " ";
1787
1788 of << std::setw (7) << CalculateThroughput (station, groupId, i, 100) / 100 << " " <<
1789 std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].throughput / 100 << " " <<
1790 std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmaProb << " " <<
1791 std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].ewmsdProb << " " <<
1792 std::setw (7) << station->m_groupsTable[groupId].m_ratesTable[i].prob << " " <<
1793 std::setw (2) << station->m_groupsTable[groupId].m_ratesTable[i].retryCount << " " <<
1794 std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateSuccess << " " <<
1795 std::setw (3) << station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt << " " <<
1796 std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].successHist << " " <<
1797 std::setw (9) << station->m_groupsTable[groupId].m_ratesTable[i].attemptHist << "\n";
1798 }
1799 }
1800}
1801uint32_t
1802MinstrelHtWifiManager::GetIndex (uint32_t groupId, uint32_t rateId)
1803{
1804 NS_LOG_FUNCTION (this << groupId << rateId)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << groupId << rateId; std::clog << ")"
<< std::endl; } } while (false)
;
1805 uint32_t index;
1806 index = groupId * m_numRates + rateId;
1807 return index;
1808}
1809
1810uint32_t
1811MinstrelHtWifiManager::GetRateId (uint32_t index)
1812{
1813 NS_LOG_FUNCTION (this << index)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << index; std::clog << ")" << std::endl
; } } while (false)
;
1814
1815 uint32_t id;
1816 id = index % m_numRates;
1817 return id;
1818}
1819
1820uint32_t
1821MinstrelHtWifiManager::GetGroupId (uint32_t index)
1822{
1823 NS_LOG_FUNCTION (this << index)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << index; std::clog << ")" << std::endl
; } } while (false)
;
1824
1825 return index / m_numRates;
1826}
1827
1828uint32_t
1829MinstrelHtWifiManager::GetHtGroupId (uint8_t txstreams, uint8_t sgi, uint8_t chWidth)
1830{
1831 NS_LOG_FUNCTION (this << (uint16_t)txstreams << (uint16_t)sgi << (uint16_t)chWidth)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << (uint16_t)txstreams << (uint16_t)sgi <<
(uint16_t)chWidth; std::clog << ")" << std::endl
; } } while (false)
;
1832
1833 return MAX_SUPPORTED_STREAMS * 2 * (chWidth == 40 ? 1 : 0) + MAX_SUPPORTED_STREAMS * sgi + txstreams - 1;
1834}
1835
1836uint32_t
1837MinstrelHtWifiManager::GetVhtGroupId (uint8_t txstreams, uint8_t sgi, uint8_t chWidth)
1838{
1839 NS_LOG_FUNCTION (this << (uint16_t)txstreams << (uint16_t)sgi << (uint16_t)chWidth)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << (uint16_t)txstreams << (uint16_t)sgi <<
(uint16_t)chWidth; std::clog << ")" << std::endl
; } } while (false)
;
1840
1841 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;
1842}
1843
1844uint32_t
1845MinstrelHtWifiManager::GetLowestIndex (MinstrelHtWifiRemoteStation *station)
1846{
1847 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1848
1849 uint32_t groupId = 0;
1850 uint32_t rateId = 0;
1851 while (groupId < m_numGroups && !station->m_groupsTable[groupId].m_supported)
1852 {
1853 groupId++;
1854 }
1855 while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1856 {
1857 rateId++;
1858 }
1859 NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported)do { if (!(station->m_groupsTable[groupId].m_supported &&
station->m_groupsTable[groupId].m_ratesTable[rateId].supported
)) { std::cerr << "assert failed. cond=\"" << "station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported"
<< "\", "; do { std::cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 1859 << std::endl; ::ns3::
FatalImpl::FlushStreams (); if (true) std::terminate (); } while
(false); } } while (false)
;
1860 return GetIndex (groupId, rateId);
1861}
1862
1863uint32_t
1864MinstrelHtWifiManager::GetLowestIndex (MinstrelHtWifiRemoteStation *station, uint32_t groupId)
1865{
1866 NS_LOG_FUNCTION (this << station)do { if (g_log.IsEnabled (ns3::LOG_FUNCTION)) { if (g_log.IsEnabled
(ns3::LOG_PREFIX_TIME)) { ns3::LogTimePrinter printer = ns3::
LogGetTimePrinter (); if (printer != 0) { (*printer)(std::clog
); std::clog << " "; } }; if (g_log.IsEnabled (ns3::LOG_PREFIX_NODE
)) { ns3::LogNodePrinter printer = ns3::LogGetNodePrinter ();
if (printer != 0) { (*printer)(std::clog); std::clog <<
" "; } }; ; std::clog << g_log.Name () << ":" <<
__FUNCTION__ << "("; ns3::ParameterLogger (std::clog) <<
this << station; std::clog << ")" << std::
endl; } } while (false)
;
1867
1868 uint32_t rateId = 0;
1869 while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
1870 {
1871 rateId++;
1872 }
1873 NS_ASSERT (station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported)do { if (!(station->m_groupsTable[groupId].m_supported &&
station->m_groupsTable[groupId].m_ratesTable[rateId].supported
)) { std::cerr << "assert failed. cond=\"" << "station->m_groupsTable[groupId].m_supported && station->m_groupsTable[groupId].m_ratesTable[rateId].supported"
<< "\", "; do { std::cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 1873 << std::endl; ::ns3::
FatalImpl::FlushStreams (); if (true) std::terminate (); } while
(false); } } while (false)
;
1874 return GetIndex (groupId, rateId);
1875}
1876
1877
1878WifiModeList
1879MinstrelHtWifiManager::GetVhtDeviceMcsList (void) const
1880{
1881 WifiModeList vhtMcsList;
1882 Ptr<WifiPhy> phy = GetPhy ();
1883 for (uint32_t i = 0; i < phy->GetNMcs (); i++)
1884 {
1885 WifiMode mode = phy->GetMcs (i);
1886 if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)
1887 {
1888 vhtMcsList.push_back (mode);
1889 }
1890 }
1891 return vhtMcsList;
1892}
1893
1894WifiModeList
1895MinstrelHtWifiManager::GetHtDeviceMcsList (void) const
1896{
1897 WifiModeList htMcsList;
1898 Ptr<WifiPhy> phy = GetPhy ();
1899 for (uint32_t i = 0; i < phy->GetNMcs (); i++)
1900 {
1901 WifiMode mode = phy->GetMcs (i);
1902 if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT)
1903 {
1904 htMcsList.push_back (mode);
1905 }
1906 }
1907 return htMcsList;
1908}
1909
1910void
1911MinstrelHtWifiManager::SetHeSupported (bool enable)
1912{
1913 //HE is not supported yet by this algorithm.
1914 if (enable)
1915 {
1916 NS_FATAL_ERROR ("WifiRemoteStationManager selected does not support HE rates")do { std::cerr << "msg=\"" << "WifiRemoteStationManager selected does not support HE rates"
<< "\", "; do { std::cerr << "file=" << "../src/wifi/model/minstrel-ht-wifi-manager.cc"
<< ", line=" << 1916 << std::endl; ::ns3::
FatalImpl::FlushStreams (); if (true) std::terminate (); } while
(false); } while (false)
;
1917 }
1918}
1919
1920} // namespace ns3
1921
1922
1923
1924
1925