|
duy@4703
|
1 |
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
duy@4703
|
2 |
/*
|
|
duy@4703
|
3 |
* Copyright (c) 2009 Duy Nguyen
|
|
duy@4703
|
4 |
*
|
|
duy@4703
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
duy@4703
|
6 |
* it under the terms of the GNU General Public License version 2 as
|
|
duy@4703
|
7 |
* published by the Free Software Foundation;
|
|
duy@4703
|
8 |
*
|
|
duy@4703
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
duy@4703
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
duy@4703
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
duy@4703
|
12 |
* GNU General Public License for more details.
|
|
duy@4703
|
13 |
*
|
|
duy@4703
|
14 |
* You should have received a copy of the GNU General Public License
|
|
duy@4703
|
15 |
* along with this program; if not, write to the Free Software
|
|
duy@4703
|
16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
duy@4703
|
17 |
*
|
|
duy@4703
|
18 |
* Author: Duy Nguyen <duy@soe.ucsc.edu>
|
|
duy@4703
|
19 |
*
|
|
duy@4703
|
20 |
* Some Comments:
|
|
duy@4703
|
21 |
*
|
|
duy@4703
|
22 |
* 1) Segment Size is declared for completeness but not used because it has
|
|
duy@4703
|
23 |
* to do more with the requirement of the specific hardware.
|
|
duy@4703
|
24 |
*
|
|
duy@4703
|
25 |
* 2) By default, Minstrel applies the multi-rate retry(the core of Minstrel
|
|
duy@4703
|
26 |
* algorithm). Otherwise, please use ConstantRateWifiManager instead.
|
|
duy@4703
|
27 |
*
|
|
duy@4703
|
28 |
* http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel
|
|
duy@4703
|
29 |
*/
|
|
duy@4703
|
30 |
|
|
duy@4703
|
31 |
|
|
duy@4703
|
32 |
|
|
duy@4703
|
33 |
#include "minstrel-wifi-manager.h"
|
|
duy@4703
|
34 |
#include "wifi-phy.h"
|
|
duy@4703
|
35 |
#include "ns3/random-variable.h"
|
|
duy@4703
|
36 |
#include "ns3/simulator.h"
|
|
duy@4703
|
37 |
#include "ns3/log.h"
|
|
duy@4703
|
38 |
#include "ns3/uinteger.h"
|
|
duy@4703
|
39 |
#include "ns3/double.h"
|
|
duy@4703
|
40 |
#include "ns3/wifi-mac.h"
|
|
duy@4703
|
41 |
#include "ns3/assert.h"
|
|
duy@4703
|
42 |
#include <vector>
|
|
duy@4703
|
43 |
|
|
duy@4703
|
44 |
NS_LOG_COMPONENT_DEFINE ("MinstrelWifiManager");
|
|
duy@4703
|
45 |
|
|
duy@4703
|
46 |
|
|
duy@4703
|
47 |
namespace ns3 {
|
|
duy@4703
|
48 |
|
|
duy@4703
|
49 |
NS_OBJECT_ENSURE_REGISTERED (MinstrelWifiManager);
|
|
duy@4703
|
50 |
|
|
duy@4703
|
51 |
TypeId
|
|
duy@4703
|
52 |
MinstrelWifiManager::GetTypeId (void)
|
|
duy@4703
|
53 |
{
|
|
duy@4703
|
54 |
static TypeId tid = TypeId ("ns3::MinstrelWifiManager")
|
|
duy@4703
|
55 |
.SetParent<WifiRemoteStationManager> ()
|
|
duy@4703
|
56 |
.AddConstructor<MinstrelWifiManager> ()
|
|
duy@4703
|
57 |
.AddAttribute ("UpdateStatistics",
|
|
duy@4703
|
58 |
"The interval between updating statistics table ",
|
|
duy@4703
|
59 |
TimeValue (Seconds (0.1)),
|
|
duy@4703
|
60 |
MakeTimeAccessor (&MinstrelWifiManager::m_updateStats),
|
|
duy@4703
|
61 |
MakeTimeChecker ())
|
|
duy@4703
|
62 |
.AddAttribute ("LookAroundRate",
|
|
duy@4703
|
63 |
"the percentage to try other rates",
|
|
duy@4703
|
64 |
DoubleValue (10),
|
|
duy@4703
|
65 |
MakeDoubleAccessor (&MinstrelWifiManager::m_lookAroundRate),
|
|
duy@4703
|
66 |
MakeDoubleChecker<double> ())
|
|
duy@4703
|
67 |
.AddAttribute ("EWMA",
|
|
duy@4703
|
68 |
"EWMA level",
|
|
duy@4703
|
69 |
DoubleValue (75),
|
|
duy@4703
|
70 |
MakeDoubleAccessor (&MinstrelWifiManager::m_ewmaLevel),
|
|
duy@4703
|
71 |
MakeDoubleChecker<double> ())
|
|
duy@4703
|
72 |
.AddAttribute ("SegmentSize",
|
|
duy@4703
|
73 |
"The largest allowable segment size packet",
|
|
duy@4703
|
74 |
DoubleValue (6000),
|
|
duy@4703
|
75 |
MakeDoubleAccessor (&MinstrelWifiManager::m_segmentSize),
|
|
duy@4703
|
76 |
MakeDoubleChecker <double> ())
|
|
duy@4703
|
77 |
.AddAttribute ("SampleColumn",
|
|
duy@4703
|
78 |
"The number of columns used for sampling",
|
|
duy@4703
|
79 |
DoubleValue (10),
|
|
duy@4703
|
80 |
MakeDoubleAccessor (&MinstrelWifiManager::m_sampleCol),
|
|
duy@4703
|
81 |
MakeDoubleChecker <double> ())
|
|
duy@4703
|
82 |
.AddAttribute ("PacketLength",
|
|
duy@4703
|
83 |
"The packet length used for calculating mode TxTime",
|
|
duy@4703
|
84 |
DoubleValue (1200),
|
|
duy@4703
|
85 |
MakeDoubleAccessor (&MinstrelWifiManager::m_pktLen),
|
|
duy@4703
|
86 |
MakeDoubleChecker <double> ())
|
|
duy@4703
|
87 |
;
|
|
duy@4703
|
88 |
return tid;
|
|
duy@4703
|
89 |
}
|
|
duy@4703
|
90 |
|
|
duy@4703
|
91 |
MinstrelWifiManager::MinstrelWifiManager ()
|
|
duy@4703
|
92 |
{}
|
|
duy@4703
|
93 |
|
|
duy@4703
|
94 |
MinstrelWifiManager::~MinstrelWifiManager ()
|
|
duy@4703
|
95 |
{}
|
|
duy@4703
|
96 |
|
|
duy@4703
|
97 |
void
|
|
duy@4703
|
98 |
MinstrelWifiManager::SetupPhy (Ptr<WifiPhy> phy)
|
|
duy@4703
|
99 |
{
|
|
duy@4703
|
100 |
uint32_t nModes = phy->GetNModes ();
|
|
duy@4703
|
101 |
for (uint32_t i = 0; i < nModes; i++)
|
|
duy@4703
|
102 |
{
|
|
duy@4703
|
103 |
WifiMode mode = phy->GetMode (i);
|
|
duy@4703
|
104 |
AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, mode, WIFI_PREAMBLE_LONG));
|
|
duy@4703
|
105 |
}
|
|
duy@4703
|
106 |
WifiRemoteStationManager::SetupPhy (phy);
|
|
duy@4703
|
107 |
}
|
|
duy@4703
|
108 |
|
|
duy@4703
|
109 |
WifiRemoteStation *
|
|
duy@4703
|
110 |
MinstrelWifiManager::CreateStation (void)
|
|
duy@4703
|
111 |
{
|
|
duy@4703
|
112 |
return new MinstrelWifiRemoteStation (this);
|
|
duy@4703
|
113 |
}
|
|
duy@4703
|
114 |
|
|
duy@4703
|
115 |
Time
|
|
duy@4703
|
116 |
MinstrelWifiManager::GetCalcTxTime (WifiMode mode) const
|
|
duy@4703
|
117 |
{
|
|
duy@4703
|
118 |
|
|
duy@4703
|
119 |
for (TxTime::const_iterator i = m_calcTxTime.begin (); i != m_calcTxTime.end (); i++)
|
|
duy@4703
|
120 |
{
|
|
duy@4703
|
121 |
if (mode == i->second)
|
|
duy@4703
|
122 |
{
|
|
duy@4703
|
123 |
return i->first;
|
|
duy@4703
|
124 |
}
|
|
duy@4703
|
125 |
}
|
|
duy@4703
|
126 |
NS_ASSERT (false);
|
|
duy@4703
|
127 |
return Seconds (0);
|
|
duy@4703
|
128 |
}
|
|
duy@4703
|
129 |
|
|
duy@4703
|
130 |
void
|
|
duy@4703
|
131 |
MinstrelWifiManager::AddCalcTxTime (WifiMode mode, Time t)
|
|
duy@4703
|
132 |
{
|
|
duy@4703
|
133 |
m_calcTxTime.push_back (std::make_pair (t, mode));
|
|
duy@4703
|
134 |
}
|
|
duy@4703
|
135 |
|
|
duy@4703
|
136 |
MinstrelWifiRemoteStation::MinstrelWifiRemoteStation (Ptr<MinstrelWifiManager> stations)
|
|
duy@4703
|
137 |
:m_stations (stations),
|
|
duy@4703
|
138 |
m_nextStatsUpdate (Simulator::Now () + stations->m_updateStats),
|
|
duy@4703
|
139 |
m_col (0),
|
|
duy@4703
|
140 |
m_index (0),
|
|
duy@4703
|
141 |
m_maxTpRate (0),
|
|
duy@4703
|
142 |
m_maxTpRate2 (0),
|
|
duy@4703
|
143 |
m_maxProbRate (0),
|
|
duy@4703
|
144 |
m_packetCount (0),
|
|
duy@4703
|
145 |
m_sampleCount (0),
|
|
duy@4703
|
146 |
m_isSampling (false),
|
|
duy@4703
|
147 |
m_sampleRate (0),
|
|
duy@4703
|
148 |
m_sampleRateSlower (false),
|
|
duy@4703
|
149 |
m_currentRate (0),
|
|
duy@4703
|
150 |
m_shortRetry (0),
|
|
duy@4703
|
151 |
m_longRetry (0),
|
|
duy@4703
|
152 |
m_retry (0),
|
|
duy@4703
|
153 |
m_err (0),
|
|
duy@4703
|
154 |
m_txrate (0),
|
|
duy@4703
|
155 |
m_initialized (false)
|
|
duy@4703
|
156 |
{}
|
|
duy@4703
|
157 |
|
|
duy@4703
|
158 |
MinstrelWifiRemoteStation::~MinstrelWifiRemoteStation ()
|
|
duy@4703
|
159 |
{}
|
|
duy@4703
|
160 |
|
|
duy@4703
|
161 |
void
|
|
duy@4703
|
162 |
MinstrelWifiRemoteStation::CheckInit(void)
|
|
duy@4703
|
163 |
{
|
|
duy@4703
|
164 |
if (!m_initialized)
|
|
duy@4703
|
165 |
{
|
|
duy@4703
|
166 |
m_minstrelTable = MinstrelRate(GetNSupportedModes ());
|
|
duy@4703
|
167 |
m_sampleTable = SampleRate(GetNSupportedModes (), std::vector<uint32_t> (m_stations->m_sampleCol));
|
|
duy@4703
|
168 |
InitSampleTable ();
|
|
duy@4703
|
169 |
RateInit ();
|
|
duy@4703
|
170 |
m_initialized = true;
|
|
duy@4703
|
171 |
}
|
|
duy@4703
|
172 |
}
|
|
duy@4703
|
173 |
|
|
duy@4703
|
174 |
void
|
|
duy@4703
|
175 |
MinstrelWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
|
|
duy@4703
|
176 |
{
|
|
duy@4703
|
177 |
NS_LOG_DEBUG("DoReportRxOk m_txrate=" << m_txrate);
|
|
duy@4703
|
178 |
}
|
|
duy@4703
|
179 |
|
|
duy@4703
|
180 |
void
|
|
duy@4703
|
181 |
MinstrelWifiRemoteStation::DoReportRtsFailed (void)
|
|
duy@4703
|
182 |
{
|
|
duy@4703
|
183 |
NS_LOG_DEBUG("DoReportRtsFailed m_txrate=" << m_txrate);
|
|
duy@4703
|
184 |
|
|
duy@4703
|
185 |
m_shortRetry++;
|
|
duy@4703
|
186 |
}
|
|
duy@4703
|
187 |
|
|
duy@4703
|
188 |
void
|
|
duy@4703
|
189 |
MinstrelWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
|
|
duy@4703
|
190 |
{
|
|
duy@4703
|
191 |
NS_LOG_DEBUG ("self="<<this<<" rts ok");
|
|
duy@4703
|
192 |
}
|
|
duy@4703
|
193 |
|
|
duy@4703
|
194 |
void
|
|
duy@4703
|
195 |
MinstrelWifiRemoteStation::DoReportFinalRtsFailed (void)
|
|
duy@4703
|
196 |
{
|
|
duy@4703
|
197 |
UpdateRetry ();
|
|
duy@4703
|
198 |
m_err++;
|
|
duy@4703
|
199 |
}
|
|
duy@4703
|
200 |
|
|
duy@4703
|
201 |
void
|
|
duy@4703
|
202 |
MinstrelWifiRemoteStation::DoReportDataFailed (void)
|
|
duy@4703
|
203 |
{
|
|
duy@4703
|
204 |
CheckInit();
|
|
duy@4703
|
205 |
|
|
duy@4703
|
206 |
m_longRetry++;
|
|
duy@4703
|
207 |
|
|
duy@4703
|
208 |
NS_LOG_DEBUG ("DoReportDataFailed " << this << "\t rate " << m_txrate << "\tlongRetry \t" << m_longRetry);
|
|
duy@4703
|
209 |
|
|
duy@4703
|
210 |
/// for normal rate, we're not currently sampling random rates
|
|
duy@4703
|
211 |
if (!m_isSampling)
|
|
duy@4703
|
212 |
{
|
|
duy@4703
|
213 |
/// use best throughput rate
|
|
duy@4703
|
214 |
if( m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
|
|
duy@4703
|
215 |
{
|
|
duy@4703
|
216 |
; ///< there's still a few retries left
|
|
duy@4703
|
217 |
}
|
|
duy@4703
|
218 |
|
|
duy@4703
|
219 |
/// use second best throughput rate
|
|
duy@4703
|
220 |
else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
221 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount))
|
|
duy@4703
|
222 |
{
|
|
duy@4703
|
223 |
m_txrate = m_maxTpRate2;
|
|
duy@4703
|
224 |
}
|
|
duy@4703
|
225 |
|
|
duy@4703
|
226 |
/// use best probability rate
|
|
duy@4703
|
227 |
else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
228 |
m_minstrelTable[m_maxTpRate2].adjustedRetryCount +
|
|
duy@4703
|
229 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount))
|
|
duy@4703
|
230 |
{
|
|
duy@4703
|
231 |
m_txrate = m_maxProbRate;
|
|
duy@4703
|
232 |
}
|
|
duy@4703
|
233 |
|
|
duy@4703
|
234 |
/// use lowest base rate
|
|
duy@4703
|
235 |
else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
236 |
m_minstrelTable[m_maxTpRate2].adjustedRetryCount +
|
|
duy@4703
|
237 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount))
|
|
duy@4703
|
238 |
{
|
|
duy@4703
|
239 |
m_txrate = 0;
|
|
duy@4703
|
240 |
}
|
|
duy@4703
|
241 |
}
|
|
duy@4703
|
242 |
|
|
duy@4703
|
243 |
/// for look-around rate, we're currently sampling random rates
|
|
duy@4703
|
244 |
else
|
|
duy@4703
|
245 |
{
|
|
duy@4703
|
246 |
/// current sampling rate is slower than the current best rate
|
|
duy@4703
|
247 |
if (m_sampleRateSlower)
|
|
duy@4703
|
248 |
{
|
|
duy@4703
|
249 |
/// use best throughput rate
|
|
duy@4703
|
250 |
if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
|
|
duy@4703
|
251 |
{
|
|
duy@4703
|
252 |
; ///< there are a few retries left
|
|
duy@4703
|
253 |
}
|
|
duy@4703
|
254 |
|
|
duy@4703
|
255 |
/// use random rate
|
|
duy@4703
|
256 |
else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
257 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount))
|
|
duy@4703
|
258 |
{
|
|
duy@4703
|
259 |
m_txrate = m_sampleRate;
|
|
duy@4703
|
260 |
}
|
|
duy@4703
|
261 |
|
|
duy@4703
|
262 |
/// use max probability rate
|
|
duy@4703
|
263 |
else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
264 |
m_minstrelTable[m_sampleRate].adjustedRetryCount +
|
|
duy@4703
|
265 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount ))
|
|
duy@4703
|
266 |
{
|
|
duy@4703
|
267 |
m_txrate = m_maxProbRate;
|
|
duy@4703
|
268 |
}
|
|
duy@4703
|
269 |
|
|
duy@4703
|
270 |
/// use lowest base rate
|
|
duy@4703
|
271 |
else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
272 |
m_minstrelTable[m_sampleRate].adjustedRetryCount +
|
|
duy@4703
|
273 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount))
|
|
duy@4703
|
274 |
{
|
|
duy@4703
|
275 |
m_txrate = 0;
|
|
duy@4703
|
276 |
}
|
|
duy@4703
|
277 |
}
|
|
duy@4703
|
278 |
|
|
duy@4703
|
279 |
/// current sampling rate is better than current best rate
|
|
duy@4703
|
280 |
else
|
|
duy@4703
|
281 |
{
|
|
duy@4703
|
282 |
/// use random rate
|
|
duy@4703
|
283 |
if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
|
|
duy@4703
|
284 |
{
|
|
duy@4703
|
285 |
; ///< keep using it
|
|
duy@4703
|
286 |
}
|
|
duy@4703
|
287 |
|
|
duy@4703
|
288 |
/// use the best rate
|
|
duy@4703
|
289 |
else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
290 |
m_minstrelTable[m_sampleRate].adjustedRetryCount)
|
|
duy@4703
|
291 |
{
|
|
duy@4703
|
292 |
m_txrate = m_maxTpRate;
|
|
duy@4703
|
293 |
}
|
|
duy@4703
|
294 |
|
|
duy@4703
|
295 |
/// use the best probability rate
|
|
duy@4703
|
296 |
else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
297 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount +
|
|
duy@4703
|
298 |
m_minstrelTable[m_sampleRate].adjustedRetryCount)
|
|
duy@4703
|
299 |
{
|
|
duy@4703
|
300 |
m_txrate = m_maxProbRate;
|
|
duy@4703
|
301 |
}
|
|
duy@4703
|
302 |
|
|
duy@4703
|
303 |
/// use the lowest base rate
|
|
duy@4703
|
304 |
else if (m_longRetry > m_minstrelTable[m_txrate].adjustedRetryCount +
|
|
duy@4703
|
305 |
m_minstrelTable[m_maxTpRate].adjustedRetryCount +
|
|
duy@4703
|
306 |
m_minstrelTable[m_sampleRate].adjustedRetryCount)
|
|
duy@4703
|
307 |
{
|
|
duy@4703
|
308 |
m_txrate = 0;
|
|
duy@4703
|
309 |
}
|
|
duy@4703
|
310 |
}
|
|
duy@4703
|
311 |
}
|
|
duy@4703
|
312 |
}
|
|
duy@4703
|
313 |
|
|
duy@4703
|
314 |
void
|
|
duy@4703
|
315 |
MinstrelWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
|
|
duy@4703
|
316 |
{
|
|
duy@4703
|
317 |
m_isSampling = false;
|
|
duy@4703
|
318 |
m_sampleRateSlower=false;
|
|
duy@4703
|
319 |
|
|
duy@4703
|
320 |
CheckInit ();
|
|
duy@4703
|
321 |
|
|
duy@4703
|
322 |
m_minstrelTable[m_txrate].numRateSuccess++;
|
|
duy@4703
|
323 |
m_minstrelTable[m_txrate].numRateAttempt++;
|
|
duy@4703
|
324 |
|
|
duy@4703
|
325 |
UpdateRetry ();
|
|
duy@4703
|
326 |
|
|
duy@4703
|
327 |
m_minstrelTable[m_txrate].numRateAttempt += m_retry;
|
|
duy@4703
|
328 |
m_packetCount++;
|
|
duy@4703
|
329 |
|
|
duy@4703
|
330 |
if (GetNSupportedModes () >= 1)
|
|
duy@4703
|
331 |
{
|
|
duy@4703
|
332 |
m_txrate = FindRate ();
|
|
duy@4703
|
333 |
}
|
|
duy@4703
|
334 |
}
|
|
duy@4703
|
335 |
|
|
duy@4703
|
336 |
void
|
|
duy@4703
|
337 |
MinstrelWifiRemoteStation::DoReportFinalDataFailed (void)
|
|
duy@4703
|
338 |
{
|
|
duy@4703
|
339 |
NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << m_txrate);
|
|
duy@4703
|
340 |
|
|
duy@4703
|
341 |
m_isSampling = false;
|
|
duy@4703
|
342 |
m_sampleRateSlower=false;
|
|
duy@4703
|
343 |
|
|
duy@4703
|
344 |
UpdateRetry ();
|
|
duy@4703
|
345 |
|
|
duy@4703
|
346 |
m_minstrelTable[m_txrate].numRateAttempt += m_retry;
|
|
duy@4703
|
347 |
m_err++;
|
|
duy@4703
|
348 |
|
|
duy@4703
|
349 |
if (GetNSupportedModes () >= 1)
|
|
duy@4703
|
350 |
{
|
|
duy@4703
|
351 |
m_txrate = FindRate ();
|
|
duy@4703
|
352 |
}
|
|
duy@4703
|
353 |
}
|
|
duy@4703
|
354 |
|
|
duy@4703
|
355 |
void
|
|
duy@4703
|
356 |
MinstrelWifiRemoteStation::UpdateRetry (void)
|
|
duy@4703
|
357 |
{
|
|
duy@4703
|
358 |
m_retry = m_shortRetry + m_longRetry;
|
|
duy@4703
|
359 |
m_shortRetry = 0;
|
|
duy@4703
|
360 |
m_longRetry = 0;
|
|
duy@4703
|
361 |
}
|
|
duy@4703
|
362 |
|
|
duy@4703
|
363 |
Ptr<WifiRemoteStationManager>
|
|
duy@4703
|
364 |
MinstrelWifiRemoteStation::GetManager (void) const
|
|
duy@4703
|
365 |
{
|
|
duy@4703
|
366 |
return m_stations;
|
|
duy@4703
|
367 |
}
|
|
duy@4703
|
368 |
|
|
duy@4703
|
369 |
WifiMode
|
|
duy@4703
|
370 |
MinstrelWifiRemoteStation::DoGetDataMode (uint32_t size)
|
|
duy@4703
|
371 |
{
|
|
duy@4703
|
372 |
UpdateStats ();
|
|
duy@4703
|
373 |
if (!m_initialized)
|
|
duy@4703
|
374 |
{
|
|
duy@4703
|
375 |
CheckInit ();
|
|
duy@4703
|
376 |
|
|
duy@4703
|
377 |
/// start the rate at half way
|
|
duy@4703
|
378 |
m_txrate = GetNSupportedModes () / 2;
|
|
duy@4703
|
379 |
}
|
|
duy@4703
|
380 |
return GetSupportedMode (m_txrate);
|
|
duy@4703
|
381 |
}
|
|
duy@4703
|
382 |
|
|
duy@4703
|
383 |
WifiMode
|
|
duy@4703
|
384 |
MinstrelWifiRemoteStation::DoGetRtsMode (void)
|
|
duy@4703
|
385 |
{
|
|
duy@4703
|
386 |
NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << m_txrate);
|
|
duy@4703
|
387 |
|
|
duy@4703
|
388 |
UpdateStats ();
|
|
duy@4703
|
389 |
return GetSupportedMode (0);
|
|
duy@4703
|
390 |
}
|
|
duy@4703
|
391 |
|
|
duy@4703
|
392 |
uint32_t
|
|
duy@4703
|
393 |
MinstrelWifiRemoteStation::GetNextSample ()
|
|
duy@4703
|
394 |
{
|
|
duy@4703
|
395 |
uint32_t bitrate;
|
|
duy@4703
|
396 |
bitrate = m_sampleTable[m_index][m_col];
|
|
duy@4703
|
397 |
m_index++;
|
|
duy@4703
|
398 |
|
|
duy@4703
|
399 |
/// bookeeping for m_index and m_col variables
|
|
duy@4703
|
400 |
if (m_index > (GetNSupportedModes () -2))
|
|
duy@4703
|
401 |
{
|
|
duy@4703
|
402 |
m_index =0;
|
|
duy@4703
|
403 |
m_col++;
|
|
duy@4703
|
404 |
if (m_col >= m_stations->m_sampleCol)
|
|
duy@4703
|
405 |
{
|
|
duy@4703
|
406 |
m_col = 0;
|
|
duy@4703
|
407 |
}
|
|
duy@4703
|
408 |
}
|
|
duy@4703
|
409 |
return bitrate;
|
|
duy@4703
|
410 |
}
|
|
duy@4703
|
411 |
|
|
duy@4703
|
412 |
uint32_t
|
|
duy@4703
|
413 |
MinstrelWifiRemoteStation::FindRate ()
|
|
duy@4703
|
414 |
{
|
|
duy@4703
|
415 |
NS_LOG_DEBUG ("FindRate " << "packet=" << m_packetCount );
|
|
duy@4703
|
416 |
|
|
duy@4703
|
417 |
if ((m_sampleCount + m_packetCount) == 0)
|
|
duy@4703
|
418 |
{
|
|
duy@4703
|
419 |
return 0;
|
|
duy@4703
|
420 |
}
|
|
duy@4703
|
421 |
|
|
duy@4703
|
422 |
|
|
duy@4703
|
423 |
uint32_t idx;
|
|
duy@4703
|
424 |
|
|
duy@4703
|
425 |
/// for determining when to try a sample rate
|
|
duy@4703
|
426 |
UniformVariable coinFlip (0, 100);
|
|
duy@4703
|
427 |
|
|
duy@4703
|
428 |
/**
|
|
duy@4703
|
429 |
* if we are below the target of look around rate percentage, look around
|
|
duy@4703
|
430 |
* note: do it randomly by flipping a coin instead sampling
|
|
duy@4703
|
431 |
* all at once until it reaches the look around rate
|
|
duy@4703
|
432 |
*/
|
|
duy@4703
|
433 |
if ( (((100* m_sampleCount) / (m_sampleCount + m_packetCount )) < m_stations->m_lookAroundRate) &&
|
|
duy@4703
|
434 |
((int)coinFlip.GetValue ()) % 2 == 1 )
|
|
duy@4703
|
435 |
{
|
|
duy@4703
|
436 |
|
|
duy@4703
|
437 |
/// now go through the table and find an index rate
|
|
duy@4703
|
438 |
idx = GetNextSample ();
|
|
duy@4703
|
439 |
|
|
duy@4703
|
440 |
|
|
duy@4703
|
441 |
/**
|
|
duy@4703
|
442 |
* This if condition is used to make sure that we don't need to use
|
|
duy@4703
|
443 |
* the sample rate it is the same as our current rate
|
|
duy@4703
|
444 |
*/
|
|
duy@4703
|
445 |
if (idx != m_maxTpRate && idx != m_txrate)
|
|
duy@4703
|
446 |
{
|
|
duy@4703
|
447 |
|
|
duy@4703
|
448 |
/// start sample count
|
|
duy@4703
|
449 |
m_sampleCount++;
|
|
duy@4703
|
450 |
|
|
duy@4703
|
451 |
/// set flag that we are currently sampling
|
|
duy@4703
|
452 |
m_isSampling = true;
|
|
duy@4703
|
453 |
|
|
duy@4703
|
454 |
/// bookeeping for resetting stuff
|
|
duy@4703
|
455 |
if (m_packetCount >= 10000)
|
|
duy@4703
|
456 |
{
|
|
duy@4703
|
457 |
m_sampleCount = 0;
|
|
duy@4703
|
458 |
m_packetCount = 0;
|
|
duy@4703
|
459 |
}
|
|
duy@4703
|
460 |
|
|
duy@4703
|
461 |
/// error check
|
|
duy@4703
|
462 |
if (idx >= GetNSupportedModes () || idx < 0 )
|
|
duy@4703
|
463 |
{
|
|
duy@4703
|
464 |
NS_LOG_DEBUG ("ALERT!!! ERROR");
|
|
duy@4703
|
465 |
}
|
|
duy@4703
|
466 |
|
|
duy@4703
|
467 |
/// set the rate that we're currently sampling
|
|
duy@4703
|
468 |
m_sampleRate = idx;
|
|
duy@4703
|
469 |
|
|
duy@4703
|
470 |
if (m_sampleRate == m_maxTpRate)
|
|
duy@4703
|
471 |
{
|
|
duy@4703
|
472 |
m_sampleRate = m_maxTpRate2;
|
|
duy@4703
|
473 |
}
|
|
duy@4703
|
474 |
|
|
duy@4703
|
475 |
/// is this rate slower than the current best rate
|
|
duy@4703
|
476 |
m_sampleRateSlower = (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[m_maxTpRate].perfectTxTime);
|
|
duy@4703
|
477 |
|
|
duy@4703
|
478 |
/// using the best rate instead
|
|
duy@4703
|
479 |
if (m_sampleRateSlower)
|
|
duy@4703
|
480 |
{
|
|
duy@4703
|
481 |
idx = m_maxTpRate;
|
|
duy@4703
|
482 |
}
|
|
duy@4703
|
483 |
}
|
|
duy@4703
|
484 |
|
|
duy@4703
|
485 |
}
|
|
duy@4703
|
486 |
|
|
duy@4703
|
487 |
/// continue using the best rate
|
|
duy@4703
|
488 |
else
|
|
duy@4703
|
489 |
{
|
|
duy@4703
|
490 |
idx = m_maxTpRate;
|
|
duy@4703
|
491 |
}
|
|
duy@4703
|
492 |
|
|
duy@4703
|
493 |
|
|
duy@4703
|
494 |
NS_LOG_DEBUG ("FindRate " << "sample rate=" << idx);
|
|
duy@4703
|
495 |
|
|
duy@4703
|
496 |
return idx;
|
|
duy@4703
|
497 |
}
|
|
duy@4703
|
498 |
|
|
duy@4703
|
499 |
void
|
|
duy@4703
|
500 |
MinstrelWifiRemoteStation::UpdateStats ()
|
|
duy@4703
|
501 |
{
|
|
duy@4703
|
502 |
if (Simulator::Now () < m_nextStatsUpdate)
|
|
duy@4703
|
503 |
{
|
|
duy@4703
|
504 |
return;
|
|
duy@4703
|
505 |
}
|
|
duy@4703
|
506 |
|
|
duy@4703
|
507 |
NS_LOG_DEBUG ("Updating stats="<<this);
|
|
duy@4703
|
508 |
|
|
duy@4703
|
509 |
m_nextStatsUpdate = Simulator::Now () + m_stations->m_updateStats;
|
|
duy@4703
|
510 |
|
|
duy@4703
|
511 |
Time txTime;
|
|
duy@4703
|
512 |
uint32_t tempProb;
|
|
duy@4703
|
513 |
|
|
duy@4703
|
514 |
for (uint32_t i =0; i < GetNSupportedModes (); i++)
|
|
duy@4703
|
515 |
{
|
|
duy@4703
|
516 |
|
|
duy@4703
|
517 |
/// calculate the perfect tx time for this rate
|
|
duy@4703
|
518 |
txTime = m_minstrelTable[i].perfectTxTime;
|
|
duy@4703
|
519 |
|
|
duy@4703
|
520 |
/// just for initialization
|
|
duy@4703
|
521 |
if (txTime.GetMicroSeconds () == 0)
|
|
duy@4703
|
522 |
{
|
|
duy@4703
|
523 |
txTime = Seconds (1);
|
|
duy@4703
|
524 |
}
|
|
duy@4703
|
525 |
|
|
duy@4703
|
526 |
NS_LOG_DEBUG ("m_txrate=" << m_txrate << "\t attempt=" << m_minstrelTable[i].numRateAttempt << "\t success=" << m_minstrelTable[i].numRateSuccess);
|
|
duy@4703
|
527 |
|
|
duy@4703
|
528 |
/// if we've attempted something
|
|
duy@4703
|
529 |
if (m_minstrelTable[i].numRateAttempt)
|
|
duy@4703
|
530 |
{
|
|
duy@4703
|
531 |
/**
|
|
duy@4703
|
532 |
* calculate the probability of success
|
|
duy@4703
|
533 |
* assume probability scales from 0 to 18000
|
|
duy@4703
|
534 |
*/
|
|
duy@4703
|
535 |
tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt;
|
|
duy@4703
|
536 |
|
|
duy@4703
|
537 |
/// bookeeping
|
|
duy@4703
|
538 |
m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess;
|
|
duy@4703
|
539 |
m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt;
|
|
duy@4703
|
540 |
m_minstrelTable[i].prob = tempProb;
|
|
duy@4703
|
541 |
|
|
duy@4703
|
542 |
/// ewma probability
|
|
duy@4703
|
543 |
tempProb = ((tempProb * (100 - m_stations->m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_stations->m_ewmaLevel) )/100;
|
|
duy@4703
|
544 |
|
|
duy@4703
|
545 |
m_minstrelTable[i].ewmaProb = tempProb;
|
|
duy@4703
|
546 |
|
|
duy@4703
|
547 |
/// calculating throughput
|
|
duy@4703
|
548 |
m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds());
|
|
duy@4703
|
549 |
|
|
duy@4703
|
550 |
}
|
|
duy@4703
|
551 |
|
|
duy@4703
|
552 |
/// bookeeping
|
|
duy@4703
|
553 |
m_minstrelTable[i].prevNumRateAttempt= m_minstrelTable[i].numRateAttempt;
|
|
duy@4703
|
554 |
m_minstrelTable[i].prevNumRateSuccess = m_minstrelTable[i].numRateSuccess;
|
|
duy@4703
|
555 |
m_minstrelTable[i].numRateSuccess = 0;
|
|
duy@4703
|
556 |
m_minstrelTable[i].numRateAttempt = 0;
|
|
duy@4703
|
557 |
|
|
duy@4703
|
558 |
/// Sample less often below 10% and above 95% of success
|
|
duy@4703
|
559 |
if ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800))
|
|
duy@4703
|
560 |
{
|
|
duy@4703
|
561 |
/**
|
|
duy@4703
|
562 |
* retry count denotes the number of retries permitted for each rate
|
|
duy@4703
|
563 |
* # retry_count/2
|
|
duy@4703
|
564 |
*/
|
|
duy@4703
|
565 |
m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1;
|
|
duy@4703
|
566 |
if (m_minstrelTable[i].adjustedRetryCount > 2)
|
|
duy@4703
|
567 |
{
|
|
duy@4703
|
568 |
m_minstrelTable[i].adjustedRetryCount = 2 ;
|
|
duy@4703
|
569 |
}
|
|
duy@4703
|
570 |
}
|
|
duy@4703
|
571 |
else
|
|
duy@4703
|
572 |
{
|
|
duy@4703
|
573 |
m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount;
|
|
duy@4703
|
574 |
}
|
|
duy@4703
|
575 |
|
|
duy@4703
|
576 |
/// if it's 0 allow one retry limit
|
|
duy@4703
|
577 |
if (m_minstrelTable[i].adjustedRetryCount == 0)
|
|
duy@4703
|
578 |
{
|
|
duy@4703
|
579 |
m_minstrelTable[i].adjustedRetryCount = 1;
|
|
duy@4703
|
580 |
}
|
|
duy@4703
|
581 |
}
|
|
duy@4703
|
582 |
|
|
duy@4703
|
583 |
|
|
duy@4703
|
584 |
uint32_t max_prob = 0, index_max_prob =0, max_tp =0, index_max_tp=0, index_max_tp2=0;
|
|
duy@4703
|
585 |
|
|
duy@4703
|
586 |
/// go find max throughput, second maximum throughput, high probability succ
|
|
duy@4703
|
587 |
for (uint32_t i =0; i < GetNSupportedModes (); i++)
|
|
duy@4703
|
588 |
{
|
|
duy@4703
|
589 |
NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput << "\n ewma" << m_minstrelTable[i].ewmaProb);
|
|
duy@4703
|
590 |
|
|
duy@4703
|
591 |
if (max_tp < m_minstrelTable[i].throughput)
|
|
duy@4703
|
592 |
{
|
|
duy@4703
|
593 |
index_max_tp = i;
|
|
duy@4703
|
594 |
max_tp = m_minstrelTable[i].throughput;
|
|
duy@4703
|
595 |
}
|
|
duy@4703
|
596 |
|
|
duy@4703
|
597 |
if (max_prob < m_minstrelTable[i].ewmaProb)
|
|
duy@4703
|
598 |
{
|
|
duy@4703
|
599 |
index_max_prob = i;
|
|
duy@4703
|
600 |
max_prob = m_minstrelTable[i].ewmaProb;
|
|
duy@4703
|
601 |
}
|
|
duy@4703
|
602 |
}
|
|
duy@4703
|
603 |
|
|
duy@4703
|
604 |
|
|
duy@4703
|
605 |
max_tp = 0;
|
|
duy@4703
|
606 |
/// find the second highest max
|
|
duy@4703
|
607 |
for (uint32_t i =0; i < GetNSupportedModes (); i++)
|
|
duy@4703
|
608 |
{
|
|
duy@4703
|
609 |
if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput))
|
|
duy@4703
|
610 |
{
|
|
duy@4703
|
611 |
index_max_tp2 = i;
|
|
duy@4703
|
612 |
max_tp = m_minstrelTable[i].throughput;
|
|
duy@4703
|
613 |
}
|
|
duy@4703
|
614 |
}
|
|
duy@4703
|
615 |
|
|
duy@4703
|
616 |
m_maxTpRate = index_max_tp;
|
|
duy@4703
|
617 |
m_maxTpRate2 = index_max_tp2;
|
|
duy@4703
|
618 |
m_maxProbRate = index_max_prob;
|
|
duy@4703
|
619 |
m_currentRate = index_max_tp;
|
|
duy@4703
|
620 |
|
|
duy@4703
|
621 |
if (index_max_tp > m_txrate)
|
|
duy@4703
|
622 |
{
|
|
duy@4703
|
623 |
m_txrate= index_max_tp;
|
|
duy@4703
|
624 |
}
|
|
duy@4703
|
625 |
|
|
duy@4703
|
626 |
NS_LOG_DEBUG ("max tp="<< index_max_tp << "\nmax tp2="<< index_max_tp2<< "\nmax prob="<< index_max_prob);
|
|
duy@4703
|
627 |
|
|
duy@4703
|
628 |
/// reset it
|
|
duy@4703
|
629 |
RateInit ();
|
|
duy@4703
|
630 |
}
|
|
duy@4703
|
631 |
|
|
duy@4703
|
632 |
void
|
|
duy@4703
|
633 |
MinstrelWifiRemoteStation::RateInit ()
|
|
duy@4703
|
634 |
{
|
|
duy@4703
|
635 |
NS_LOG_DEBUG ("RateInit="<<this);
|
|
duy@4703
|
636 |
|
|
duy@4703
|
637 |
for (uint32_t i = 0; i < GetNSupportedModes (); i++)
|
|
duy@4703
|
638 |
{
|
|
duy@4703
|
639 |
m_minstrelTable[i].numRateAttempt = 0;
|
|
duy@4703
|
640 |
m_minstrelTable[i].numRateSuccess = 0;
|
|
duy@4703
|
641 |
m_minstrelTable[i].prob = 0;
|
|
duy@4703
|
642 |
m_minstrelTable[i].ewmaProb = 0;
|
|
duy@4703
|
643 |
m_minstrelTable[i].prevNumRateAttempt = 0;
|
|
duy@4703
|
644 |
m_minstrelTable[i].prevNumRateSuccess = 0;
|
|
duy@4703
|
645 |
m_minstrelTable[i].successHist = 0;
|
|
duy@4703
|
646 |
m_minstrelTable[i].attemptHist = 0;
|
|
duy@4703
|
647 |
m_minstrelTable[i].throughput = 0;
|
|
duy@4703
|
648 |
m_minstrelTable[i].perfectTxTime = m_stations->GetCalcTxTime (GetSupportedMode (i));
|
|
duy@4703
|
649 |
m_minstrelTable[i].retryCount =1;
|
|
duy@4703
|
650 |
m_minstrelTable[i].adjustedRetryCount =1;
|
|
duy@4703
|
651 |
}
|
|
duy@4703
|
652 |
}
|
|
duy@4703
|
653 |
|
|
duy@4703
|
654 |
void
|
|
duy@4703
|
655 |
MinstrelWifiRemoteStation::InitSampleTable ()
|
|
duy@4703
|
656 |
{
|
|
duy@4703
|
657 |
NS_LOG_DEBUG ("InitSampleTable="<<this);
|
|
duy@4703
|
658 |
|
|
duy@4703
|
659 |
m_col = m_index = 0;
|
|
duy@4703
|
660 |
|
|
duy@4703
|
661 |
/// for off-seting to make rates fall between 0 and numrates
|
|
duy@4703
|
662 |
uint32_t numSampleRates= GetNSupportedModes () - 1;
|
|
duy@4703
|
663 |
|
|
duy@4703
|
664 |
uint32_t newIndex;
|
|
duy@4703
|
665 |
for (uint32_t col = 0; col < m_stations->m_sampleCol; col++)
|
|
duy@4703
|
666 |
{
|
|
duy@4703
|
667 |
for (uint32_t i = 0; i < numSampleRates; i++ )
|
|
duy@4703
|
668 |
{
|
|
duy@4703
|
669 |
|
|
duy@4703
|
670 |
/**
|
|
duy@4703
|
671 |
* The next two lines basically tries to generate a random number
|
|
duy@4703
|
672 |
* between 0 and the number of available rates
|
|
duy@4703
|
673 |
*/
|
|
duy@4703
|
674 |
UniformVariable uv (0, numSampleRates);
|
|
duy@4703
|
675 |
newIndex = (i + (uint32_t)uv.GetValue ()) % numSampleRates;
|
|
duy@4703
|
676 |
|
|
duy@4703
|
677 |
/// this loop is used for filling in other uninitilized places
|
|
duy@4703
|
678 |
while (m_sampleTable[newIndex][col] != 0)
|
|
duy@4703
|
679 |
{
|
|
duy@4703
|
680 |
newIndex = (newIndex + 1)%GetNSupportedModes ();
|
|
duy@4703
|
681 |
}
|
|
duy@4703
|
682 |
m_sampleTable[newIndex][col] = i+1;
|
|
duy@4703
|
683 |
|
|
duy@4703
|
684 |
}
|
|
duy@4703
|
685 |
}
|
|
duy@4703
|
686 |
}
|
|
duy@4703
|
687 |
|
|
duy@4703
|
688 |
void
|
|
duy@4703
|
689 |
MinstrelWifiRemoteStation::PrintSampleTable ()
|
|
duy@4703
|
690 |
{
|
|
duy@4703
|
691 |
NS_LOG_DEBUG ("PrintSampleTable="<<this );
|
|
duy@4703
|
692 |
|
|
duy@4703
|
693 |
uint32_t numSampleRates= GetNSupportedModes ();
|
|
duy@4703
|
694 |
for (uint32_t i=0; i < numSampleRates; i++)
|
|
duy@4703
|
695 |
{
|
|
duy@4703
|
696 |
for (uint32_t j=0; j < m_stations->m_sampleCol; j++)
|
|
duy@4703
|
697 |
{
|
|
duy@4703
|
698 |
std::cout << m_sampleTable[i][j] << "\t";
|
|
duy@4703
|
699 |
}
|
|
duy@4703
|
700 |
std::cout << std::endl;
|
|
duy@4703
|
701 |
}
|
|
duy@4703
|
702 |
}
|
|
duy@4703
|
703 |
|
|
duy@4703
|
704 |
void
|
|
duy@4703
|
705 |
MinstrelWifiRemoteStation::PrintTable ()
|
|
duy@4703
|
706 |
{
|
|
duy@4703
|
707 |
NS_LOG_DEBUG ("PrintTable="<<this);
|
|
duy@4703
|
708 |
|
|
duy@4703
|
709 |
for (uint32_t i=0; i < GetNSupportedModes (); i++)
|
|
duy@4703
|
710 |
{
|
|
duy@4703
|
711 |
std::cout << "index(" << i << ") = " << m_minstrelTable[i].perfectTxTime<< "\n";
|
|
duy@4703
|
712 |
}
|
|
duy@4703
|
713 |
}
|
|
duy@4703
|
714 |
|
|
duy@4703
|
715 |
} //namespace ns3
|
|
duy@4703
|
716 |
|
|
duy@4703
|
717 |
|
|
duy@4703
|
718 |
|
|
duy@4703
|
719 |
|
|
duy@4703
|
720 |
|