27#include "ns3/ht-configuration.h"
29#include "ns3/packet.h"
30#include "ns3/random-variable-stream.h"
31#include "ns3/simulator.h"
32#include "ns3/wifi-mac.h"
33#include "ns3/wifi-net-device.h"
34#include "ns3/wifi-phy.h"
38#define Min(a, b) ((a < b) ? a : b)
39#define Max(a, b) ((a > b) ? a : b)
72 TypeId(
"ns3::MinstrelHtWifiManager")
74 .AddConstructor<MinstrelHtWifiManager>()
76 .AddAttribute(
"UpdateStatistics",
77 "The interval between updating statistics table",
81 .AddAttribute(
"LegacyUpdateStatistics",
82 "The interval between updating statistics table (for legacy Minstrel)",
86 .AddAttribute(
"LookAroundRate",
87 "The percentage to try other rates (for legacy Minstrel)",
96 .AddAttribute(
"SampleColumn",
97 "The number of columns used for sampling",
101 .AddAttribute(
"PacketLength",
102 "The packet length used for calculating mode TxTime (bytes)",
106 .AddAttribute(
"UseLatestAmendmentOnly",
107 "Use only the latest amendment when it is supported by both peers",
111 .AddAttribute(
"PrintStats",
112 "Control the printing of the statistics table",
116 .AddTraceSource(
"Rate",
117 "Traced value for rate changes (b/s)",
119 "ns3::TracedValueCallback::Uint64");
151 int64_t numStreamsAssigned = 0;
153 numStreamsAssigned++;
155 return numStreamsAssigned;
222 for (
int gi = 800; gi >= 400;)
227 uint8_t groupId =
GetHtGroupId(streams, guardInterval, chWidth);
240 && (
GetPhy()->GetMaxSupportedTxSpatialStreams() >=
250 WifiMode mode = htMcsList[deviceIndex];
268 NS_LOG_DEBUG(
"Initialized group " << +groupId <<
": (" << +streams <<
","
269 << guardInterval <<
"," << chWidth
283 for (
int gi = 800; gi >= 400;)
288 uint8_t groupId =
GetVhtGroupId(streams, guardInterval, chWidth);
301 && (
GetPhy()->GetMaxSupportedTxSpatialStreams() >=
333 NS_LOG_DEBUG(
"Initialized group " << +groupId <<
": (" << +streams <<
","
334 << gi <<
"," << chWidth <<
")");
347 for (
int gi = 3200; gi >= 800;)
352 uint8_t groupId =
GetHeGroupId(streams, guardInterval, chWidth);
365 && (
GetPhy()->GetMaxSupportedTxSpatialStreams() >=
397 NS_LOG_DEBUG(
"Initialized group " << +groupId <<
": (" << +streams <<
","
398 << gi <<
"," << chWidth <<
")");
426 NS_LOG_FUNCTION(
this << phy << +streams << gi << chWidth << mode << mpduType);
452 m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.insert(std::make_pair(mode, t));
480 station->m_index = 0;
481 station->m_maxTpRate = 0;
482 station->m_maxTpRate2 = 0;
483 station->m_maxProbRate = 0;
484 station->m_nModes = 0;
485 station->m_totalPacketsCount = 0;
486 station->m_samplePacketsCount = 0;
487 station->m_isSampling =
false;
488 station->m_sampleRate = 0;
489 station->m_sampleDeferred =
false;
490 station->m_shortRetry = 0;
491 station->m_longRetry = 0;
492 station->m_txrate = 0;
493 station->m_initialized =
false;
496 station->m_sampleGroup = 0;
497 station->m_numSamplesSlow = 0;
498 station->m_sampleCount = 16;
499 station->m_sampleWait = 0;
500 station->m_sampleTries = 4;
502 station->m_avgAmpduLen = 1;
503 station->m_ampduLen = 0;
504 station->m_ampduPacketCount = 0;
508 station->m_isHt =
static_cast<bool>(
GetPhy()->
GetDevice()->GetHtConfiguration());
569 if (!station->m_initialized)
573 NS_LOG_DEBUG(
"DoReportRtsFailed m_txrate = " << station->m_txrate);
574 station->m_shortRetry++;
593 if (!station->m_initialized)
607 if (!station->m_initialized)
612 NS_LOG_DEBUG(
"DoReportDataFailed " << station <<
"\t rate " << station->m_txrate
613 <<
"\tlongRetry \t" << station->m_longRetry);
615 if (!station->m_isHt)
621 uint8_t rateId =
GetRateId(station->m_txrate);
622 uint8_t groupId =
GetGroupId(station->m_txrate);
623 station->m_groupsTable[groupId]
624 .m_ratesTable[rateId]
635 MHz_u dataChannelWidth,
638 NS_LOG_FUNCTION(
this << st << ackSnr << ackMode << dataSnr << dataChannelWidth << +dataNss);
642 if (!station->m_initialized)
647 if (!station->m_isHt)
651 <<
", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt
652 <<
", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess
653 <<
" (before update).");
655 station->m_minstrelTable[station->m_txrate].numRateSuccess++;
656 station->m_minstrelTable[station->m_txrate].numRateAttempt++;
662 <<
", attempt = " << station->m_minstrelTable[station->m_txrate].numRateAttempt
663 <<
", success = " << station->m_minstrelTable[station->m_txrate].numRateSuccess
664 <<
" (after update).");
669 if (station->m_nModes >= 1)
676 uint8_t rateId =
GetRateId(station->m_txrate);
677 uint8_t groupId =
GetGroupId(station->m_txrate);
680 "DoReportDataOk m_txrate = "
682 <<
", attempt = " << station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt
683 <<
", success = " << station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess
684 <<
" (before update).");
686 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess++;
687 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt++;
692 "DoReportDataOk m_txrate = "
694 <<
", attempt = " << station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt
695 <<
", success = " << station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess
696 <<
" (after update).");
698 station->m_isSampling =
false;
699 station->m_sampleDeferred =
false;
707 if (station->m_nModes >= 1)
709 station->m_txrate =
FindRate(station);
713 NS_LOG_DEBUG(
"Next rate to use TxRate = " << station->m_txrate);
723 if (!station->m_initialized)
728 NS_LOG_DEBUG(
"DoReportFinalDataFailed - TxRate=" << station->m_txrate);
730 if (!station->m_isHt)
737 if (station->m_nModes >= 1)
746 station->m_isSampling =
false;
747 station->m_sampleDeferred =
false;
755 if (station->m_nModes >= 1)
757 station->m_txrate =
FindRate(station);
760 NS_LOG_DEBUG(
"Next rate to use TxRate = " << station->m_txrate);
765 uint16_t nSuccessfulMpdus,
766 uint16_t nFailedMpdus,
769 MHz_u dataChannelWidth,
772 NS_LOG_FUNCTION(
this << st << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
773 << dataChannelWidth << +dataNss);
777 if (!station->m_initialized)
782 NS_ASSERT_MSG(station->m_isHt,
"A-MPDU Tx Status called but this is a non-HT STA.");
784 NS_LOG_DEBUG(
"DoReportAmpduTxStatus. TxRate=" << station->m_txrate
785 <<
" SuccMpdus=" << nSuccessfulMpdus
786 <<
" FailedMpdus=" << nFailedMpdus);
788 station->m_ampduPacketCount++;
789 station->m_ampduLen += nSuccessfulMpdus + nFailedMpdus;
793 uint8_t rateId =
GetRateId(station->m_txrate);
794 uint8_t groupId =
GetGroupId(station->m_txrate);
795 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess += nSuccessfulMpdus;
796 station->m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt +=
797 nSuccessfulMpdus + nFailedMpdus;
799 if (nSuccessfulMpdus == 0 && station->m_longRetry <
CountRetries(station))
806 station->m_isSampling =
false;
807 station->m_sampleDeferred =
false;
815 if (station->m_nModes >= 1)
817 station->m_txrate =
FindRate(station);
819 NS_LOG_DEBUG(
"Next rate to use TxRate = " << station->m_txrate);
871 station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount)
879 (station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
880 station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount))
888 (station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
889 station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
890 station->
m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount))
897 NS_FATAL_ERROR(
"Max retries reached and m_longRetry not cleared properly. longRetry= "
908 1 + station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount)
916 1 + station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
917 station->
m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount)
924 NS_FATAL_ERROR(
"Max retries reached and m_longRetry not cleared properly. longRetry= "
941 uint16_t nSuccessfulMpdus,
942 uint16_t nFailedMpdus)
973 if (group.
chWidth <= allowedWidth)
975 NS_LOG_DEBUG(
"Channel width is not greater than allowed width, nothing to do");
984 auto width = group.
chWidth / 2;
988 if (width > allowedWidth)
1018 NS_ABORT_MSG_IF(width < 20,
"No rate compatible with the allowed width found");
1029 if (!station->m_initialized)
1034 if (!station->m_isHt)
1047 NS_LOG_DEBUG(
"DoGetDataMode m_txrate= " << station->m_txrate);
1049 uint8_t rateId =
GetRateId(station->m_txrate);
1050 uint8_t groupId =
GetGroupId(station->m_txrate);
1051 uint8_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
1053 NS_LOG_DEBUG(
"DoGetDataMode rateId= " << +rateId <<
" groupId= " << +groupId
1099 if (!station->m_initialized)
1104 if (!station->m_isHt)
1110 NS_LOG_DEBUG(
"DoGetRtsMode m_txrate=" << station->m_txrate);
1126 uint8_t rateId =
GetRateId(station->m_txrate);
1127 uint8_t groupId =
GetGroupId(station->m_txrate);
1128 uint8_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
1135 bool rateFound =
false;
1137 for (uint8_t i = 0; i < nBasicRates; i++)
1140 if (rate <= lastDataRate)
1150 for (
const auto& mode : phy->GetModeList())
1152 uint64_t rate = mode.GetDataRate(20);
1153 if (rate <= lastDataRate)
1186 if (!station->m_initialized)
1193 if (!station->m_isHt)
1202 if (station->m_longRetry >= maxRetries)
1204 NS_LOG_DEBUG(
"No re-transmission allowed. Retries: " << station->m_longRetry
1205 <<
" Max retries: " << maxRetries);
1210 NS_LOG_DEBUG(
"Re-transmit. Retries: " << station->m_longRetry
1211 <<
" Max retries: " << maxRetries);
1228 return station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].retryCount +
1229 station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].retryCount +
1230 station->
m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1234 return 1 + station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTp2RateId].retryCount +
1235 station->
m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].retryCount;
1244 uint8_t index = station->
m_groupsTable[sampleGroup].m_index;
1247 uint16_t rateIndex =
GetIndex(sampleGroup, sampleIndex);
1305 uint8_t sampleGroupId =
GetGroupId(sampleIdx);
1306 uint8_t sampleRateId =
GetRateId(sampleIdx);
1310 station->
m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId].supported)
1320 station->
m_groupsTable[sampleGroupId].m_ratesTable[sampleRateId];
1324 <<
" SampleRate= " << sampleIdx
1325 <<
" SampleProb= " << sampleRateInfo.
ewmaProb);
1345 Time maxTp2Duration =
1346 station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].perfectTxTime;
1348 .m_ratesTable[maxProbRateId]
1352 << sampleDuration <<
" maxTp2Duration= " << maxTp2Duration
1353 <<
" maxProbDuration= " << maxProbDuration <<
" sampleStreams= "
1354 << +sampleStreams <<
" maxTpStreams= " << +maxTpStreams);
1355 if (sampleDuration < maxTp2Duration ||
1356 (sampleStreams < maxTpStreams && sampleDuration < maxProbDuration))
1365 <<
"sampleRate=" << sampleIdx);
1381 <<
"sampleRate=" << sampleIdx);
1443 station->
m_groupsTable[j].m_ratesTable[i].retryUpdated =
false;
1452 << station->
m_groupsTable[j].m_ratesTable[i].numRateSuccess);
1455 if (station->
m_groupsTable[j].m_ratesTable[i].numRateAttempt > 0)
1457 station->
m_groupsTable[j].m_ratesTable[i].numSamplesSkipped = 0;
1463 (100 * station->
m_groupsTable[j].m_ratesTable[i].numRateSuccess) /
1469 if (station->
m_groupsTable[j].m_ratesTable[i].successHist == 0)
1471 station->
m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1485 station->
m_groupsTable[j].m_ratesTable[i].ewmaProb = tempProb;
1498 station->
m_groupsTable[j].m_ratesTable[i].numSamplesSkipped++;
1502 station->
m_groupsTable[j].m_ratesTable[i].prevNumRateSuccess =
1504 station->
m_groupsTable[j].m_ratesTable[i].prevNumRateAttempt =
1506 station->
m_groupsTable[j].m_ratesTable[i].numRateSuccess = 0;
1507 station->
m_groupsTable[j].m_ratesTable[i].numRateAttempt = 0;
1509 if (station->
m_groupsTable[j].m_ratesTable[i].throughput != 0)
1556 Time txTime = station->
m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime;
1581 uint8_t maxGPGroupId;
1582 uint8_t maxGPRateId;
1592 tmpProb = station->
m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].ewmaProb;
1593 tmpTh = station->
m_groupsTable[tmpGroupId].m_ratesTable[tmpRateId].throughput;
1597 currentTh = station->
m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1598 if (currentTh > tmpTh)
1605 maxGPTh = station->
m_groupsTable[maxGPGroupId].m_ratesTable[maxGPRateId].throughput;
1607 if (currentTh > maxGPTh)
1640 uint8_t maxTpGroupId;
1641 uint8_t maxTpRateId;
1642 uint8_t maxTp2GroupId;
1643 uint8_t maxTp2RateId;
1651 prob = station->
m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb;
1652 th = station->
m_groupsTable[groupId].m_ratesTable[rateId].throughput;
1656 maxTpProb = station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].ewmaProb;
1657 maxTpTh = station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1661 maxTp2Prob = station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].ewmaProb;
1662 maxTp2Th = station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1664 if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1669 else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1680 maxTpTh = station->
m_groupsTable[maxTpGroupId].m_ratesTable[maxTpRateId].throughput;
1684 maxTp2Prob = group->
m_ratesTable[maxTp2RateId].ewmaProb;
1685 maxTp2Th = station->
m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].throughput;
1687 if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb))
1692 else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob))
1709 bool noSupportedGroupFound =
true;
1710 for (uint8_t groupId = 0; groupId <
m_numGroups; groupId++)
1773 noSupportedGroupFound =
false;
1782 station->
m_groupsTable[groupId].m_ratesTable[i].supported =
false;
1787 for (uint8_t i = 0; i < station->
m_nModes; i++)
1823 station->
m_groupsTable[groupId].m_ratesTable[rateId].supported =
true;
1824 station->
m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex =
1826 station->
m_groupsTable[groupId].m_ratesTable[rateId].numRateAttempt = 0;
1827 station->
m_groupsTable[groupId].m_ratesTable[rateId].numRateSuccess = 0;
1828 station->
m_groupsTable[groupId].m_ratesTable[rateId].prob = 0;
1829 station->
m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb = 0;
1830 station->
m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateAttempt = 0;
1831 station->
m_groupsTable[groupId].m_ratesTable[rateId].prevNumRateSuccess = 0;
1832 station->
m_groupsTable[groupId].m_ratesTable[rateId].numSamplesSkipped = 0;
1833 station->
m_groupsTable[groupId].m_ratesTable[rateId].successHist = 0;
1834 station->
m_groupsTable[groupId].m_ratesTable[rateId].attemptHist = 0;
1835 station->
m_groupsTable[groupId].m_ratesTable[rateId].throughput = 0;
1836 station->
m_groupsTable[groupId].m_ratesTable[rateId].perfectTxTime =
1838 station->
m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 0;
1839 station->
m_groupsTable[groupId].m_ratesTable[rateId].adjustedRetryCount = 0;
1847 if (noSupportedGroupFound)
1862 if (!station->
m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated)
1883 if (station->
m_groupsTable[groupId].m_ratesTable[rateId].ewmaProb < 1)
1885 station->
m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 1;
1889 station->
m_groupsTable[groupId].m_ratesTable[rateId].retryCount = 2;
1890 station->
m_groupsTable[groupId].m_ratesTable[rateId].retryUpdated =
true;
1896 station->
m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) +
1900 station->
m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex)) *
1904 cwTime = (cw / 2) * slotTime;
1905 cw =
Min((cw + 1) * 2, cwMax);
1906 cwTime += (cw / 2) * slotTime;
1907 cw =
Min((cw + 1) * 2, cwMax);
1910 txTime = cwTime + 2 * (dataTxTime + ackTime);
1916 cwTime = (cw / 2) * slotTime;
1917 cw =
Min((cw + 1) * 2, cwMax);
1920 txTime += cwTime + ackTime + dataTxTime;
1922 (++station->
m_groupsTable[groupId].m_ratesTable[rateId].retryCount < 7));
1937 diff = currentProb - ewmaProb;
1938 incr = (100 - weight) * diff / 100;
1939 tmp = oldEwmsd * oldEwmsd;
1940 tmp = weight * (tmp + diff * incr) / 100;
1958 for (uint8_t i = 0; i < numSampleRates; i++)
1965 newIndex = (i + uv) % numSampleRates;
1982 std::ostringstream tmp;
1984 station->
m_statsFile.open(tmp.str(), std::ios::out);
1988 <<
" best ____________rate__________ ________statistics________ "
1989 "________last_______ ______sum-of________\n"
1990 <<
" mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] "
1991 "[prob.|retry|suc|att] [#success | #attempts]\n";
1997 station->
m_statsFile <<
"\nTotal packet count:: ideal "
2014 for (uint8_t i = 0; i < numRates; i++)
2026 uint16_t idx =
GetIndex(groupId, i);
2027 if (idx == maxTpRate)
2035 if (idx == maxTpRate2)
2043 if (idx == maxProbRate)
2054 of << std::setw(4) <<
" MCS" << (group.
streams - 1) * 8 + i;
2058 of << std::setw(7) <<
" MCS" << +i <<
"/" <<
static_cast<int>(group.
streams);
2061 of <<
" " << std::setw(3) << +idx <<
" ";
2070 << std::setw(7) << station->
m_groupsTable[groupId].m_ratesTable[i].throughput / 100
2071 <<
" " << std::setw(7) << station->
m_groupsTable[groupId].m_ratesTable[i].ewmaProb
2072 <<
" " << std::setw(7) << station->
m_groupsTable[groupId].m_ratesTable[i].ewmsdProb
2073 <<
" " << std::setw(7) << station->
m_groupsTable[groupId].m_ratesTable[i].prob
2074 <<
" " << std::setw(2) << station->
m_groupsTable[groupId].m_ratesTable[i].retryCount
2075 <<
" " << std::setw(3)
2076 << station->
m_groupsTable[groupId].m_ratesTable[i].prevNumRateSuccess <<
" "
2077 << std::setw(3) << station->
m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt
2078 <<
" " << std::setw(9)
2079 << station->
m_groupsTable[groupId].m_ratesTable[i].successHist <<
" "
2080 << std::setw(9) << station->
m_groupsTable[groupId].m_ratesTable[i].attemptHist
2115 uint8_t giIndex = (guardInterval.
GetNanoSeconds() == 400) ? 1 : 0;
2116 uint8_t widthIndex = (chWidth == 40) ? 1 : 0;
2125 uint8_t giIndex = (guardInterval.
GetNanoSeconds() == 400) ? 1 : 0;
2131 else if (chWidth == 80)
2135 else if (chWidth == 40)
2158 else if (gi == 1600)
2171 else if (chWidth == 80)
2175 else if (chWidth == 40)
2183 uint8_t groupId = 0;
2202 uint8_t groupId = 0;
2204 while (groupId < m_numGroups && !station->m_groupsTable[groupId].m_supported)
2208 while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
2213 station->
m_groupsTable[groupId].m_ratesTable[rateId].supported);
2223 while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported)
2228 station->
m_groupsTable[groupId].m_ratesTable[rateId].supported);
2236 WifiModeList heMcsList(mcsList.begin(), mcsList.end());
2244 WifiModeList vhtMcsList(mcsList.begin(), mcsList.end());
2252 WifiModeList htMcsList(mcsList.begin(), mcsList.end());
Implementation of Minstrel-HT Rate Control Algorithm.
static TypeId GetTypeId()
Get the type ID.
uint32_t CountRetries(MinstrelHtWifiRemoteStation *station)
Count retries.
uint32_t m_frameLength
Frame length used to calculate modes TxTime in bytes.
void InitSampleTable(MinstrelHtWifiRemoteStation *station)
Initialize Sample Table.
bool m_printStats
If statistics table should be printed.
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode) override
This method is a pure virtual method that must be implemented by the sub-class.
bool DoNeedRetransmission(WifiRemoteStation *st, Ptr< const Packet > packet, bool normally) override
void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr, MHz_u dataChannelWidth, uint8_t dataNss) override
This method is a pure virtual method that must be implemented by the sub-class.
WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station) override
MinstrelMcsGroups m_minstrelGroups
Global array for groups information.
void AddMpduTxTime(uint8_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
void SetNextSample(MinstrelHtWifiRemoteStation *station)
Set the next sample from Sample Table.
uint8_t m_numRates
Number of rates per group Minstrel should consider.
uint16_t UpdateRateAfterAllowedWidth(uint16_t txRate, MHz_u allowedWidth)
Given the index of the current TX rate, check whether the channel width is not greater than the given...
uint8_t m_nSampleCol
Number of sample columns.
bool IsValidMcs(Ptr< WifiPhy > phy, uint8_t streams, MHz_u chWidth, WifiMode mode)
Check the validity of a combination of number of streams, chWidth and mode.
void RateInit(MinstrelHtWifiRemoteStation *station)
Initialize Minstrel Table.
void SetBestStationThRates(MinstrelHtWifiRemoteStation *station, uint16_t index)
Set index rate as maxTpRate or maxTp2Rate if is better than current values.
~MinstrelHtWifiManager() override
void PrintTable(MinstrelHtWifiRemoteStation *station)
Printing Minstrel Table.
void StatsDump(MinstrelHtWifiRemoteStation *station, uint8_t groupId, std::ofstream &of)
Print group statistics.
double CalculateThroughput(MinstrelHtWifiRemoteStation *station, uint8_t groupId, uint8_t rateId, double ewmaProb)
Return the average throughput of the MCS defined by groupId and rateId.
void AddFirstMpduTxTime(uint8_t groupId, WifiMode mode, Time t)
Save a TxTime to the vector of groups.
double CalculateEwmsd(double oldEwmsd, double currentProb, double ewmaProb, double weight)
Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation.
void DoReportDataFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
void SetBestProbabilityRate(MinstrelHtWifiRemoteStation *station, uint16_t index)
Set index rate as maxProbRate if it is better than current value.
WifiModeList GetHeDeviceMcsList() const
Returns a list of only the HE MCS supported by the device.
Time m_updateStats
How frequent do we calculate the stats.
TracedValue< uint64_t > m_currentRate
Trace rate changes.
uint16_t GetLowestIndex(MinstrelHtWifiRemoteStation *station)
Returns the lowest global index of the rates supported by the station.
void DoInitialize() override
Initialize() implementation.
WifiModeList GetVhtDeviceMcsList() const
Returns a list of only the VHT MCS supported by the device.
uint8_t GetVhtGroupId(uint8_t txstreams, Time guardInterval, MHz_u chWidth)
Returns the groupId of a VHT MCS with the given number of streams, GI and channel width used.
WifiTxVector DoGetDataTxVector(WifiRemoteStation *station, MHz_u allowedWidth) override
void CheckInit(MinstrelHtWifiRemoteStation *station)
Check for initializations.
WifiModeList GetHtDeviceMcsList() const
Returns a list of only the HT MCS supported by the device.
void UpdateRetry(MinstrelHtWifiRemoteStation *station)
Update the number of retries and reset accordingly.
Time GetFirstMpduTxTime(uint8_t groupId, WifiMode mode) const
Obtain the TxTime saved in the group information.
Time GetMpduTxTime(uint8_t groupId, WifiMode mode) const
Obtain the TxTime saved in the group information.
uint8_t m_numGroups
Number of groups Minstrel should consider.
void CalculateRetransmits(MinstrelHtWifiRemoteStation *station, uint16_t index)
Calculate the number of retransmissions to set for the index rate.
void SetupPhy(const Ptr< WifiPhy > phy) override
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
uint8_t GetHeGroupId(uint8_t txstreams, Time guardInterval, MHz_u chWidth)
Returns the groupId of an HE MCS with the given number of streams, GI and channel width used.
uint8_t m_ewmaLevel
Exponential weighted moving average level (or coefficient).
uint16_t FindRate(MinstrelHtWifiRemoteStation *station)
Find a rate to use from Minstrel Table.
uint8_t m_lookAroundRate
The % to try other rates than our current rate.
void UpdateRate(MinstrelHtWifiRemoteStation *station)
Update rate.
uint8_t GetRateId(uint16_t index)
Return the rateId inside a group, from the global index.
Time m_legacyUpdateStats
How frequent do we calculate the stats for legacy MinstrelWifiManager.
uint8_t GetGroupId(uint16_t index)
Return the groupId from the global index.
void DoReportRtsOk(WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr) override
This method is a pure virtual method that must be implemented by the sub-class.
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
Time CalculateMpduTxDuration(Ptr< WifiPhy > phy, uint8_t streams, Time gi, MHz_u chWidth, WifiMode mode, MpduType mpduType)
Estimates the TxTime of a frame with a given mode and group (stream, guard interval and channel width...
uint8_t GetHtGroupId(uint8_t txstreams, Time guardInterval, MHz_u chWidth)
Returns the groupId of an HT MCS with the given number of streams, GI and channel width used.
uint16_t GetNextSample(MinstrelHtWifiRemoteStation *station)
Getting the next sample from Sample Table.
void UpdateStats(MinstrelHtWifiRemoteStation *station)
Update the Minstrel Table.
uint16_t GetIndex(uint8_t groupId, uint8_t rateId)
Returns the global index corresponding to the groupId and rateId.
WifiRemoteStation * DoCreateStation() const override
Ptr< MinstrelWifiManager > m_legacyManager
Pointer to an instance of MinstrelWifiManager.
void SetupMac(const Ptr< WifiMac > mac) override
Set up MAC associated with this device since it is the object that knows the full set of timing param...
void DoReportFinalDataFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
void UpdatePacketCounters(MinstrelHtWifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus)
Update the number of sample count variables.
void DoReportFinalRtsFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
bool m_useLatestAmendmentOnly
Flag if only the latest supported amendment by both peers should be used.
void DoReportRtsFailed(WifiRemoteStation *station) override
This method is a pure virtual method that must be implemented by the sub-class.
void DoReportAmpduTxStatus(WifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, MHz_u dataChannelWidth, uint8_t dataNss) override
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
Smart pointer class similar to boost::intrusive_ptr.
static Time Now()
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
represent a single transmission mode
WifiModulationClass GetModulationClass() const
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
uint64_t GetNonHtReferenceRate() const
uint8_t GetMcsValue() const
Time GetBlockAckTxTime() const
Return the estimated BlockAck TX time for this PHY.
static Time GetPayloadDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, MpduType mpdutype=NORMAL_MPDU, uint16_t staId=SU_STA_ID)
Time GetSlot() const
Return the slot duration for this PHY.
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
MHz_u GetTxBandwidth(WifiMode mode, MHz_u maxAllowedBandWidth=std::numeric_limits< MHz_u >::max()) const
Get the bandwidth for a transmission occurring on the current operating channel and using the given W...
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
std::list< WifiMode > GetMcsList() const
The WifiPhy::GetMcsList() method is used (e.g., by a WifiRemoteStationManager) to determine the set o...
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
hold a list of per-remote-station state.
uint8_t GetNumberOfSupportedStreams(Mac48Address address) const
Return the number of spatial streams supported by the station.
uint8_t GetNess(const WifiRemoteStation *station) const
uint8_t GetNBasicModes() const
Return the number of basic modes we support.
Time GetGuardInterval() const
Return the supported HE guard interval duration.
uint8_t GetDefaultTxPowerLevel() const
Ptr< WifiPhy > GetPhy() const
Return the WifiPhy.
MHz_u GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
Ptr< const He6GhzBandCapabilities > GetStationHe6GhzCapabilities(const Mac48Address &from) const
Return the HE 6 GHz Band Capabilities sent by a remote station.
bool GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
bool GetHtSupported() const
Return whether the device has HT capability support enabled on the link this manager is associated wi...
uint8_t GetNumberOfAntennas() const
uint8_t GetNMcsSupported(Mac48Address address) const
Return the number of MCS supported by the station.
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
bool GetShortGuardIntervalSupported() const
Return whether the device has SGI support enabled.
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
WifiMode GetMcsSupported(const WifiRemoteStation *station, uint8_t i) const
Return the WifiMode supported by the specified station at the specified index.
bool GetVhtSupported() const
Return whether the device has VHT capability support enabled on the link this manager is associated w...
bool GetShortPreambleEnabled() const
Return whether the device uses short PHY preambles.
bool GetHeSupported() const
Return whether the device has HE capability support enabled.
virtual void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
void SetGuardInterval(Time guardInterval)
Sets the guard interval duration (in nanoseconds)
bool IsValid(WifiPhyBand band=WIFI_PHY_BAND_UNSPECIFIED) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
MpduType
The type of an MPDU.
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
static const MHz_u MAX_HT_WIDTH
Maximal channel width.
static const uint8_t MAX_HT_GROUP_RATES
Number of rates (or MCS) per HT group.
static const uint8_t MAX_VHT_STREAM_GROUPS
Maximal number of groups per stream in VHT (4 possible channel widths and 2 possible GI configuration...
Ptr< const AttributeChecker > MakeUintegerChecker()
std::vector< RateInfo > MinstrelRate
Data structure for a Minstrel Rate table A vector of a struct RateInfo.
std::vector< McsGroup > MinstrelMcsGroups
Data structure for a table of group definitions.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
@ WIFI_MINSTREL_GROUP_VHT
static const uint8_t MAX_VHT_GROUP_RATES
Number of rates (or MCS) per VHT group.
static const uint8_t MAX_VHT_SUPPORTED_STREAMS
Maximal number of streams supported by the VHT PHY layer.
static const uint8_t MAX_HT_SUPPORTED_STREAMS
Constants for maximum values.
static const uint8_t MAX_HE_GROUP_RATES
Number of rates (or MCS) per HE group.
static const MHz_u MAX_VHT_WIDTH
Maximal channel width.
static const uint8_t MAX_HT_STREAM_GROUPS
Maximal number of groups per stream in HT (2 possible channel widths and 2 possible GI configurations...
static const uint8_t MAX_HE_STREAM_GROUPS
Maximal number of groups per stream in HE (4 possible channel widths and 3 possible GI configurations...
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble)
Return the preamble to be used for the transmission.
std::vector< MinstrelHtRateInfo > MinstrelHtRate
Data structure for a Minstrel Rate table.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
std::vector< WifiMode > WifiModeList
In various parts of the code, folk are interested in maintaining a list of transmission modes.
std::vector< std::vector< uint8_t > > SampleRate
Data structure for a Sample Rate table A vector of a vector uint8_t.
std::vector< GroupInfo > McsGroupData
Data structure for a table of groups.
static const uint8_t MAX_HE_SUPPORTED_STREAMS
Maximal number of streams supported by the HE PHY layer.
static const MHz_u MAX_HE_WIDTH
Maximal channel width.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
A struct to contain information of a group.
MinstrelHtRate m_ratesTable
Information about rates of this group.
uint16_t m_maxTpRate2
The second max throughput rate of this group in bps.
uint16_t m_maxProbRate
The highest success probability rate of this group in bps.
uint16_t m_maxTpRate
The max throughput rate of this group in bps.
Data structure to contain the information that defines a group.
MHz_u chWidth
channel width
Time gi
guard interval duration
McsGroupType type
identifies the group,
bool isSupported
flag whether group is supported
uint8_t streams
number of spatial streams
A struct to contain all statistics information related to a data rate.
Time perfectTxTime
Perfect transmission time calculation, or frame calculation.
double ewmaProb
Exponential weighted moving average of probability.
uint32_t numSamplesSkipped
Number of times this rate statistics were not updated because no attempts have been made.
MinstrelHtWifiRemoteStation structure.
McsGroupData m_groupsTable
Table of groups with stats.
uint32_t m_sampleCount
Max number of samples per update interval.
uint8_t m_sampleGroup
The group that the sample rate belongs to.
uint32_t m_ampduPacketCount
Number of A-MPDUs transmitted.
uint32_t m_numSamplesSlow
Number of times a slow rate was sampled.
uint32_t m_sampleTries
Number of sample tries after waiting sampleWait.
std::ofstream m_statsFile
File where statistics table is written.
uint32_t m_sampleWait
How many transmission attempts to wait until a new sample.
bool m_isHt
If the station is HT capable.
uint32_t m_avgAmpduLen
Average number of MPDUs in an A-MPDU.
uint32_t m_ampduLen
Number of MPDUs in an A-MPDU.
hold per-remote-station state for Minstrel Wifi manager.
uint16_t m_maxTpRate2
second highest throughput rate in bps
Time m_nextStatsUpdate
10 times every second
bool m_initialized
for initializing tables
uint16_t m_sampleRate
current sample rate in bps
uint8_t m_index
vector index
uint16_t m_txrate
current transmit rate in bps
int m_totalPacketsCount
total number of packets as of now
bool m_isSampling
a flag to indicate we are currently sampling
MinstrelRate m_minstrelTable
minstrel table
uint32_t m_shortRetry
short retries such as control packets
uint16_t m_maxTpRate
the current throughput rate in bps
uint8_t m_nModes
number of modes supported
SampleRate m_sampleTable
sample table
int m_samplePacketsCount
how many packets we have sample so far
uint8_t m_col
To keep track of the current position in the our random sample table going row by row from 1st column...
uint32_t m_longRetry
long retries such as data packets
uint16_t m_maxProbRate
rate with highest probability of success in bps
hold per-remote-station state.
WifiRemoteStationState * m_state
Remote station state.
Mac48Address m_address
Mac48Address of the remote station.
void CalculateThroughput()
Calculate the throughput.