|
|
| 36 |
struct IdealWifiRemoteStation : public WifiRemoteStation |
36 |
struct IdealWifiRemoteStation : public WifiRemoteStation |
| 37 |
{ |
37 |
{ |
| 38 |
double m_lastSnrObserved; //!< SNR of most recently reported packet sent to the remote station |
38 |
double m_lastSnrObserved; //!< SNR of most recently reported packet sent to the remote station |
| 39 |
double m_lastSnrCached; //!< SNR most recently used to select a rate |
39 |
double m_lastSnrUsed; //!< SNR most recently used to select a rate |
| 40 |
double m_nss; //!< SNR most recently used to select a rate |
40 |
uint64_t m_lastRate; //!< last data rate used towards the station |
|
|
41 |
double m_nss; //!< nss most recently used towards the station |
| 41 |
WifiMode m_lastMode; //!< Mode most recently used to the remote station |
42 |
WifiMode m_lastMode; //!< Mode most recently used to the remote station |
| 42 |
}; |
43 |
}; |
| 43 |
|
44 |
|
|
|
| 57 |
DoubleValue (1e-5), |
58 |
DoubleValue (1e-5), |
| 58 |
MakeDoubleAccessor (&IdealWifiManager::m_ber), |
59 |
MakeDoubleAccessor (&IdealWifiManager::m_ber), |
| 59 |
MakeDoubleChecker<double> ()) |
60 |
MakeDoubleChecker<double> ()) |
| 60 |
.AddTraceSource ("Rate", |
61 |
.AddTraceSource ("RateChange", |
| 61 |
"Traced value for rate changes (b/s)", |
62 |
"The transmission rate has changed", |
| 62 |
MakeTraceSourceAccessor (&IdealWifiManager::m_currentRate), |
63 |
MakeTraceSourceAccessor (&IdealWifiManager::m_rateChange), |
| 63 |
"ns3::TracedValueCallback::Uint64") |
64 |
"ns3::IdealWifiManager::RateChangeTracedCallback") |
| 64 |
; |
65 |
; |
| 65 |
return tid; |
66 |
return tid; |
| 66 |
} |
67 |
} |
| 67 |
|
68 |
|
| 68 |
IdealWifiManager::IdealWifiManager () |
69 |
IdealWifiManager::IdealWifiManager () |
| 69 |
: m_currentRate (0) |
|
|
| 70 |
{ |
70 |
{ |
| 71 |
} |
71 |
} |
| 72 |
|
72 |
|
|
|
| 118 |
" short GI " << GetPhy ()->GetGuardInterval ()); |
118 |
" short GI " << GetPhy ()->GetGuardInterval ()); |
| 119 |
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); |
119 |
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); |
| 120 |
} |
120 |
} |
| 121 |
// Add all Ht and Vht MCSes |
121 |
// Add all supported Ht and Vht MCSes |
| 122 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
122 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
| 123 |
if (HasVhtSupported () == true || HasHtSupported () == true ) |
123 |
if (HasVhtSupported () == true || HasHtSupported () == true ) |
| 124 |
{ |
124 |
{ |
|
|
| 126 |
for (uint32_t i = 0; i < nModes; i++) |
126 |
for (uint32_t i = 0; i < nModes; i++) |
| 127 |
{ |
127 |
{ |
| 128 |
mode = GetPhy ()->GetMcs (i); |
128 |
mode = GetPhy ()->GetMcs (i); |
| 129 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) |
129 |
txVector.SetMode (mode); |
|
|
130 |
for (uint8_t j = 1; j <= GetPhy ()->GetSupportedTxSpatialStreams (); j++) |
| 130 |
{ |
131 |
{ |
| 131 |
//derive NSS from the Mcs index |
132 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) |
| 132 |
nss = (mode.GetMcsValue () / 8) + 1; |
133 |
{ |
|
|
134 |
//derive NSS from the Mcs index |
| 135 |
nss = (mode.GetMcsValue () / 8) + 1; |
| 136 |
if (nss != j) |
| 137 |
{ |
| 138 |
continue; |
| 139 |
} |
| 140 |
} |
| 141 |
else |
| 142 |
{ |
| 143 |
nss = j; |
| 144 |
} |
| 145 |
txVector.SetNss (nss); |
| 146 |
if (IsSupportedTxVector (txVector) && WifiPhy::IsValidTxVector (txVector)) |
| 147 |
{ |
| 148 |
NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () << |
| 149 |
" channel width " << GetPhy ()->GetChannelWidth () << |
| 150 |
" nss " << (uint16_t) nss << |
| 151 |
" short GI " << GetPhy ()->GetGuardInterval ()); |
| 152 |
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); |
| 153 |
} |
| 154 |
else |
| 155 |
{ |
| 156 |
NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << " as unsupported"); |
| 157 |
} |
| 133 |
} |
158 |
} |
| 134 |
else |
|
|
| 135 |
{ |
| 136 |
nss = GetPhy ()->GetSupportedTxSpatialStreams (); |
| 137 |
} |
| 138 |
NS_LOG_DEBUG ("Initialize, adding mode = " << mode.GetUniqueName () << |
| 139 |
" channel width " << GetPhy ()->GetChannelWidth () << |
| 140 |
" nss " << (uint16_t) nss << |
| 141 |
" short GI " << GetPhy ()->GetGuardInterval ()); |
| 142 |
NS_LOG_DEBUG ("In SetupPhy, adding mode = " << mode.GetUniqueName ()); |
| 143 |
txVector.SetNss (nss); |
| 144 |
txVector.SetMode (mode); |
| 145 |
AddSnrThreshold (txVector, GetPhy ()->CalculateSnr (txVector, m_ber)); |
| 146 |
} |
159 |
} |
| 147 |
} |
160 |
} |
| 148 |
} |
161 |
} |
|
|
| 184 |
NS_LOG_FUNCTION (this); |
197 |
NS_LOG_FUNCTION (this); |
| 185 |
IdealWifiRemoteStation *station = new IdealWifiRemoteStation (); |
198 |
IdealWifiRemoteStation *station = new IdealWifiRemoteStation (); |
| 186 |
station->m_lastSnrObserved = 0.0; |
199 |
station->m_lastSnrObserved = 0.0; |
| 187 |
station->m_lastSnrCached = 0.0; |
200 |
station->m_lastSnrUsed = -100.0; |
|
|
201 |
station->m_lastRate = 0; |
| 188 |
station->m_lastMode = GetDefaultMode (); |
202 |
station->m_lastMode = GetDefaultMode (); |
| 189 |
station->m_nss = 1; |
203 |
station->m_nss = 1; |
| 190 |
return station; |
204 |
return station; |
|
|
| 254 |
{ |
268 |
{ |
| 255 |
} |
269 |
} |
| 256 |
|
270 |
|
|
|
271 |
// This check is encapsulated in case any more sophisticated checks |
| 272 |
// for applicability of cached data are added in the future |
| 273 |
bool |
| 274 |
IdealWifiManager::UseCachedDataTxVector (WifiRemoteStation *st) const |
| 275 |
{ |
| 276 |
NS_LOG_FUNCTION (this << st); |
| 277 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 278 |
if (station->m_lastSnrObserved == station->m_lastSnrUsed) |
| 279 |
{ |
| 280 |
return true; |
| 281 |
} |
| 282 |
return false; |
| 283 |
} |
| 284 |
|
| 285 |
void |
| 286 |
IdealWifiManager::UpdateCachedDataTxVector (WifiRemoteStation *st, WifiMode mode, uint8_t nss) |
| 287 |
{ |
| 288 |
NS_LOG_FUNCTION (this << st); |
| 289 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 290 |
NS_LOG_DEBUG ("Mode found; updating cached values for station to " << mode.GetUniqueName () << " snr " << station->m_lastSnrObserved); |
| 291 |
station->m_lastSnrUsed = station->m_lastSnrObserved; |
| 292 |
station->m_lastMode = mode; |
| 293 |
station->m_nss = nss; |
| 294 |
uint64_t dataRate = mode.GetDataRate (GetChannelWidth (station), GetPhy ()->GetGuardInterval (), nss); |
| 295 |
if (station->m_lastRate != dataRate) |
| 296 |
{ |
| 297 |
NS_LOG_DEBUG ("Updated datarate: " << dataRate << " to station " << station->m_state->m_address); |
| 298 |
station->m_lastRate = dataRate; |
| 299 |
m_rateChange (dataRate, station->m_state->m_address); |
| 300 |
} |
| 301 |
} |
| 302 |
|
| 303 |
bool |
| 304 |
IdealWifiManager::DoGetDataTxVectorVht (WifiRemoteStation *st) |
| 305 |
{ |
| 306 |
NS_LOG_FUNCTION (this << st); |
| 307 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 308 |
WifiMode mode; |
| 309 |
uint8_t nss = 1; |
| 310 |
WifiTxVector txVector; |
| 311 |
// channel width and guard interval are not variable within here |
| 312 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
| 313 |
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ()); |
| 314 |
|
| 315 |
// Search within the supported rate set for the mode corresponding |
| 316 |
// to the highest rate with an SNR threshold smaller than the last |
| 317 |
// SNR reported from the remote station |
| 318 |
WifiMode maxMode = GetDefaultMode (); |
| 319 |
uint8_t maxNss = 1; |
| 320 |
uint64_t maxDataRate = 0; |
| 321 |
|
| 322 |
bool found = false; |
| 323 |
for (uint32_t i = 0; i < GetNMcsSupported (station); i++) |
| 324 |
{ |
| 325 |
mode = GetMcsSupported (station, i); |
| 326 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) |
| 327 |
{ |
| 328 |
continue; |
| 329 |
} |
| 330 |
txVector.SetMode (mode); |
| 331 |
// For each VHT mode, we must consider multiple spatial streams |
| 332 |
for (uint8_t j = 1; j <= GetPhy ()->GetSupportedTxSpatialStreams (); j++) |
| 333 |
{ |
| 334 |
txVector.SetNss (j); |
| 335 |
if (WifiPhy::IsValidTxVector (txVector) == false || IsSupportedTxVector (txVector) == false) |
| 336 |
{ |
| 337 |
NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << |
| 338 |
" nss " << (uint16_t) j << " width " << |
| 339 |
txVector.GetChannelWidth()); |
| 340 |
continue; |
| 341 |
} |
| 342 |
// Mode is a candidate |
| 343 |
double threshold = GetSnrThreshold (txVector); |
| 344 |
NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << |
| 345 |
" threshold " << threshold << |
| 346 |
" last snr observed " << |
| 347 |
station->m_lastSnrObserved << " cached " << |
| 348 |
station->m_lastSnrUsed); |
| 349 |
uint64_t candidateRate = mode.GetDataRate (GetPhy ()->GetChannelWidth (), GetPhy ()->GetGuardInterval (), nss); |
| 350 |
// Prefer a mode if its data rate exceeds previous candidate |
| 351 |
if (candidateRate > maxDataRate && threshold < station->m_lastSnrObserved) |
| 352 |
{ |
| 353 |
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << |
| 354 |
" threshold " << threshold << |
| 355 |
" last snr observed " << |
| 356 |
station->m_lastSnrObserved); |
| 357 |
maxMode = mode; |
| 358 |
maxNss = nss; |
| 359 |
maxDataRate = candidateRate; |
| 360 |
found = true; |
| 361 |
} |
| 362 |
} |
| 363 |
} |
| 364 |
if (found) |
| 365 |
{ |
| 366 |
UpdateCachedDataTxVector (st, maxMode, maxNss); |
| 367 |
} |
| 368 |
return found; |
| 369 |
} |
| 370 |
|
| 371 |
bool |
| 372 |
IdealWifiManager::DoGetDataTxVectorHt (WifiRemoteStation *st) |
| 373 |
{ |
| 374 |
NS_LOG_FUNCTION (this << st); |
| 375 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 376 |
WifiMode mode; |
| 377 |
uint8_t nss = 1; |
| 378 |
WifiTxVector txVector; |
| 379 |
// channel width and guard interval are not variable within here |
| 380 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
| 381 |
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ()); |
| 382 |
|
| 383 |
// Search within the supported rate set for the mode corresponding |
| 384 |
// to the highest rate with an SNR threshold smaller than the last |
| 385 |
// SNR reported from the remote station |
| 386 |
WifiMode maxMode = GetDefaultMode (); |
| 387 |
uint8_t maxNss = 1; |
| 388 |
uint64_t maxDataRate = 0; |
| 389 |
|
| 390 |
bool found = false; |
| 391 |
for (uint32_t i = 0; i < GetNMcsSupported (station); i++) |
| 392 |
{ |
| 393 |
mode = GetMcsSupported (station, i); |
| 394 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT) |
| 395 |
{ |
| 396 |
continue; |
| 397 |
} |
| 398 |
txVector.SetMode (mode); |
| 399 |
// For each HT mode, we can derive the nss from the MCS number |
| 400 |
nss = (mode.GetMcsValue () / 8) + 1; |
| 401 |
txVector.SetNss (nss); |
| 402 |
if (WifiPhy::IsValidTxVector (txVector) == false || IsSupportedTxVector (txVector) == false) |
| 403 |
{ |
| 404 |
NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << |
| 405 |
" nss " << (uint16_t) nss << " width " << |
| 406 |
txVector.GetChannelWidth()); |
| 407 |
continue; |
| 408 |
} |
| 409 |
// Mode is a candidate |
| 410 |
double threshold = GetSnrThreshold (txVector); |
| 411 |
NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << |
| 412 |
" threshold " << threshold << " last snr observed " << |
| 413 |
station->m_lastSnrObserved << " cached " << |
| 414 |
station->m_lastSnrUsed); |
| 415 |
uint64_t candidateRate = mode.GetDataRate (GetPhy ()->GetChannelWidth (), GetPhy ()->GetGuardInterval (), nss); |
| 416 |
// Prefer a mode if its data rate exceeds previous candidate |
| 417 |
if (candidateRate > maxDataRate && threshold < station->m_lastSnrObserved) |
| 418 |
{ |
| 419 |
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << |
| 420 |
" threshold " << threshold << " last snr observed " << |
| 421 |
station->m_lastSnrObserved); |
| 422 |
maxMode = mode; |
| 423 |
maxNss = nss; |
| 424 |
maxDataRate = candidateRate; |
| 425 |
found = true; |
| 426 |
} |
| 427 |
} |
| 428 |
if (found) |
| 429 |
{ |
| 430 |
UpdateCachedDataTxVector (st, maxMode, maxNss); |
| 431 |
} |
| 432 |
return found; |
| 433 |
} |
| 434 |
|
| 435 |
bool |
| 436 |
IdealWifiManager::DoGetDataTxVectorLegacy (WifiRemoteStation *st) |
| 437 |
{ |
| 438 |
NS_LOG_FUNCTION (this << st); |
| 439 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 440 |
WifiMode mode; |
| 441 |
uint8_t nss = 1; |
| 442 |
WifiTxVector txVector; |
| 443 |
// channel width and guard interval are not variable within here |
| 444 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
| 445 |
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ()); |
| 446 |
|
| 447 |
// Search within the supported rate set for the mode corresponding |
| 448 |
// to the highest rate with an SNR threshold smaller than the last |
| 449 |
// SNR reported from the remote station |
| 450 |
WifiMode maxMode = GetDefaultMode (); |
| 451 |
uint8_t maxNss = 1; |
| 452 |
uint64_t maxDataRate = 0; |
| 453 |
|
| 454 |
bool found = false; |
| 455 |
for (uint32_t i = 0; i < GetNSupported (station); i++) |
| 456 |
{ |
| 457 |
mode = GetSupported (station, i); |
| 458 |
txVector.SetMode (mode); |
| 459 |
txVector.SetNss (nss); |
| 460 |
txVector.SetChannelWidth (GetChannelWidthForMode (mode)); |
| 461 |
double threshold = GetSnrThreshold (txVector); |
| 462 |
NS_LOG_DEBUG ("mode = " << mode.GetUniqueName () << |
| 463 |
" threshold " << threshold << |
| 464 |
" last snr observed " << |
| 465 |
station->m_lastSnrObserved); |
| 466 |
uint64_t candidateRate = mode.GetDataRate (GetPhy ()->GetChannelWidth (), GetPhy ()->GetGuardInterval (), nss); |
| 467 |
// Prefer a mode if its data rate exceeds previous candidate |
| 468 |
if (candidateRate > maxDataRate && threshold < station->m_lastSnrObserved) |
| 469 |
{ |
| 470 |
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << |
| 471 |
" threshold " << threshold << " last snr observed " << |
| 472 |
station->m_lastSnrObserved); |
| 473 |
maxMode = mode; |
| 474 |
maxNss = nss; |
| 475 |
maxDataRate = candidateRate; |
| 476 |
found = true; |
| 477 |
} |
| 478 |
} |
| 479 |
if (found) |
| 480 |
{ |
| 481 |
UpdateCachedDataTxVector (st, maxMode, maxNss); |
| 482 |
} |
| 483 |
return found; |
| 484 |
} |
| 485 |
|
| 257 |
WifiTxVector |
486 |
WifiTxVector |
| 258 |
IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) |
487 |
IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) |
| 259 |
{ |
488 |
{ |
| 260 |
NS_LOG_FUNCTION (this << st); |
489 |
NS_LOG_FUNCTION (this << st); |
| 261 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
490 |
IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st; |
| 262 |
//We search within the Supported rate set the mode with the |
491 |
|
| 263 |
//highest snr threshold possible which is smaller than m_lastSnr |
492 |
if (UseCachedDataTxVector (st)) |
| 264 |
//to ensure correct packet delivery. |
|
|
| 265 |
double maxThreshold = 0.0; |
| 266 |
WifiMode maxMode = GetDefaultMode (); |
| 267 |
std::vector<WifiTxVector> candidateTxVectors; |
| 268 |
WifiTxVector txVector; |
| 269 |
WifiMode mode; |
| 270 |
uint8_t nss = 1; |
| 271 |
txVector.SetChannelWidth (GetPhy ()->GetChannelWidth ()); |
| 272 |
txVector.SetShortGuardInterval (GetPhy ()->GetGuardInterval ()); |
| 273 |
if (station->m_lastSnrObserved == station->m_lastSnrCached) |
| 274 |
{ |
493 |
{ |
| 275 |
// SNR has not changed, so skip the search and use the last |
494 |
NS_LOG_DEBUG ("Using cached WifiTxVector to station " << station->m_state->m_address); |
| 276 |
// mode selected |
495 |
NS_LOG_DEBUG ("Returning cached mode: " << |
| 277 |
maxMode = station->m_lastMode; |
496 |
station->m_lastMode.GetUniqueName () << |
| 278 |
nss = station->m_nss; |
497 |
" channelWidth: " << GetChannelWidth (station) << |
| 279 |
NS_LOG_DEBUG ("Using cached mode = " << maxMode.GetUniqueName () << |
498 |
" nss " << (uint16_t) station->m_nss << " dataRate: " << |
| 280 |
" last snr observed " << station->m_lastSnrObserved << |
499 |
station->m_lastRate); |
| 281 |
" cached " << station->m_lastSnrCached); |
500 |
return WifiTxVector (station->m_lastMode, GetDefaultTxPowerLevel (), |
|
|
501 |
GetLongRetryCount (station), false, station->m_nss, |
| 502 |
0, GetChannelWidth (station), |
| 503 |
GetAggregation (station), false); |
| 504 |
} |
| 505 |
bool found = false; |
| 506 |
if (HasVhtSupported () == true && GetVhtSupported (st)) |
| 507 |
{ |
| 508 |
NS_LOG_DEBUG ("Searching VHT modes to station " << station->m_state->m_address); |
| 509 |
found = DoGetDataTxVectorVht (st); |
| 510 |
} |
| 511 |
if (!found && HasHtSupported () == true && GetHtSupported (st)) |
| 512 |
{ |
| 513 |
NS_LOG_DEBUG ("Searching HT modes to station " << station->m_state->m_address); |
| 514 |
found = DoGetDataTxVectorHt (st); |
| 515 |
} |
| 516 |
if (!found) |
| 517 |
{ |
| 518 |
NS_LOG_DEBUG ("Searching legacy modes to station " << station->m_state->m_address); |
| 519 |
found = DoGetDataTxVectorLegacy (st); |
| 520 |
} |
| 521 |
if (found) |
| 522 |
{ |
| 523 |
return WifiTxVector (station->m_lastMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, station->m_nss, 0, GetChannelWidth (station), GetAggregation (station), false); |
| 282 |
} |
524 |
} |
| 283 |
else |
525 |
else |
| 284 |
{ |
526 |
{ |
| 285 |
if (HasVhtSupported () == true || HasHtSupported () == true) |
527 |
NS_LOG_DEBUG ("Suitable mode not found; returning default mode"); |
| 286 |
{ |
528 |
return WifiTxVector (GetDefaultMode (), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, GetChannelWidth (station), GetAggregation (station), false); |
| 287 |
for (uint32_t i = 0; i < GetNMcsSupported (station); i++) |
|
|
| 288 |
{ |
| 289 |
mode = GetMcsSupported (station, i); |
| 290 |
txVector.SetMode (mode); |
| 291 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) |
| 292 |
{ |
| 293 |
//derive NSS from the Mcs index |
| 294 |
nss = (mode.GetMcsValue () / 8) + 1; |
| 295 |
} |
| 296 |
else |
| 297 |
{ |
| 298 |
nss = GetPhy ()->GetSupportedTxSpatialStreams (); |
| 299 |
} |
| 300 |
txVector.SetNss (nss); |
| 301 |
if (WifiPhy::IsValidTxVector (txVector) == false) |
| 302 |
{ |
| 303 |
NS_LOG_DEBUG ("Skipping mode " << mode.GetUniqueName () << |
| 304 |
" nss " << nss << " width " << |
| 305 |
txVector.GetChannelWidth()); |
| 306 |
continue; |
| 307 |
} |
| 308 |
double threshold = GetSnrThreshold (txVector); |
| 309 |
// If the node and peer are both VHT capable, only search VHT modes |
| 310 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT && HasVhtSupported () && GetVhtSupported (st)) |
| 311 |
{ |
| 312 |
continue; |
| 313 |
} |
| 314 |
// If the node and peer are not both VHT capable, only search HT modes |
| 315 |
if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT && (!HasVhtSupported () || !GetVhtSupported (st))) |
| 316 |
{ |
| 317 |
continue; |
| 318 |
} |
| 319 |
NS_LOG_DEBUG ("Testing mode = " << mode.GetUniqueName () << |
| 320 |
" threshold " << threshold << " maxThreshold " << |
| 321 |
maxThreshold << " last snr observed " << |
| 322 |
station->m_lastSnrObserved << " cached " << |
| 323 |
station->m_lastSnrCached); |
| 324 |
if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) |
| 325 |
{ |
| 326 |
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << |
| 327 |
" threshold " << threshold << |
| 328 |
" last snr observed " << |
| 329 |
station->m_lastSnrObserved); |
| 330 |
maxThreshold = threshold; |
| 331 |
maxMode = mode; |
| 332 |
} |
| 333 |
} |
| 334 |
} |
| 335 |
else |
| 336 |
{ |
| 337 |
// Non-HT selection |
| 338 |
nss = 1; |
| 339 |
for (uint32_t i = 0; i < GetNSupported (station); i++) |
| 340 |
{ |
| 341 |
mode = GetSupported (station, i); |
| 342 |
txVector.SetMode (mode); |
| 343 |
txVector.SetNss (nss); |
| 344 |
txVector.SetChannelWidth (GetChannelWidthForMode (mode)); |
| 345 |
double threshold = GetSnrThreshold (txVector); |
| 346 |
NS_LOG_DEBUG ("mode = " << mode.GetUniqueName () << |
| 347 |
" threshold " << threshold << |
| 348 |
" last snr observed " << |
| 349 |
station->m_lastSnrObserved); |
| 350 |
if (threshold > maxThreshold && threshold < station->m_lastSnrObserved) |
| 351 |
{ |
| 352 |
NS_LOG_DEBUG ("Candidate mode = " << mode.GetUniqueName () << |
| 353 |
" threshold " << threshold << |
| 354 |
" last snr observed " << |
| 355 |
station->m_lastSnrObserved); |
| 356 |
maxThreshold = threshold; |
| 357 |
maxMode = mode; |
| 358 |
} |
| 359 |
} |
| 360 |
} |
| 361 |
NS_LOG_DEBUG ("Updating cached values for station to " << maxMode.GetUniqueName () << " snr " << station->m_lastSnrObserved); |
| 362 |
station->m_lastSnrCached = station->m_lastSnrObserved; |
| 363 |
station->m_lastMode = maxMode; |
| 364 |
station->m_nss = nss; |
| 365 |
} |
529 |
} |
| 366 |
uint32_t channelWidth = GetChannelWidth (station); |
|
|
| 367 |
NS_LOG_DEBUG ("Found maxMode: " << maxMode << " channelWidth: " << channelWidth); |
| 368 |
if (m_currentRate != maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss)) |
| 369 |
{ |
| 370 |
NS_LOG_DEBUG ("New datarate: " << maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss)); |
| 371 |
m_currentRate = maxMode.GetDataRate (channelWidth, GetPhy ()->GetGuardInterval (), nss); |
| 372 |
} |
| 373 |
return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, nss, 0, channelWidth, GetAggregation (station), false); |
| 374 |
} |
530 |
} |
| 375 |
|
531 |
|
| 376 |
WifiTxVector |
532 |
WifiTxVector |
|
|
| 411 |
return true; |
567 |
return true; |
| 412 |
} |
568 |
} |
| 413 |
|
569 |
|
|
|
570 |
bool |
| 571 |
IdealWifiManager::IsSupportedTxVector (const WifiTxVector txVector) const |
| 572 |
{ |
| 573 |
if (txVector.GetNss () > GetPhy ()->GetSupportedTxSpatialStreams ()) |
| 574 |
{ |
| 575 |
return false; |
| 576 |
} |
| 577 |
return true; |
| 578 |
} |
| 579 |
|
| 414 |
} //namespace ns3 |
580 |
} //namespace ns3 |