From 3041c01667611d573f96946a43e1360e715313f0 Mon Sep 17 00:00:00 2001 From: Abin Thomas Date: Tue, 5 Nov 2019 13:41:06 +0100 Subject: [PATCH] added latest minstrel and remote station manager --- source/minstrel-ht-wifi-manager.cc | 153 +- source/wifi-remote-station-manager.cc | 2312 +++++++++++++++++++++++++ 2 files changed, 2397 insertions(+), 68 deletions(-) create mode 100644 source/wifi-remote-station-manager.cc diff --git a/source/minstrel-ht-wifi-manager.cc b/source/minstrel-ht-wifi-manager.cc index 0230818..bdf51eb 100644 --- a/source/minstrel-ht-wifi-manager.cc +++ b/source/minstrel-ht-wifi-manager.cc @@ -56,20 +56,22 @@ NS_LOG_COMPONENT_DEFINE ("MinstrelHtWifiManager"); namespace ns3 { std::map mcsphyrate = {{0,6.5},{1,13},{2,19.5},{3,26},{4,39},{5,52},{6,58.5},{7,65}}; -std::map addresslist = {{Mac48Address("00:00:00:00:00:01"), 0},{Mac48Address("00:00:00:00:00:02"), 0},{Mac48Address("00:00:00:00:00:03"), 0}, - {Mac48Address("00:00:00:00:00:04"), 0}, {Mac48Address("00:00:00:00:00:05"), 0}, {Mac48Address("00:00:00:00:00:06"), 0}, - {Mac48Address("00:00:00:00:00:07"), 0}, {Mac48Address("00:00:00:00:00:08"), 0}, {Mac48Address("00:00:00:00:00:09"), 0}, - {Mac48Address("00:00:00:00:00:0a"), 0}}; -std::map addressstamap = {{Mac48Address("00:00:00:00:00:01"), 1},{Mac48Address("00:00:00:00:00:02"), 2},{Mac48Address("00:00:00:00:00:03"), 3}, - {Mac48Address("00:00:00:00:00:04"), 4}, {Mac48Address("00:00:00:00:00:05"), 5}, {Mac48Address("00:00:00:00:00:06"), 6}, - {Mac48Address("00:00:00:00:00:07"), 7}, {Mac48Address("00:00:00:00:00:08"), 8}, {Mac48Address("00:00:00:00:00:09"), 9}, - {Mac48Address("00:00:00:00:00:0a"), 10}}; -std::map lastmcsperaddress = {{Mac48Address("00:00:00:00:00:01"), 0},{Mac48Address("00:00:00:00:00:02"), 0},{Mac48Address("00:00:00:00:00:03"), 0}, +std::map addresslist = {{Mac48Address("00:00:00:00:00:01"), 0},{Mac48Address("00:00:00:00:00:02"), 0},{Mac48Address("00:00:00:00:00:03"), 0}, {Mac48Address("00:00:00:00:00:04"), 0}, {Mac48Address("00:00:00:00:00:05"), 0}, {Mac48Address("00:00:00:00:00:06"), 0}, {Mac48Address("00:00:00:00:00:07"), 0}, {Mac48Address("00:00:00:00:00:08"), 0}, {Mac48Address("00:00:00:00:00:09"), 0}, {Mac48Address("00:00:00:00:00:0a"), 0}}; +std::map addressstamap = {{Mac48Address("00:00:00:00:00:01"), 1},{Mac48Address("00:00:00:00:00:02"), 2},{Mac48Address("00:00:00:00:00:03"), 3}, + {Mac48Address("00:00:00:00:00:04"), 4}, {Mac48Address("00:00:00:00:00:05"), 5}, {Mac48Address("00:00:00:00:00:06"), 6}, + {Mac48Address("00:00:00:00:00:07"), 7}, {Mac48Address("00:00:00:00:00:08"), 8}, {Mac48Address("00:00:00:00:00:09"), 9}, + {Mac48Address("00:00:00:00:00:0a"), 10}}; + +std::map lastmcsperaddress = {{Mac48Address("00:00:00:00:00:01"), 7},{Mac48Address("00:00:00:00:00:02"), 7},{Mac48Address("00:00:00:00:00:03"), 7}, + {Mac48Address("00:00:00:00:00:04"), 7}, {Mac48Address("00:00:00:00:00:05"), 7}, {Mac48Address("00:00:00:00:00:06"), 7}, + {Mac48Address("00:00:00:00:00:07"), 7}, {Mac48Address("00:00:00:00:00:08"), 7}, {Mac48Address("00:00:00:00:00:09"), 7}, + {Mac48Address("00:00:00:00:00:0a"), 7}}; + std::map mcs0agglengthexpth = {{550, 0},{1024, 0},{2048, 0},{3839, 0}}; std::map mcs1agglengthexpth = {{550, 0},{1024, 0},{2048, 0},{3839, 0}}; std::map mcs2agglengthexpth = {{550, 0},{1024, 0},{2048, 0},{3839, 0}}; @@ -108,10 +110,11 @@ std::array sta9bannedcount = {0}; std::array sta10bannedcount = {0}; //map fr banned counter per station -std::map > bannedagglengthcounterperstation = {{Mac48Address("00:00:00:00:00:01"), sta1bannedcount},{Mac48Address("00:00:00:00:00:02"), sta2bannedcount},{Mac48Address("00:00:00:00:00:03"), sta3bannedcount}, - {Mac48Address("00:00:00:00:00:04"), sta4bannedcount}, {Mac48Address("00:00:00:00:00:05"), sta5bannedcount}, {Mac48Address("00:00:00:00:00:06"), sta6bannedcount}, - {Mac48Address("00:00:00:00:00:07"), sta7bannedcount}, {Mac48Address("00:00:00:00:00:08"), sta8bannedcount}, {Mac48Address("00:00:00:00:00:09"), sta9bannedcount}, - {Mac48Address("00:00:00:00:00:0a"), sta10bannedcount}}; +std::map > bannedagglengthcounterperstation = {{Mac48Address("00:00:00:00:00:01"), sta1bannedcount},{Mac48Address("00:00:00:00:00:02"), sta2bannedcount}, + {Mac48Address("00:00:00:00:00:03"), sta3bannedcount}, {Mac48Address("00:00:00:00:00:04"), sta4bannedcount}, + {Mac48Address("00:00:00:00:00:05"), sta5bannedcount}, {Mac48Address("00:00:00:00:00:06"), sta6bannedcount}, + {Mac48Address("00:00:00:00:00:07"), sta7bannedcount}, {Mac48Address("00:00:00:00:00:08"), sta8bannedcount}, + {Mac48Address("00:00:00:00:00:09"), sta9bannedcount}, {Mac48Address("00:00:00:00:00:0a"), sta10bannedcount}}; std::map agglengthtoindexmap = {{550,0},{1024,1},{2048,2},{3839,3}}; uint len_1, len_2, len_3, len_4; @@ -152,7 +155,7 @@ MinstrelHtWifiManager::GetTypeId (void) MakeTimeChecker ()) .AddAttribute ("LookAroundRate", "The percentage to try other rates (for legacy Minstrel)", - UintegerValue (10), + UintegerValue (0), MakeUintegerAccessor (&MinstrelHtWifiManager::m_lookAroundRate), MakeUintegerChecker(0, 100)) .AddAttribute ("EWMA", @@ -199,6 +202,7 @@ MinstrelHtWifiManager::MinstrelHtWifiManager () * Create the legacy Minstrel manager in case HT is not supported by the device * or non-HT stations want to associate. */ + //std::cout<<"LEGACY\n"; m_legacyManager = CreateObject (); } @@ -222,6 +226,7 @@ MinstrelHtWifiManager::AssignStreams (int64_t stream) int64_t numStreamsAssigned = 0; m_uniformRandomVariable->SetStream (stream); numStreamsAssigned++; + //std::cout<<"legacy\n"; numStreamsAssigned += m_legacyManager->AssignStreams (stream); return numStreamsAssigned; } @@ -231,6 +236,7 @@ MinstrelHtWifiManager::SetupPhy (const Ptr phy) { NS_LOG_FUNCTION (this << phy); // Setup phy for legacy manager. + //std::cout<<"legacy\n"; m_legacyManager->SetupPhy (phy); WifiRemoteStationManager::SetupPhy (phy); } @@ -251,7 +257,7 @@ MinstrelHtWifiManager::DoInitialize () { m_numGroups = MAX_SUPPORTED_STREAMS * MAX_HT_STREAM_GROUPS; m_numRates = MAX_HT_GROUP_RATES; - + NS_LOG_DEBUG("NUMGROUPS"< mac) { NS_LOG_FUNCTION (this << mac); + //std::cout<<"legacy\n"; m_legacyManager->SetupMac (mac); WifiRemoteStationManager::SetupMac (mac); } @@ -409,6 +416,7 @@ MinstrelHtWifiManager::GetFirstMpduTxTime (uint8_t groupId, WifiMode mode) const { NS_LOG_FUNCTION (this << +groupId << mode); auto it = m_minstrelGroups[groupId].ratesFirstMpduTxTimeTable.find (mode); + std::cout<second; } @@ -442,12 +450,13 @@ MinstrelHtWifiManager::DoCreateStation (void) const NS_LOG_FUNCTION (this); MinstrelHtWifiRemoteStation *station = new MinstrelHtWifiRemoteStation (); - // Initialize variables common to both stations. + // Initialize variables common to both stations. //hard station->m_nextStatsUpdate = Simulator::Now () + m_updateStats; station->m_col = 0; station->m_index = 0; - station->m_maxTpRate = 0; - station->m_maxTpRate2 = 0; + //std::cout<m_state->m_address<<" last mcs\n"; + station->m_maxTpRate = 0;//lastmcsperaddress[station->m_state->m_address];//0 + station->m_maxTpRate2 = 0;//lastmcsperaddress[station->m_state->m_address];//0 station->m_maxProbRate = 0; station->m_nModes = 0; station->m_totalPacketsCount = 0; @@ -472,6 +481,7 @@ MinstrelHtWifiManager::DoCreateStation (void) const station->m_ampduPacketCount = 0; // If the device supports HT + //std::cout<<" HT:"<m_isHt<<"\n"; if (HasHtSupported () || HasVhtSupported ()) { /** @@ -479,13 +489,13 @@ MinstrelHtWifiManager::DoCreateStation (void) const * When correct information available it will be checked. */ station->m_isHt = true; - std::cout<<"HT HT HT"<m_isHt<<"\n"; + //std::cout<<"HT HT HT"/*<m_state->m_address<<" address"*/<<" is HT:"<m_isHt<<"\n"; } // Use the variable in the station to indicate that the device do not support HT else { station->m_isHt = false; - std::cout<<"HT HT not not HT"<m_isHt<<"\n"; + //std::cout<<"HT HT not not HT"<m_isHt<<"\n"; } return station; @@ -506,7 +516,8 @@ MinstrelHtWifiManager::CheckInit (MinstrelHtWifiRemoteStation *station) * the station will not support HT either. * We save from using another check and variable. */ - if (!GetHtSupported (station) && !GetVhtSupported (station)) + //std::cout<<"in CHECKINIT MINSTRELHT\n"; + if (!GetHtSupported (station) && !GetVhtSupported (station)) //hard to avoid legacy remaining in WifiRemoteStationManager { NS_LOG_INFO ("Non-HT station " << station->m_state->m_address); station->m_isHt = false; @@ -522,18 +533,21 @@ MinstrelHtWifiManager::CheckInit (MinstrelHtWifiRemoteStation *station) } else { + //std::cout<<"in HT"<<"\n"; NS_LOG_DEBUG ("HT station " << station->m_state->m_address); station->m_isHt = true; - station->m_nModes = GetNMcsSupported (station); + station->m_nModes = GetNMcsSupported (station);//static_cast (1);//hard + //station->m_state->m_operationalMcsSet.push_back(GetMcsSupported(station, 0));//hard station->m_minstrelTable = MinstrelRate (station->m_nModes); station->m_sampleTable = SampleRate (m_numRates, std::vector (m_nSampleCol)); InitSampleTable (station); RateInit (station); std::ostringstream tmp; + std::cout<m_state->m_address]<<" is the last mcs:\n"; tmp << "minstrel-ht-stats-" << station->m_state->m_address << ".txt"; station->m_statsFile.open (tmp.str ().c_str (), std::ios::out); station->m_initialized = true; - } + } } } @@ -593,7 +607,8 @@ MinstrelHtWifiManager::DoReportDataFailed (WifiRemoteStation *st) NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry); if (!station->m_isHt) - { + {//legacy + //std::cout<<"legacy\n"; m_legacyManager->UpdateRate (station); } else @@ -788,7 +803,7 @@ MinstrelHtWifiManager::UpdateRate (MinstrelHtWifiRemoteStation *station) * Following implementation in Linux, in MinstrelHT Lowest baserate is not used. * Explanation can be found here: http://marc.info/?l=linux-wireless&m=144602778611966&w=2 */ - + std::cout<<"in update rate\n"; CheckInit (station); if (!station->m_initialized) { @@ -909,24 +924,23 @@ MinstrelHtWifiManager::DoGetDataTxVector (WifiRemoteStation *st) } if (!station->m_isHt) - { + {// try disabling to hard? WifiTxVector vector = m_legacyManager->GetDataTxVector (station); uint64_t dataRate = vector.GetMode ().GetDataRate (vector); if (m_currentRate != dataRate && !station->m_isSampling) { - NS_LOG_DEBUG ("New datarate: " << dataRate); + NS_LOG_DEBUG ("New datarate notHT: " << dataRate); m_currentRate = dataRate; } return vector; } else { - NS_LOG_DEBUG ("DoGetDataMode m_txrate= " << station->m_txrate); + NS_LOG_DEBUG ("DoGetDataMode m_txrate= " << station->m_txrate<<" address:"<m_state->m_address); uint8_t rateId = GetRateId (station->m_txrate); uint8_t groupId = GetGroupId (station->m_txrate); uint8_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex; - NS_LOG_DEBUG ("DoGetDataMode rateId= " << +rateId << " groupId= " << +groupId << " mode= " << GetMcsSupported (station, mcsIndex)); McsGroup group = m_minstrelGroups[groupId]; @@ -1153,7 +1167,7 @@ MinstrelHtWifiManager::FindRate (MinstrelHtWifiRemoteStation *station) //SAMPLING NS_LOG_DEBUG ("Obtaining a sampling rate"); /// Now go through the table and find an index rate. - uint16_t sampleIdx = GetNextSample (station); + uint16_t sampleIdx = lastmcsperaddress[station->m_state->m_address]/*GetNextSample (station)*/;//hard NS_LOG_DEBUG ("Sampling rate = " << sampleIdx); //Evaluate if the sampling rate selected should be used. @@ -1190,9 +1204,13 @@ MinstrelHtWifiManager::FindRate (MinstrelHtWifiRemoteStation *station) uint8_t maxProbGroupId = GetGroupId (station->m_maxProbRate); uint8_t maxProbRateId = GetRateId (station->m_maxProbRate); + + uint8_t maxTpStreams = m_minstrelGroups[maxTpGroupId].streams; uint8_t sampleStreams = m_minstrelGroups[sampleGroupId].streams; + //std::cout <<"FMAXTPratestreams="<m_groupsTable[maxTp2GroupId].m_ratesTable[maxTp2RateId].perfectTxTime; Time maxProbDuration = station->m_groupsTable[maxProbGroupId].m_ratesTable[maxProbRateId].perfectTxTime; @@ -1208,7 +1226,7 @@ MinstrelHtWifiManager::FindRate (MinstrelHtWifiRemoteStation *station) /// set the rate that we're currently sampling station->m_sampleRate = sampleIdx; - NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx); + NS_LOG_DEBUG ("FindRate " << "sampleRate=" << sampleIdx<<" for station:"<m_state->m_address); station->m_sampleTries--; return sampleIdx; } @@ -1262,9 +1280,9 @@ MinstrelHtWifiManager::UpdateStats (MinstrelHtWifiRemoteStation *station) } /* Initialize global rate indexes */ - station->m_maxTpRate = GetLowestIndex (station); - station->m_maxTpRate2 = GetLowestIndex (station); - station->m_maxProbRate = GetLowestIndex (station); + station->m_maxTpRate = lastmcsperaddress[station->m_state->m_address]/*GetLowestIndex (station)*/;//7/**/; + station->m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address]/*GetLowestIndex (station)*/;// 7/*GetLowestIndex (station)*/; + station->m_maxProbRate = lastmcsperaddress[station->m_state->m_address]/*GetLowestIndex (station)*/;//7/*GetLowestIndex (station)*/; /// Update throughput and EWMA for each rate inside each group. for (uint8_t j = 0; j < m_numGroups; j++) @@ -1275,9 +1293,9 @@ MinstrelHtWifiManager::UpdateStats (MinstrelHtWifiRemoteStation *station) NS_LOG_DEBUG("Count of sample = "<m_sampleCount<<"\n"); /* (re)Initialize group rate indexes */ - station->m_groupsTable[j].m_maxTpRate = GetLowestIndex (station, j); - station->m_groupsTable[j].m_maxTpRate2 = GetLowestIndex (station, j); - station->m_groupsTable[j].m_maxProbRate = GetLowestIndex (station, j); + station->m_groupsTable[j].m_maxTpRate = lastmcsperaddress[station->m_state->m_address];//GetLowestIndex (station, j); + station->m_groupsTable[j].m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address];//GetLowestIndex (station, j); + station->m_groupsTable[j].m_maxProbRate = lastmcsperaddress[station->m_state->m_address];//GetLowestIndex (station, j); for (uint8_t i = 0; i < m_numRates; i++) { @@ -1419,7 +1437,7 @@ MinstrelHtWifiManager::SetBestProbabilityRate (MinstrelHtWifiRemoteStation *stat currentTh = station->m_groupsTable[groupId].m_ratesTable[rateId].throughput; if (currentTh > tmpTh) { - station->m_maxProbRate = index; + station->m_maxProbRate = lastmcsperaddress[station->m_state->m_address];//index;//hard } maxGPGroupId = GetGroupId (group->m_maxProbRate); @@ -1428,19 +1446,19 @@ MinstrelHtWifiManager::SetBestProbabilityRate (MinstrelHtWifiRemoteStation *stat if (currentTh > maxGPTh) { - group->m_maxProbRate = index; + group->m_maxProbRate = lastmcsperaddress[station->m_state->m_address];//index;//hard } } else { if (rate.ewmaProb > tmpProb) { - station->m_maxProbRate = index; + station->m_maxProbRate = lastmcsperaddress[station->m_state->m_address];//index;//hard } maxGPRateId = GetRateId (group->m_maxProbRate); if (rate.ewmaProb > group->m_ratesTable[maxGPRateId].ewmaProb) { - group->m_maxProbRate = index; + group->m_maxProbRate = lastmcsperaddress[station->m_state->m_address];//index//hard; } } } @@ -1479,12 +1497,12 @@ MinstrelHtWifiManager::SetBestStationThRates (MinstrelHtWifiRemoteStation *stati if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb)) { - station->m_maxTpRate2 = station->m_maxTpRate; - station->m_maxTpRate = index; + station->m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address]/*station->m_maxTpRate*/; + station->m_maxTpRate = lastmcsperaddress[station->m_state->m_address];//index; } else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob)) { - station->m_maxTpRate2 = index; + station->m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address];//index; } //Find best rates per group @@ -1502,12 +1520,12 @@ MinstrelHtWifiManager::SetBestStationThRates (MinstrelHtWifiRemoteStation *stati if (th > maxTpTh || (th == maxTpTh && prob > maxTpProb)) { - group->m_maxTpRate2 = group->m_maxTpRate; - group->m_maxTpRate = index; + group->m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address];//group->m_maxTpRate;//hard + group->m_maxTpRate = lastmcsperaddress[station->m_state->m_address];//index;//hard } else if (th > maxTp2Th || (th == maxTp2Th && prob > maxTp2Prob)) { - group->m_maxTpRate2 = index; + group->m_maxTpRate2 = lastmcsperaddress[station->m_state->m_address];//index;//hard } } @@ -1545,10 +1563,11 @@ MinstrelHtWifiManager::RateInit (MinstrelHtWifiRemoteStation *station) { station->m_groupsTable[groupId].m_ratesTable[i].supported = false; } - + NS_LOG_DEBUG("no of modes before forloop:"<m_nModes)<<"\n"); // Initialize all modes supported by the remote station that belong to the current group. for (uint8_t i = 0; i < station->m_nModes; i++) { + NS_LOG_DEBUG("No of modes:"<m_nModes)<<" no of mcs:"<m_state->m_address]; - + //discouting the ulink traffic if(idx == prevmcs && station->m_state->m_address != Mac48Address("00:00:00:00:00:0b") && station->m_state->m_address != Mac48Address("00:00:00:00:00:0c") && station->m_state->m_address != Mac48Address("00:00:00:00:00:0d"))// { if (ns3val) { //std::cout<<"The last mcs is "<m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateSuccess)<<" is the success bytes at prev mcs "<m_state->m_address<<" for attempts "<m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateSuccess)<<"at MCS "<< unsigned(prevmcs)<< "\n"; + //std::cout<< packetsizeperstation[station->m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateSuccess)<<" is the success bytes at prev mcs "<m_state->m_address<<" for attempts "<m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateSuccess)<<"at MCS "<< unsigned(prevmcs)<< "\n"; totalnoofbytessuccesscurrent = packetsizeperstation[station->m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateSuccess); //std::cout<<"no of currnet attempt bytes:"<m_state->m_address<<" at MCS "<m_state->m_address] = totalnoofbytessuccesscurrent*8/(1024*1024*mcsphyrate[prevmcs]*0.1);//channel util for platform 0.1 for minstrel window 100ms + chanutil[station->m_state->m_address] = totalnoofbytessuccesscurrent*8*10/(1024*1024*mcsphyrate[prevmcs]);//channel util for platform 0.1 for minstrel window 100ms successrations3[station->m_state->m_address] = float(station->m_groupsTable[groupId].m_ratesTable[prevmcs].lasttoprevNumRateSuccess) / float(station->m_groupsTable[groupId].m_ratesTable[prevmcs].lasttoprevNumRateAttempt)*100; //station->m_statsFile << "\nGoodput:"<m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[i].lasttoprevNumRateSuccess)*8/(1024*1024*0.1))<<"\n Channel Utilization:"<m_state->m_address]<<"\n"; filegp <m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[i].lasttoprevNumRateSuccess)*8/(1024*1024*0.1))<<","; @@ -1897,15 +1916,15 @@ MinstrelHtWifiManager::StatsDump (MinstrelHtWifiRemoteStation *station, uint8_t else { //for platform validation - totalnoofbytesattemptedcurrent += packetsizeperstation[station->m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt);// the time taken for the data is? - std::cout<<"no of currnet attempt bytes:"<m_state->m_address<<"\n"; - std::cout<<" num of attempts:"<m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt<<"\n"; + totalnoofbytesattemptedcurrent = packetsizeperstation[station->m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt);// the time taken for the data is? + //std::cout<<"no of currnet attempt bytes:"<m_state->m_address<<"\n"; + //std::cout<<" num of attempts:"<m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt<<"\n"; //std::cout<<"last attempts "<m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt)<<" and the product is"<m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt)*(0.000034+0.000012+0.000016+0.000016+0.000004+0.000002154)<<"\n"; - float inus = float((station->m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt)*(0.000034+0.000012+0.000016+0.000016+0.000004+0.000002154)/0.1); - float datas = float(totalnoofbytesattemptedcurrent*8/(1024*1024*mcsphyrate[prevmcs]*0.1)); - - std::cout<m_groupsTable[groupId].m_ratesTable[prevmcs].prevNumRateAttempt)*(0.000034+0.000012+0.000016+0.000016+0.000004+0.000002154)*10);//check for the ch util unit is seconds + float datas = float(totalnoofbytesattemptedcurrent*8*10/(1024*1024*mcsphyrate[prevmcs]));//gp(mbs)/phyrate(mbs) + std::cout<<"Percentage is:"<<((datas + inus)/1)*1<<"\n"; + //std::cout<m_state->m_address] = datas + inus;//+(double(station->m_groupsTable[groupId].m_ratesTable[i].prevNumRateAttempt)*(0.000034+0.000012+0.000016+0.000016+0.000004+0.000002154)); successratioplatform[station->m_state->m_address] = float(station->m_groupsTable[groupId].m_ratesTable[prevmcs].lasttoprevNumRateSuccess) / float(station->m_groupsTable[groupId].m_ratesTable[prevmcs].lasttoprevNumRateAttempt); last_attempt_bytes[station->m_state->m_address] = packetsizeperstation[station->m_state->m_address]*double(station->m_groupsTable[groupId].m_ratesTable[prevmcs].lasttoprevNumRateSuccess); @@ -2016,15 +2035,16 @@ MinstrelHtWifiManager::GetVhtGroupId (uint8_t txstreams, uint8_t sgi, uint16_t c } uint16_t -MinstrelHtWifiManager::GetLowestIndex (MinstrelHtWifiRemoteStation *station) +MinstrelHtWifiManager::GetLowestIndex (MinstrelHtWifiRemoteStation *station)//HARD { NS_LOG_FUNCTION (this << station); uint8_t groupId = 0; uint8_t rateId = 0; + //NS_LOG_DEBUG(); while (groupId < m_numGroups && !station->m_groupsTable[groupId].m_supported) { - groupId++; + groupId++;//increase groupid till it reaches the numgroups } while (rateId < m_numRates && !station->m_groupsTable[groupId].m_ratesTable[rateId].supported) { @@ -2072,9 +2092,9 @@ MinstrelHtWifiManager::GetHtDeviceMcsList (void) const for (uint8_t i = 0; i < phy->GetNMcs (); i++)// phy->GetNMcs (); { - + //std::cout<GetNMcs ())<<"no of mcs\n"; NS_LOG_DEBUG("inside GetHtDeviceMcsList"); - WifiMode mode = phy->GetMcs (i); + WifiMode mode = phy->GetMcs (i);//hard 7=i if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) { htMcsList.push_back (mode); @@ -5083,10 +5103,7 @@ int MinstrelHtWifiManager::comparelastandcurrentplatform (float succratio, float Py_DECREF(file3args); Py_DECREF(file4args); Py_DECREF(testobj); - //PyList_SET_ITEM(listObj, 2, PyFloat_FromDouble(double(mcsva))); - /*PyRun_SimpleString("from time import time,ctime\n" - "print 'Today is',ctime(time())\n");*/ - //Py_XDECREF(listObj); + Py_DECREF(xdata); Py_DECREF(xdatatup); diff --git a/source/wifi-remote-station-manager.cc b/source/wifi-remote-station-manager.cc new file mode 100644 index 0000000..d8d0a79 --- /dev/null +++ b/source/wifi-remote-station-manager.cc @@ -0,0 +1,2312 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,2007 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + +#include "ns3/log.h" +#include "ns3/boolean.h" +#include "ns3/uinteger.h" +#include "ns3/enum.h" +#include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/tag.h" +#include "wifi-remote-station-manager.h" +#include "wifi-phy.h" +#include "wifi-mac.h" +#include "wifi-utils.h" +#include "wifi-mac-header.h" +#include "wifi-mac-trailer.h" +#include "ht-capabilities.h" +#include "vht-capabilities.h" +#include "he-capabilities.h" + +/*************************************************************** + * Packet Mode Tagger + ***************************************************************/ + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("WifiRemoteStationManager"); + +/** + * HighLatencyDataTxVectorTag class + */ +class HighLatencyDataTxVectorTag : public Tag +{ +public: + HighLatencyDataTxVectorTag (); + /** + * Constructor + * + * \param dataTxVector TXVECTOR for data frames + */ + HighLatencyDataTxVectorTag (WifiTxVector dataTxVector); + /** + * \returns the transmission mode to use to send this packet + */ + WifiTxVector GetDataTxVector (void) const; + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; + +private: + WifiTxVector m_dataTxVector; ///< TXVECTOR for data frames +}; + +HighLatencyDataTxVectorTag::HighLatencyDataTxVectorTag () +{ +} + +HighLatencyDataTxVectorTag::HighLatencyDataTxVectorTag (WifiTxVector dataTxVector) + : m_dataTxVector (dataTxVector) +{ +} + +WifiTxVector +HighLatencyDataTxVectorTag::GetDataTxVector (void) const +{ + return m_dataTxVector; +} + +TypeId +HighLatencyDataTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyDataTxVectorTag") + .SetParent () + .SetGroupName ("Wifi") + .AddConstructor () + ; + return tid; +} + +TypeId +HighLatencyDataTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyDataTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyDataTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyDataTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyDataTxVectorTag::Print (std::ostream &os) const +{ + os << "Data=" << m_dataTxVector; +} + +/** + * HighLatencyRtsTxVectorTag class + */ +class HighLatencyRtsTxVectorTag : public Tag +{ +public: + HighLatencyRtsTxVectorTag (); + /** + * Constructor + * + * \param rtsTxVector TXVECTOR for RTS frames + */ + HighLatencyRtsTxVectorTag (WifiTxVector rtsTxVector); + /** + * \returns the transmission mode to use to send the RTS prior to the + * transmission of the data packet itself. + */ + WifiTxVector GetRtsTxVector (void) const; + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; + +private: + WifiTxVector m_rtsTxVector; ///< TXVECTOR for data frames +}; + +HighLatencyRtsTxVectorTag::HighLatencyRtsTxVectorTag () +{ +} + +HighLatencyRtsTxVectorTag::HighLatencyRtsTxVectorTag (WifiTxVector rtsTxVector) + : m_rtsTxVector (rtsTxVector) +{ +} + +WifiTxVector +HighLatencyRtsTxVectorTag::GetRtsTxVector (void) const +{ + return m_rtsTxVector; +} + +TypeId +HighLatencyRtsTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyRtsTxVectorTag") + .SetParent () + .SetGroupName ("Wifi") + .AddConstructor () + ; + return tid; +} + +TypeId +HighLatencyRtsTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyRtsTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyRtsTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_rtsTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyRtsTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_rtsTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyRtsTxVectorTag::Print (std::ostream &os) const +{ + os << "Rts=" << m_rtsTxVector; +} + +/** + * HighLatencyCtsToSelfTxVectorTag class + */ +class HighLatencyCtsToSelfTxVectorTag : public Tag +{ +public: + HighLatencyCtsToSelfTxVectorTag (); + /** + * Constructor + * + * \param ctsToSelfTxVector TXVECTOR for CTS-to-self frames + */ + HighLatencyCtsToSelfTxVectorTag (WifiTxVector ctsToSelfTxVector); + /** + * \returns the transmission mode to use for the CTS-to-self. + */ + WifiTxVector GetCtsToSelfTxVector (void) const; + + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; + +private: + WifiTxVector m_ctsToSelfTxVector; ///< TXVECTOR for CTS-to-self frames +}; + +HighLatencyCtsToSelfTxVectorTag::HighLatencyCtsToSelfTxVectorTag () +{ +} + +HighLatencyCtsToSelfTxVectorTag::HighLatencyCtsToSelfTxVectorTag (WifiTxVector ctsToSelfTxVector) + : m_ctsToSelfTxVector (ctsToSelfTxVector) +{ +} + +WifiTxVector +HighLatencyCtsToSelfTxVectorTag::GetCtsToSelfTxVector (void) const +{ + return m_ctsToSelfTxVector; +} + +TypeId +HighLatencyCtsToSelfTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyCtsToSelfTxVectorTag") + .SetParent () + .SetGroupName ("Wifi") + .AddConstructor () + ; + return tid; +} + +TypeId +HighLatencyCtsToSelfTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyCtsToSelfTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyCtsToSelfTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_ctsToSelfTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyCtsToSelfTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_ctsToSelfTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyCtsToSelfTxVectorTag::Print (std::ostream &os) const +{ + os << "Cts To Self=" << m_ctsToSelfTxVector; +} + +} //namespace ns3 + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (WifiRemoteStationManager); + +TypeId +WifiRemoteStationManager::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::WifiRemoteStationManager") + .SetParent () + .SetGroupName ("Wifi") + .AddAttribute ("IsLowLatency", + "If true, we attempt to modelize a so-called low-latency device: " + "a device where decisions about tx parameters can be made on a per-packet basis and " + "feedback about the transmission of each packet is obtained before sending the next. " + "Otherwise, we modelize a high-latency device, that is a device where we cannot update " + "our decision about tx parameters after every packet transmission.", + TypeId::ATTR_GET, + BooleanValue (true), //this value is ignored because there is no setter + MakeBooleanAccessor (&WifiRemoteStationManager::IsLowLatency), + MakeBooleanChecker ()) + .AddAttribute ("MaxSsrc", + "The maximum number of retransmission attempts for any packet with size <= RtsCtsThreshold. " + "This value will not have any effect on some rate control algorithms.", + UintegerValue (7), + MakeUintegerAccessor (&WifiRemoteStationManager::SetMaxSsrc), + MakeUintegerChecker ()) + .AddAttribute ("MaxSlrc", + "The maximum number of retransmission attempts for any packet with size > RtsCtsThreshold. " + "This value will not have any effect on some rate control algorithms.", + UintegerValue (4), + MakeUintegerAccessor (&WifiRemoteStationManager::SetMaxSlrc), + MakeUintegerChecker ()) + .AddAttribute ("RtsCtsThreshold", + "If the size of the PSDU is bigger than this value, we use an RTS/CTS handshake before sending the data frame." + "This value will not have any effect on some rate control algorithms.", + UintegerValue (65535), + MakeUintegerAccessor (&WifiRemoteStationManager::SetRtsCtsThreshold), + MakeUintegerChecker ()) + .AddAttribute ("FragmentationThreshold", + "If the size of the PSDU is bigger than this value, we fragment it such that the size of the fragments are equal or smaller. " + "This value does not apply when it is carried in an A-MPDU. " + "This value will not have any effect on some rate control algorithms.", + UintegerValue (65535), + MakeUintegerAccessor (&WifiRemoteStationManager::DoSetFragmentationThreshold, + &WifiRemoteStationManager::DoGetFragmentationThreshold), + MakeUintegerChecker ()) + .AddAttribute ("NonUnicastMode", + "Wifi mode used for non-unicast transmissions.", + WifiModeValue (), + MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode), + MakeWifiModeChecker ()) + .AddAttribute ("DefaultTxPowerLevel", + "Default power level to be used for transmissions. " + "This is the power level that is used by all those WifiManagers that do not implement TX power control.", + UintegerValue (0), + MakeUintegerAccessor (&WifiRemoteStationManager::m_defaultTxPowerLevel), + MakeUintegerChecker ()) + .AddAttribute ("ErpProtectionMode", + "Protection mode used when non-ERP STAs are connected to an ERP AP: Rts-Cts or Cts-To-Self", + EnumValue (WifiRemoteStationManager::CTS_TO_SELF), + MakeEnumAccessor (&WifiRemoteStationManager::m_erpProtectionMode), + MakeEnumChecker (WifiRemoteStationManager::RTS_CTS, "Rts-Cts", + WifiRemoteStationManager::CTS_TO_SELF, "Cts-To-Self")) + .AddAttribute ("HtProtectionMode", + "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts or Cts-To-Self", + EnumValue (WifiRemoteStationManager::CTS_TO_SELF), + MakeEnumAccessor (&WifiRemoteStationManager::m_htProtectionMode), + MakeEnumChecker (WifiRemoteStationManager::RTS_CTS, "Rts-Cts", + WifiRemoteStationManager::CTS_TO_SELF, "Cts-To-Self")) + .AddTraceSource ("MacTxRtsFailed", + "The transmission of a RTS by the MAC layer has failed", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxDataFailed", + "The transmission of a data packet by the MAC layer has failed", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxDataFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxFinalRtsFailed", + "The transmission of a RTS has exceeded the maximum number of attempts", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalRtsFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxFinalDataFailed", + "The transmission of a data packet has exceeded the maximum number of attempts", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed), + "ns3::Mac48Address::TracedCallback") + ; + return tid; +} + +WifiRemoteStationManager::WifiRemoteStationManager () + : m_htSupported (false), + m_vhtSupported (false), + m_heSupported (false), + m_pcfSupported (false), + m_useNonErpProtection (false), + m_useNonHtProtection (false), + m_useGreenfieldProtection (false), + m_shortPreambleEnabled (false), + m_shortSlotTimeEnabled (false), + m_rifsPermitted (false) +{ + NS_LOG_FUNCTION (this); +} + +WifiRemoteStationManager::~WifiRemoteStationManager () +{ + NS_LOG_FUNCTION (this); +} + +void +WifiRemoteStationManager::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + Reset (); +} + +void +WifiRemoteStationManager::SetupPhy (const Ptr phy) +{ + NS_LOG_FUNCTION (this << phy); + //We need to track our PHY because it is the object that knows the + //full set of transmit rates that are supported. We need to know + //this in order to find the relevant mandatory rates when choosing a + //transmit rate for automatic control responses like + //acknowledgements. + m_wifiPhy = phy; + m_defaultTxMode = phy->GetMode (0); + NS_ASSERT (m_defaultTxMode.IsMandatory ()); + if (HasHtSupported () || HasVhtSupported () || HasHeSupported ()) + { + m_defaultTxMcs = phy->GetMcs (0); + } + Reset (); +} + +void +WifiRemoteStationManager::SetupMac (const Ptr mac) +{ + NS_LOG_FUNCTION (this << mac); + //We need to track our MAC because it is the object that knows the + //full set of interframe spaces. + m_wifiMac = mac; + Reset (); +} + +void +WifiRemoteStationManager::SetMaxSsrc (uint32_t maxSsrc) +{ + NS_LOG_FUNCTION (this << maxSsrc); + m_maxSsrc = maxSsrc; +} + +void +WifiRemoteStationManager::SetMaxSlrc (uint32_t maxSlrc) +{ + NS_LOG_FUNCTION (this << maxSlrc); + m_maxSlrc = maxSlrc; +} + +void +WifiRemoteStationManager::SetRtsCtsThreshold (uint32_t threshold) +{ + NS_LOG_FUNCTION (this << threshold); + m_rtsCtsThreshold = threshold; +} + +void +WifiRemoteStationManager::SetHtSupported (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_htSupported = enable; +} + +void +WifiRemoteStationManager::SetFragmentationThreshold (uint32_t threshold) +{ + NS_LOG_FUNCTION (this << threshold); + DoSetFragmentationThreshold (threshold); +} + +void +WifiRemoteStationManager::SetShortPreambleEnabled (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_shortPreambleEnabled = enable; +} + +void +WifiRemoteStationManager::SetShortSlotTimeEnabled (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_shortSlotTimeEnabled = enable; +} + +void +WifiRemoteStationManager::SetRifsPermitted (bool allow) +{ + NS_LOG_FUNCTION (this << allow); + m_rifsPermitted = allow; +} + +bool +WifiRemoteStationManager::GetShortSlotTimeEnabled (void) const +{ + return m_shortSlotTimeEnabled; +} + +bool +WifiRemoteStationManager::GetShortPreambleEnabled (void) const +{ + return m_shortPreambleEnabled; +} + +bool +WifiRemoteStationManager::GetRifsPermitted (void) const +{ + return m_rifsPermitted; +} + +bool +WifiRemoteStationManager::HasHtSupported (void) const +{ + return m_htSupported; +} + +void +WifiRemoteStationManager::SetVhtSupported (bool enable) +{ + m_vhtSupported = enable; +} + +bool +WifiRemoteStationManager::HasVhtSupported (void) const +{ + return m_vhtSupported; +} + +void +WifiRemoteStationManager::SetHeSupported (bool enable) +{ + m_heSupported = enable; +} + +bool +WifiRemoteStationManager::HasHeSupported (void) const +{ + return m_heSupported; +} + +void +WifiRemoteStationManager::SetPcfSupported (bool enable) +{ + m_pcfSupported = enable; +} + +bool +WifiRemoteStationManager::HasPcfSupported (void) const +{ + return m_pcfSupported; +} + +uint32_t +WifiRemoteStationManager::GetFragmentationThreshold (void) const +{ + return DoGetFragmentationThreshold (); +} + +void +WifiRemoteStationManager::AddSupportedPlcpPreamble (Mac48Address address, bool isShortPreambleSupported) +{ + NS_LOG_FUNCTION (this << address << isShortPreambleSupported); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_shortPreamble = isShortPreambleSupported; +} + +void +WifiRemoteStationManager::AddSupportedErpSlotTime (Mac48Address address, bool isShortSlotTimeSupported) +{ + NS_LOG_FUNCTION (this << address << isShortSlotTimeSupported); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_shortSlotTime = isShortSlotTimeSupported; +} + +void +WifiRemoteStationManager::AddSupportedMode (Mac48Address address, WifiMode mode) +{ + NS_LOG_FUNCTION (this << address << mode); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + for (WifiModeListIterator i = state->m_operationalRateSet.begin (); i != state->m_operationalRateSet.end (); i++) + { + if ((*i) == mode) + { + //already in. + return; + } + } + state->m_operationalRateSet.push_back (mode); +} + +void +WifiRemoteStationManager::AddAllSupportedModes (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_operationalRateSet.clear (); + for (uint8_t i = 0; i < m_wifiPhy->GetNModes (); i++) + { + state->m_operationalRateSet.push_back (m_wifiPhy->GetMode (i)); + if (m_wifiPhy->GetMode (i).IsMandatory ()) + { + AddBasicMode (m_wifiPhy->GetMode (i)); + } + } +} + +void +WifiRemoteStationManager::AddAllSupportedMcs (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_operationalMcsSet.clear (); + for (uint8_t i = 0; i < m_wifiPhy->GetNMcs (); i++) + { + state->m_operationalMcsSet.push_back (m_wifiPhy->GetMcs (i)); + } +} + +void +WifiRemoteStationManager::RemoveAllSupportedMcs (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_operationalMcsSet.clear (); +} + +void +WifiRemoteStationManager::AddSupportedMcs (Mac48Address address, WifiMode mcs) +{ + NS_LOG_FUNCTION (this << address << mcs); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + for (WifiModeListIterator i = state->m_operationalMcsSet.begin (); i != state->m_operationalMcsSet.end (); i++) + { + if ((*i) == mcs) + { + //already in. + return; + } + } + state->m_operationalMcsSet.push_back (mcs); +} + +bool +WifiRemoteStationManager::GetShortPreambleSupported (Mac48Address address) const +{ + return LookupState (address)->m_shortPreamble; +} + +bool +WifiRemoteStationManager::GetShortSlotTimeSupported (Mac48Address address) const +{ + return LookupState (address)->m_shortSlotTime; +} + +bool +WifiRemoteStationManager::GetQosSupported (Mac48Address address) const +{ + return LookupState (address)->m_qosSupported; +} + +bool +WifiRemoteStationManager::IsBrandNew (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return false; + } + return LookupState (address)->m_state == WifiRemoteStationState::BRAND_NEW; +} + +bool +WifiRemoteStationManager::IsAssociated (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return true; + } + return LookupState (address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK; +} + +bool +WifiRemoteStationManager::IsWaitAssocTxOk (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return false; + } + return LookupState (address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK; +} + +void +WifiRemoteStationManager::RecordWaitAssocTxOk (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::WAIT_ASSOC_TX_OK; +} + +void +WifiRemoteStationManager::RecordGotAssocTxOk (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::GOT_ASSOC_TX_OK; +} + +void +WifiRemoteStationManager::RecordGotAssocTxFailed (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::DISASSOC; +} + +void +WifiRemoteStationManager::RecordDisassociated (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::DISASSOC; +} + +void +WifiRemoteStationManager::PrepareForQueue (Mac48Address address, const WifiMacHeader *header, Ptr packet) +{ + NS_LOG_FUNCTION (this << address << *header << packet); + if (IsLowLatency () || address.IsGroup ()) + { + return; + } + WifiRemoteStation *station = Lookup (address, header); + WifiTxVector rts = DoGetRtsTxVector (station); + WifiTxVector data = DoGetDataTxVector (station); + WifiTxVector ctstoself = DoGetCtsToSelfTxVector (); + HighLatencyDataTxVectorTag datatag; + HighLatencyRtsTxVectorTag rtstag; + HighLatencyCtsToSelfTxVectorTag ctstoselftag; + //first, make sure that the tag is not here anymore. + ConstCast (packet)->RemovePacketTag (datatag); + ConstCast (packet)->RemovePacketTag (rtstag); + ConstCast (packet)->RemovePacketTag (ctstoselftag); + datatag = HighLatencyDataTxVectorTag (data); + rtstag = HighLatencyRtsTxVectorTag (rts); + ctstoselftag = HighLatencyCtsToSelfTxVectorTag (ctstoself); + //and then, add it back + packet->AddPacketTag (datatag); + packet->AddPacketTag (rtstag); + packet->AddPacketTag (ctstoselftag); +} + +uint16_t +WifiRemoteStationManager::GetChannelWidthForTransmission (WifiMode mode, uint16_t maxSupportedChannelWidth) +{ + NS_LOG_FUNCTION (mode << maxSupportedChannelWidth); + WifiModulationClass modulationClass = mode.GetModulationClass (); + if (maxSupportedChannelWidth > 20 + && (modulationClass == WifiModulationClass::WIFI_MOD_CLASS_OFDM // all non-HT OFDM control and management frames + || modulationClass == WifiModulationClass::WIFI_MOD_CLASS_ERP_OFDM)) // special case of beacons at 2.4 GHz + { + NS_LOG_LOGIC ("Channel width reduced to 20 MHz"); + return 20; + } + //at 2.4 GHz basic rate can be non-ERP DSSS + if (modulationClass == WifiModulationClass::WIFI_MOD_CLASS_DSSS + || modulationClass == WifiModulationClass::WIFI_MOD_CLASS_HR_DSSS) + { + return 22; + } + return maxSupportedChannelWidth; +} + +WifiTxVector +WifiRemoteStationManager::GetDataTxVector (Mac48Address address, const WifiMacHeader *header, Ptr packet) +{ + NS_LOG_FUNCTION (this << address << *header << packet); + if (!header->IsMgt () && address.IsGroup ()) + { + WifiMode mode = GetNonUnicastMode (); + WifiTxVector v; + v.SetMode (mode); + v.SetPreambleType (GetPreambleForTransmission (mode, address)); + v.SetTxPowerLevel (m_defaultTxPowerLevel); + v.SetChannelWidth (GetChannelWidthForTransmission (mode, m_wifiPhy->GetChannelWidth ())); + v.SetGuardInterval (ConvertGuardIntervalToNanoSeconds (mode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ())); + v.SetNTx (1); + v.SetNss (1); + v.SetNess (0); + v.SetStbc (m_wifiPhy->GetStbc ()); + return v; + } + if (!IsLowLatency ()) + { + HighLatencyDataTxVectorTag datatag; + bool found; + found = ConstCast (packet)->PeekPacketTag (datatag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return datatag.GetDataTxVector (); + } + WifiTxVector txVector = DoGetDataTxVector (Lookup (address, header)); + if (header->IsMgt ()) + { + //Use the lowest basic rate for management frames + WifiMode mgtMode; + if (GetNBasicModes () > 0) + { + mgtMode = GetBasicMode (0); + } + else + { + mgtMode = GetDefaultMode (); + } + txVector.SetMode (mgtMode); + txVector.SetPreambleType (GetPreambleForTransmission (mgtMode, address)); + txVector.SetChannelWidth (GetChannelWidthForTransmission (mgtMode, m_wifiPhy->GetChannelWidth ())); + txVector.SetGuardInterval (ConvertGuardIntervalToNanoSeconds (mgtMode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ())); + } + return txVector; +} + +WifiTxVector +WifiRemoteStationManager::GetCtsToSelfTxVector (const WifiMacHeader *header, + Ptr packet) +{ + NS_LOG_FUNCTION (this << *header << packet); + if (!IsLowLatency ()) + { + HighLatencyCtsToSelfTxVectorTag ctstoselftag; + bool found; + found = ConstCast (packet)->PeekPacketTag (ctstoselftag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return ctstoselftag.GetCtsToSelfTxVector (); + } + return DoGetCtsToSelfTxVector (); +} + +WifiTxVector +WifiRemoteStationManager::DoGetCtsToSelfTxVector (void) +{ + WifiMode defaultMode = GetDefaultMode (); + WifiPreamble defaultPreamble; + if (defaultMode.GetModulationClass () == WIFI_MOD_CLASS_HE) + { + defaultPreamble = WIFI_PREAMBLE_HE_SU; + } + else if (defaultMode.GetModulationClass () == WIFI_MOD_CLASS_VHT) + { + defaultPreamble = WIFI_PREAMBLE_VHT; + } + else if (defaultMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + defaultPreamble = WIFI_PREAMBLE_HT_MF; + } + else + { + defaultPreamble = WIFI_PREAMBLE_LONG; + } + + return WifiTxVector (defaultMode, + GetDefaultTxPowerLevel (), + defaultPreamble, + ConvertGuardIntervalToNanoSeconds (defaultMode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ()), + GetNumberOfAntennas (), + GetMaxNumberOfTransmitStreams (), + 0, + GetChannelWidthForTransmission (defaultMode, m_wifiPhy->GetChannelWidth ()), + false, + false); +} + +WifiTxVector +WifiRemoteStationManager::GetRtsTxVector (Mac48Address address, const WifiMacHeader *header, + Ptr packet) +{ + NS_LOG_FUNCTION (this << address << *header << packet); + NS_ASSERT (!address.IsGroup ()); + if (!IsLowLatency ()) + { + HighLatencyRtsTxVectorTag rtstag; + bool found; + found = ConstCast (packet)->PeekPacketTag (rtstag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return rtstag.GetRtsTxVector (); + } + return DoGetRtsTxVector (Lookup (address, header)); +} + +void +WifiRemoteStationManager::ReportRtsFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_ssrc++; + m_macTxRtsFailed (address); + DoReportRtsFailed (station); +} + +void +WifiRemoteStationManager::ReportDataFailed (Mac48Address address, const WifiMacHeader *header, + uint32_t packetSize) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + bool longMpdu = (packetSize + header->GetSize () + WIFI_MAC_FCS_LENGTH) > m_rtsCtsThreshold; + if (longMpdu) + { + station->m_slrc++; + } + else + { + station->m_ssrc++; + } + m_macTxDataFailed (address); + DoReportDataFailed (station); +} + +void +WifiRemoteStationManager::ReportRtsOk (Mac48Address address, const WifiMacHeader *header, + double ctsSnr, WifiMode ctsMode, double rtsSnr) +{ + NS_LOG_FUNCTION (this << address << *header << ctsSnr << ctsMode << rtsSnr); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxSuccess (station->m_ssrc); + station->m_ssrc = 0; + DoReportRtsOk (station, ctsSnr, ctsMode, rtsSnr); +} + +void +WifiRemoteStationManager::ReportDataOk (Mac48Address address, const WifiMacHeader *header, + double ackSnr, WifiMode ackMode, double dataSnr, + uint32_t packetSize) +{ + NS_LOG_FUNCTION (this << address << *header << ackSnr << ackMode << dataSnr); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + bool longMpdu = (packetSize + header->GetSize () + WIFI_MAC_FCS_LENGTH) > m_rtsCtsThreshold; + if (longMpdu) + { + station->m_state->m_info.NotifyTxSuccess (station->m_slrc); + station->m_slrc = 0; + } + else + { + station->m_state->m_info.NotifyTxSuccess (station->m_ssrc); + station->m_ssrc = 0; + } + DoReportDataOk (station, ackSnr, ackMode, dataSnr); +} + +void +WifiRemoteStationManager::ReportFinalRtsFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxFailed (); + station->m_ssrc = 0; + m_macTxFinalRtsFailed (address); + DoReportFinalRtsFailed (station); +} + +void +WifiRemoteStationManager::ReportFinalDataFailed (Mac48Address address, const WifiMacHeader *header, + uint32_t packetSize) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxFailed (); + bool longMpdu = (packetSize + header->GetSize () + WIFI_MAC_FCS_LENGTH) > m_rtsCtsThreshold; + if (longMpdu) + { + station->m_slrc = 0; + } + else + { + station->m_ssrc = 0; + } + m_macTxFinalDataFailed (address); + DoReportFinalDataFailed (station); +} + +void +WifiRemoteStationManager::ReportRxOk (Mac48Address address, const WifiMacHeader *header, + double rxSnr, WifiMode txMode) +{ + NS_LOG_FUNCTION (this << address << *header << rxSnr << txMode); + if (address.IsGroup ()) + { + return; + } + WifiRemoteStation *station = Lookup (address, header); + DoReportRxOk (station, rxSnr, txMode); +} + +void +WifiRemoteStationManager::ReportAmpduTxStatus (Mac48Address address, uint8_t tid, + uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, + double rxSnr, double dataSnr) +{ + NS_LOG_FUNCTION (this << address << +tid << +nSuccessfulMpdus << +nFailedMpdus << rxSnr << dataSnr); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, tid); + for (uint8_t i = 0; i < nFailedMpdus; i++) + { + m_macTxDataFailed (address); + } + DoReportAmpduTxStatus (station, nSuccessfulMpdus, nFailedMpdus, rxSnr, dataSnr); +} + +bool +WifiRemoteStationManager::NeedRts (Mac48Address address, const WifiMacHeader *header, + Ptr packet, WifiTxVector txVector) +{ + WifiMode mode = txVector.GetMode (); + NS_LOG_FUNCTION (this << address << *header << packet << mode); + if (address.IsGroup ()) + { + return false; + } + if (m_erpProtectionMode == RTS_CTS + && ((mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_HE)) + && m_useNonErpProtection) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations"); + return true; + } + else if (m_htProtectionMode == RTS_CTS + && ((mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)) + && m_useNonHtProtection + && !(m_erpProtectionMode != RTS_CTS && m_useNonErpProtection)) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations"); + return true; + } + bool normally = (packet->GetSize () + header->GetSize () + WIFI_MAC_FCS_LENGTH) > m_rtsCtsThreshold; + return DoNeedRts (Lookup (address, header), packet, normally); +} + +bool +WifiRemoteStationManager::NeedCtsToSelf (WifiTxVector txVector) +{ + WifiMode mode = txVector.GetMode (); + NS_LOG_FUNCTION (this << mode); + if (m_erpProtectionMode == CTS_TO_SELF + && ((mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_HE)) + && m_useNonErpProtection) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations"); + return true; + } + else if (m_htProtectionMode == CTS_TO_SELF + && ((mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)) + && m_useNonHtProtection + && !(m_erpProtectionMode != CTS_TO_SELF && m_useNonErpProtection)) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations"); + return true; + } + else if (!m_useNonErpProtection) + { + //search for the BSS Basic Rate set, if the used mode is in the basic set then there is no need for Cts To Self + for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++) + { + if (mode == *i) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false"); + return false; + } + } + if (HasHtSupported ()) + { + //search for the BSS Basic MCS set, if the used mode is in the basic set then there is no need for Cts To Self + for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++) + { + if (mode == *i) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false"); + return false; + } + } + } + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true"); + return true; + } + return false; +} + +void +WifiRemoteStationManager::SetUseNonErpProtection (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_useNonErpProtection = enable; +} + +bool +WifiRemoteStationManager::GetUseNonErpProtection (void) const +{ + return m_useNonErpProtection; +} + +void +WifiRemoteStationManager::SetUseNonHtProtection (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_useNonHtProtection = enable; +} + +bool +WifiRemoteStationManager::GetUseNonHtProtection (void) const +{ + return m_useNonHtProtection; +} + +void +WifiRemoteStationManager::SetUseGreenfieldProtection (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_useGreenfieldProtection = enable; +} + +bool +WifiRemoteStationManager::GetUseGreenfieldProtection (void) const +{ + return m_useGreenfieldProtection; +} + +bool +WifiRemoteStationManager::NeedRetransmission (Mac48Address address, const WifiMacHeader *header, + Ptr packet) +{ + NS_LOG_FUNCTION (this << address << packet << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + bool longMpdu = (packet->GetSize () + header->GetSize () + WIFI_MAC_FCS_LENGTH) > m_rtsCtsThreshold; + uint32_t retryCount, maxRetryCount; + if (longMpdu) + { + retryCount = station->m_slrc; + maxRetryCount = m_maxSlrc; + } + else + { + retryCount = station->m_ssrc; + maxRetryCount = m_maxSsrc; + } + bool normally = retryCount < maxRetryCount; + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedRetransmission count: " << retryCount << " result: " << std::boolalpha << normally); + return DoNeedRetransmission (station, packet, normally); +} + +bool +WifiRemoteStationManager::NeedFragmentation (Mac48Address address, const WifiMacHeader *header, + Ptr packet) +{ + NS_LOG_FUNCTION (this << address << packet << *header); + if (address.IsGroup ()) + { + return false; + } + WifiRemoteStation *station = Lookup (address, header); + bool normally = (packet->GetSize () + header->GetSize () + WIFI_MAC_FCS_LENGTH) > GetFragmentationThreshold (); + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha << normally); + return DoNeedFragmentation (station, packet, normally); +} + +void +WifiRemoteStationManager::DoSetFragmentationThreshold (uint32_t threshold) +{ + NS_LOG_FUNCTION (this << threshold); + if (threshold < 256) + { + /* + * ASN.1 encoding of the MAC and PHY MIB (256 ... 8000) + */ + NS_LOG_WARN ("Fragmentation threshold should be larger than 256. Setting to 256."); + m_nextFragmentationThreshold = 256; + } + else + { + /* + * The length of each fragment shall be an even number of octets, except for the last fragment if an MSDU or + * MMPDU, which may be either an even or an odd number of octets. + */ + if (threshold % 2 != 0) + { + NS_LOG_WARN ("Fragmentation threshold should be an even number. Setting to " << threshold - 1); + m_nextFragmentationThreshold = threshold - 1; + } + else + { + m_nextFragmentationThreshold = threshold; + } + } +} + +void +WifiRemoteStationManager::UpdateFragmentationThreshold (void) +{ + m_fragmentationThreshold = m_nextFragmentationThreshold; +} + +uint32_t +WifiRemoteStationManager::DoGetFragmentationThreshold (void) const +{ + return m_fragmentationThreshold; +} + +uint32_t +WifiRemoteStationManager::GetNFragments (const WifiMacHeader *header, Ptr packet) +{ + NS_LOG_FUNCTION (this << *header << packet); + //The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS). + uint32_t nFragments = (packet->GetSize () / (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)); + + //If the size of the last fragment is not 0. + if ((packet->GetSize () % (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)) > 0) + { + nFragments++; + } + NS_LOG_DEBUG ("WifiRemoteStationManager::GetNFragments returning " << nFragments); + return nFragments; +} + +uint32_t +WifiRemoteStationManager::GetFragmentSize (Mac48Address address, const WifiMacHeader *header, + Ptr packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + uint32_t nFragment = GetNFragments (header, packet); + if (fragmentNumber >= nFragment) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning 0"); + return 0; + } + //Last fragment + if (fragmentNumber == nFragment - 1) + { + uint32_t lastFragmentSize = packet->GetSize () - (fragmentNumber * (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)); + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize); + return lastFragmentSize; + } + //All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS). + else + { + uint32_t fragmentSize = GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH; + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize); + return fragmentSize; + } +} + +uint32_t +WifiRemoteStationManager::GetFragmentOffset (Mac48Address address, const WifiMacHeader *header, + Ptr packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + NS_ASSERT (fragmentNumber < GetNFragments (header, packet)); + uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH); + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset); + return fragmentOffset; +} + +bool +WifiRemoteStationManager::IsLastFragment (Mac48Address address, const WifiMacHeader *header, + Ptr packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + bool isLast = fragmentNumber == (GetNFragments (header, packet) - 1); + NS_LOG_DEBUG ("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast); + return isLast; +} + +bool +WifiRemoteStationManager::IsAllowedControlAnswerModulationClass (WifiModulationClass modClassReq, WifiModulationClass modClassAnswer) const +{ + switch (modClassReq) + { + case WIFI_MOD_CLASS_DSSS: + return (modClassAnswer == WIFI_MOD_CLASS_DSSS); + case WIFI_MOD_CLASS_HR_DSSS: + return (modClassAnswer == WIFI_MOD_CLASS_DSSS || modClassAnswer == WIFI_MOD_CLASS_HR_DSSS); + case WIFI_MOD_CLASS_ERP_OFDM: + return (modClassAnswer == WIFI_MOD_CLASS_DSSS || modClassAnswer == WIFI_MOD_CLASS_HR_DSSS || modClassAnswer == WIFI_MOD_CLASS_ERP_OFDM); + case WIFI_MOD_CLASS_OFDM: + return (modClassAnswer == WIFI_MOD_CLASS_OFDM); + case WIFI_MOD_CLASS_HT: + case WIFI_MOD_CLASS_VHT: + case WIFI_MOD_CLASS_HE: + return true; + default: + NS_FATAL_ERROR ("Modulation class not defined"); + return false; + } +} + +WifiMode +WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode reqMode) +{ + /** + * The standard has relatively unambiguous rules for selecting a + * control response rate (the below is quoted from IEEE 802.11-2012, + * Section 9.7): + * + * To allow the transmitting STA to calculate the contents of the + * Duration/ID field, a STA responding to a received frame shall + * transmit its Control Response frame (either CTS or ACK), other + * than the BlockAck control frame, at the highest rate in the + * BSSBasicRateSet parameter that is less than or equal to the + * rate of the immediately previous frame in the frame exchange + * sequence (as defined in Annex G) and that is of the same + * modulation class (see Section 9.7.8) as the received frame... + */ + NS_LOG_FUNCTION (this << address << reqMode); + WifiMode mode = GetDefaultMode (); + bool found = false; + //First, search the BSS Basic Rate set + for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++) + { + if ((!found || i->IsHigherDataRate (mode)) + && (!i->IsHigherDataRate (reqMode)) + && (IsAllowedControlAnswerModulationClass (reqMode.GetModulationClass (), i->GetModulationClass ()))) + { + mode = *i; + //We've found a potentially-suitable transmit rate, but we + //need to continue and consider all the basic rates before + //we can be sure we've got the right one. + found = true; + } + } + if (HasHtSupported () || HasVhtSupported () || HasHeSupported ()) + { + if (!found) + { + mode = GetDefaultMcs (); + for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++) + { + if ((!found || i->IsHigherDataRate (mode)) + && (!i->IsHigherDataRate (reqMode)) + && (i->GetModulationClass () == reqMode.GetModulationClass ())) + { + mode = *i; + //We've found a potentially-suitable transmit rate, but we + //need to continue and consider all the basic rates before + //we can be sure we've got the right one. + found = true; + } + } + } + } + //If we found a suitable rate in the BSSBasicRateSet, then we are + //done and can return that mode. + if (found) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::GetControlAnswerMode returning " << mode); + return mode; + } + + /** + * If no suitable basic rate was found, we search the mandatory + * rates. The standard (IEEE 802.11-2007, Section 9.6) says: + * + * ...If no rate contained in the BSSBasicRateSet parameter meets + * these conditions, then the control frame sent in response to a + * received frame shall be transmitted at the highest mandatory + * rate of the PHY that is less than or equal to the rate of the + * received frame, and that is of the same modulation class as the + * received frame. In addition, the Control Response frame shall + * be sent using the same PHY options as the received frame, + * unless they conflict with the requirement to use the + * BSSBasicRateSet parameter. + * + * \todo Note that we're ignoring the last sentence for now, because + * there is not yet any manipulation here of PHY options. + */ + for (uint8_t idx = 0; idx < m_wifiPhy->GetNModes (); idx++) + { + WifiMode thismode = m_wifiPhy->GetMode (idx); + /* If the rate: + * + * - is a mandatory rate for the PHY, and + * - is equal to or faster than our current best choice, and + * - is less than or equal to the rate of the received frame, and + * - is of the same modulation class as the received frame + * + * ...then it's our best choice so far. + */ + if (thismode.IsMandatory () + && (!found || thismode.IsHigherDataRate (mode)) + && (!thismode.IsHigherDataRate (reqMode)) + && (IsAllowedControlAnswerModulationClass (reqMode.GetModulationClass (), thismode.GetModulationClass ()))) + { + mode = thismode; + //As above; we've found a potentially-suitable transmit + //rate, but we need to continue and consider all the + //mandatory rates before we can be sure we've got the right one. + found = true; + } + } + if (HasHtSupported () || HasVhtSupported () || HasHeSupported ()) + { + for (uint8_t idx = 0; idx < m_wifiPhy->GetNMcs (); idx++) + { + WifiMode thismode = m_wifiPhy->GetMcs (idx); + if (thismode.IsMandatory () + && (!found || thismode.IsHigherDataRate (mode)) + && (!thismode.IsHigherCodeRate (reqMode)) + && (thismode.GetModulationClass () == reqMode.GetModulationClass ())) + { + mode = thismode; + //As above; we've found a potentially-suitable transmit + //rate, but we need to continue and consider all the + //mandatory rates before we can be sure we've got the right one. + found = true; + } + } + } + + /** + * If we still haven't found a suitable rate for the response then + * someone has messed up the simulation config. This probably means + * that the WifiPhyStandard is not set correctly, or that a rate that + * is not supported by the PHY has been explicitly requested in a + * WifiRemoteStationManager (or descendant) configuration. + * + * Either way, it is serious - we can either disobey the standard or + * fail, and I have chosen to do the latter... + */ + if (!found) + { + NS_FATAL_ERROR ("Can't find response rate for " << reqMode); + } + + NS_LOG_DEBUG ("WifiRemoteStationManager::GetControlAnswerMode returning " << mode); + return mode; +} + +WifiTxVector +WifiRemoteStationManager::GetCtsTxVector (Mac48Address address, WifiMode rtsMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiMode ctsMode = GetControlAnswerMode (address, rtsMode); + WifiTxVector v; + v.SetMode (ctsMode); + v.SetPreambleType (GetPreambleForTransmission (ctsMode, address)); + v.SetTxPowerLevel (DoGetCtsTxPowerLevel (address, ctsMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (ctsMode, DoGetCtsTxChannelWidth (address, ctsMode))); + v.SetGuardInterval (DoGetCtsTxGuardInterval (address, ctsMode)); + v.SetNss (DoGetCtsTxNss (address, ctsMode)); + v.SetNess (DoGetCtsTxNess (address, ctsMode)); + v.SetStbc (m_wifiPhy->GetStbc ()); + return v; +} + +WifiTxVector +WifiRemoteStationManager::GetAckTxVector (Mac48Address address, WifiMode dataMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiMode ackMode = GetControlAnswerMode (address, dataMode); + WifiTxVector v; + v.SetMode (ackMode); + v.SetPreambleType (GetPreambleForTransmission (ackMode, address)); + v.SetTxPowerLevel (DoGetAckTxPowerLevel (address, ackMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (ackMode, DoGetAckTxChannelWidth (address, ackMode))); + v.SetGuardInterval (DoGetAckTxGuardInterval (address, ackMode)); + v.SetNss (DoGetAckTxNss (address, ackMode)); + v.SetNess (DoGetAckTxNess (address, ackMode)); + v.SetStbc (m_wifiPhy->GetStbc ()); + return v; +} + +WifiTxVector +WifiRemoteStationManager::GetBlockAckTxVector (Mac48Address address, WifiMode blockAckReqMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiMode blockAckMode = GetControlAnswerMode (address, blockAckReqMode); + WifiTxVector v; + v.SetMode (blockAckMode); + v.SetPreambleType (GetPreambleForTransmission (blockAckMode, address)); + v.SetTxPowerLevel (DoGetBlockAckTxPowerLevel (address, blockAckMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (blockAckMode, DoGetBlockAckTxChannelWidth (address, blockAckMode))); + v.SetGuardInterval (DoGetBlockAckTxGuardInterval (address, blockAckMode)); + v.SetNss (DoGetBlockAckTxNss (address, blockAckMode)); + v.SetNess (DoGetBlockAckTxNess (address, blockAckMode)); + v.SetStbc (m_wifiPhy->GetStbc ()); + return v; +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxPowerLevel (Mac48Address address, WifiMode ctsMode) +{ + return m_defaultTxPowerLevel; +} + +uint16_t +WifiRemoteStationManager::DoGetCtsTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +uint16_t +WifiRemoteStationManager::DoGetCtsTxGuardInterval (Mac48Address address, WifiMode ctsMode) +{ + return ConvertGuardIntervalToNanoSeconds (ctsMode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ()); +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxNss (Mac48Address address, WifiMode ctsMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxNess (Mac48Address address, WifiMode ctsMode) +{ + return 0; +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxPowerLevel (Mac48Address address, WifiMode ackMode) +{ + return m_defaultTxPowerLevel; +} + +uint16_t +WifiRemoteStationManager::DoGetAckTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +uint16_t +WifiRemoteStationManager::DoGetAckTxGuardInterval (Mac48Address address, WifiMode ackMode) +{ + return ConvertGuardIntervalToNanoSeconds (ackMode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ()); +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxNss (Mac48Address address, WifiMode ackMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxNess (Mac48Address address, WifiMode ackMode) +{ + return 0; +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxPowerLevel (Mac48Address address, WifiMode blockAckMode) +{ + return m_defaultTxPowerLevel; +} + +uint16_t +WifiRemoteStationManager::DoGetBlockAckTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +uint16_t +WifiRemoteStationManager::DoGetBlockAckTxGuardInterval (Mac48Address address, WifiMode blockAckMode) +{ + return ConvertGuardIntervalToNanoSeconds (blockAckMode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ()); +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxNss (Mac48Address address, WifiMode blockAckMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxNess (Mac48Address address, WifiMode blockAckMode) +{ + return 0; +} + +uint8_t +WifiRemoteStationManager::GetDefaultTxPowerLevel (void) const +{ + return m_defaultTxPowerLevel; +} + +WifiRemoteStationInfo +WifiRemoteStationManager::GetInfo (Mac48Address address) +{ + WifiRemoteStationState *state = LookupState (address); + return state->m_info; +} + +WifiRemoteStationState * +WifiRemoteStationManager::LookupState (Mac48Address address) const +{ + NS_LOG_FUNCTION (this << address); + for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) + { + if ((*i)->m_address == address) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning existing state"); + return (*i); + } + } + WifiRemoteStationState *state = new WifiRemoteStationState (); + state->m_state = WifiRemoteStationState::BRAND_NEW; + state->m_address = address; + state->m_operationalRateSet.push_back (GetDefaultMode ()); + state->m_operationalMcsSet.push_back (GetDefaultMcs ()); + state->m_channelWidth = m_wifiPhy->GetChannelWidth (); + state->m_shortGuardInterval = m_wifiPhy->GetShortGuardInterval (); + state->m_guardInterval = static_cast (m_wifiPhy->GetGuardInterval ().GetNanoSeconds ()); + state->m_greenfield = m_wifiPhy->GetGreenfield (); + state->m_streams = 1; + state->m_ness = 0; + state->m_aggregation = false; + state->m_stbc = false; + state->m_ldpc = false; + state->m_qosSupported = false; + state->m_htSupported = false; + state->m_vhtSupported = false; + state->m_heSupported = false; + const_cast (this)->m_states.push_back (state); + NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning new state"); + return state; +} + +WifiRemoteStation * +WifiRemoteStationManager::Lookup (Mac48Address address, const WifiMacHeader *header) const +{ + uint8_t tid; + if (header->IsQosData ()) + { + tid = header->GetQosTid (); + } + else + { + tid = 0; + } + return Lookup (address, tid); +} + +WifiRemoteStation * +WifiRemoteStationManager::Lookup (Mac48Address address, uint8_t tid) const +{ + NS_LOG_FUNCTION (this << address << +tid); + for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + if ((*i)->m_tid == tid + && (*i)->m_state->m_address == address) + { + return (*i); + } + } + WifiRemoteStationState *state = LookupState (address); + + WifiRemoteStation *station = DoCreateStation (); + station->m_state = state; + station->m_tid = tid; + station->m_ssrc = 0; + station->m_slrc = 0; + const_cast (this)->m_stations.push_back (station); + return station; +} + +void +WifiRemoteStationManager::SetQosSupport (Mac48Address from, bool qosSupported) +{ + NS_LOG_FUNCTION (this << from << qosSupported); + WifiRemoteStationState *state; + state = LookupState (from); + state->m_qosSupported = qosSupported; +} + +void +WifiRemoteStationManager::AddStationHtCapabilities (Mac48Address from, HtCapabilities htCapabilities) +{ + //Used by all stations to record HT capabilities of remote stations + NS_LOG_FUNCTION (this << from << htCapabilities); + WifiRemoteStationState *state; + state = LookupState (from); + state->m_shortGuardInterval = htCapabilities.GetShortGuardInterval20 (); + if (htCapabilities.GetSupportedChannelWidth () == 1) + { + state->m_channelWidth = 40; + } + else + { + state->m_channelWidth = 20; + } + SetQosSupport (from, true); + state->m_greenfield = htCapabilities.GetGreenfield (); + state->m_streams = htCapabilities.GetRxHighestSupportedAntennas (); + for (uint8_t j = 0; j < m_wifiPhy->GetNMcs (); j++) + { + WifiMode mcs = m_wifiPhy->GetMcs (j); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_HT && htCapabilities.IsSupportedMcs (mcs.GetMcsValue ())) + { + AddSupportedMcs (from, mcs); + } + } + state->m_htSupported = true; +} + +void +WifiRemoteStationManager::AddStationVhtCapabilities (Mac48Address from, VhtCapabilities vhtCapabilities) +{ + //Used by all stations to record VHT capabilities of remote stations + NS_LOG_FUNCTION (this << from << vhtCapabilities); + WifiRemoteStationState *state; + state = LookupState (from); + if (vhtCapabilities.GetSupportedChannelWidthSet () == 1) + { + state->m_channelWidth = 160; + } + else + { + state->m_channelWidth = 80; + } + //This is a workaround to enable users to force a 20 or 40 MHz channel for a VHT-compliant device, + //since IEEE 802.11ac standard says that 20, 40 and 80 MHz channels are mandatory. + if (m_wifiPhy->GetChannelWidth () < state->m_channelWidth) + { + state->m_channelWidth = m_wifiPhy->GetChannelWidth (); + } + state->m_ldpc = (vhtCapabilities.GetRxLdpc () != 0); + state->m_stbc = (vhtCapabilities.GetTxStbc () != 0 || vhtCapabilities.GetRxStbc () != 0); + for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams (); i++) + { + for (uint8_t j = 0; j < m_wifiPhy->GetNMcs (); j++) + { + WifiMode mcs = m_wifiPhy->GetMcs (j); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_VHT && vhtCapabilities.IsSupportedMcs (mcs.GetMcsValue (), i)) + { + AddSupportedMcs (from, mcs); + } + } + } + state->m_vhtSupported = true; +} + +void +WifiRemoteStationManager::AddStationHeCapabilities (Mac48Address from, HeCapabilities heCapabilities) +{ + //Used by all stations to record HE capabilities of remote stations + NS_LOG_FUNCTION (this << from << heCapabilities); + WifiRemoteStationState *state; + state = LookupState (from); + if (Is5Ghz (m_wifiPhy->GetFrequency ())) + { + if (heCapabilities.GetChannelWidthSet () & 0x04) + { + state->m_channelWidth = 160; + } + else if (heCapabilities.GetChannelWidthSet () & 0x02) + { + state->m_channelWidth = 80; + } + //For other cases at 5 GHz, the supported channel width is set by the VHT capabilities + } + else if (Is2_4Ghz (m_wifiPhy->GetFrequency ())) + { + if (heCapabilities.GetChannelWidthSet () & 0x01) + { + state->m_channelWidth = 40; + } + else + { + state->m_channelWidth = 20; + } + } + if (heCapabilities.GetHeLtfAndGiForHePpdus () >= 2) + { + state->m_guardInterval = 800; + } + else if (heCapabilities.GetHeLtfAndGiForHePpdus () == 1) + { + state->m_guardInterval = 1600; + } + else + { + state->m_guardInterval = 3200; + } + for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams (); i++) + { + for (uint8_t j = 0; j < m_wifiPhy->GetNMcs (); j++) + { + WifiMode mcs = m_wifiPhy->GetMcs (j); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_HE + && heCapabilities.GetHighestNssSupported () >= i + && heCapabilities.GetHighestMcsSupported () >= j) + { + AddSupportedMcs (from, mcs); + } + } + } + state->m_heSupported = true; + SetQosSupport (from, true); +} + +bool +WifiRemoteStationManager::GetGreenfieldSupported (Mac48Address address) const +{ + return LookupState (address)->m_greenfield; +} + +WifiMode +WifiRemoteStationManager::GetDefaultMode (void) const +{ + return m_defaultTxMode; +} + +WifiMode +WifiRemoteStationManager::GetDefaultMcs (void) const +{ + return m_defaultTxMcs; +} + +void +WifiRemoteStationManager::Reset (void) +{ + NS_LOG_FUNCTION (this); + for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) + { + delete (*i); + } + m_states.clear (); + for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + delete (*i); + } + m_stations.clear (); + m_bssBasicRateSet.clear (); + m_bssBasicMcsSet.clear (); +} + +void +WifiRemoteStationManager::AddBasicMode (WifiMode mode) +{ + NS_LOG_FUNCTION (this << mode); + if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT || mode.GetModulationClass () == WIFI_MOD_CLASS_VHT || mode.GetModulationClass () == WIFI_MOD_CLASS_HE) + { + NS_FATAL_ERROR ("It is not allowed to add a (V)HT rate in the BSSBasicRateSet!"); + } + for (uint8_t i = 0; i < GetNBasicModes (); i++) + { + if (GetBasicMode (i) == mode) + { + return; + } + } + m_bssBasicRateSet.push_back (mode); +} + +uint8_t +WifiRemoteStationManager::GetNBasicModes (void) const +{ + return static_cast (m_bssBasicRateSet.size ()); +} + +WifiMode +WifiRemoteStationManager::GetBasicMode (uint8_t i) const +{ + NS_ASSERT (i < GetNBasicModes ()); + return m_bssBasicRateSet[i]; +} + +uint32_t +WifiRemoteStationManager::GetNNonErpBasicModes (void) const +{ + uint32_t size = 0; + for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++) + { + if (i->GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + { + continue; + } + size++; + } + return size; +} + +WifiMode +WifiRemoteStationManager::GetNonErpBasicMode (uint8_t i) const +{ + NS_ASSERT (i < GetNNonErpBasicModes ()); + uint32_t index = 0; + bool found = false; + for (WifiModeListIterator j = m_bssBasicRateSet.begin (); j != m_bssBasicRateSet.end (); ) + { + if (i == index) + { + found = true; + } + if (j->GetModulationClass () != WIFI_MOD_CLASS_ERP_OFDM) + { + if (found) + { + break; + } + } + index++; + j++; + } + return m_bssBasicRateSet[index]; +} + +void +WifiRemoteStationManager::AddBasicMcs (WifiMode mcs) +{ + NS_LOG_FUNCTION (this << +mcs.GetMcsValue ()); + for (uint8_t i = 0; i < GetNBasicMcs (); i++) + { + if (GetBasicMcs (i) == mcs) + { + return; + } + } + m_bssBasicMcsSet.push_back (mcs); +} + +uint8_t +WifiRemoteStationManager::GetNBasicMcs (void) const +{ + return static_cast (m_bssBasicMcsSet.size ()); +} + +WifiMode +WifiRemoteStationManager::GetBasicMcs (uint8_t i) const +{ + NS_ASSERT (i < GetNBasicMcs ()); + return m_bssBasicMcsSet[i]; +} + +WifiMode +WifiRemoteStationManager::GetNonUnicastMode (void) const +{ + if (m_nonUnicastMode == WifiMode ()) + { + if (GetNBasicModes () > 0) + { + return GetBasicMode (0); + } + else + { + return GetDefaultMode (); + } + } + else + { + return m_nonUnicastMode; + } +} + +bool +WifiRemoteStationManager::DoNeedRts (WifiRemoteStation *station, + Ptr packet, bool normally) +{ + return normally; +} + +bool +WifiRemoteStationManager::DoNeedRetransmission (WifiRemoteStation *station, + Ptr packet, bool normally) +{ + return normally; +} + +bool +WifiRemoteStationManager::DoNeedFragmentation (WifiRemoteStation *station, + Ptr packet, bool normally) +{ + return normally; +} + +void +WifiRemoteStationManager::DoReportAmpduTxStatus (WifiRemoteStation *station, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr) +{ + NS_LOG_DEBUG ("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!"); +} + +WifiMode +WifiRemoteStationManager::GetSupported (const WifiRemoteStation *station, uint8_t i) const +{ + NS_ASSERT (i < GetNSupported (station)); + return station->m_state->m_operationalRateSet[i]; +} + +WifiMode +WifiRemoteStationManager::GetMcsSupported (const WifiRemoteStation *station, uint8_t i) const +{ + //std::cout<<"NMcs:"<m_state->m_operationalMcsSet[i]; +} + +WifiMode +WifiRemoteStationManager::GetNonErpSupported (const WifiRemoteStation *station, uint8_t i) const +{ + NS_ASSERT (i < GetNNonErpSupported (station)); + //IEEE 802.11g standard defines that if the protection mechanism is enabled, Rts, Cts and Cts-To-Self + //frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b basic rate. + //This is a implemented here to avoid changes in every RAA, but should maybe be moved in case it breaks standard rules. + uint32_t index = 0; + bool found = false; + for (WifiModeListIterator j = station->m_state->m_operationalRateSet.begin (); j != station->m_state->m_operationalRateSet.end (); ) + { + if (i == index) + { + found = true; + } + if (j->GetModulationClass () != WIFI_MOD_CLASS_ERP_OFDM) + { + if (found) + { + break; + } + } + index++; + j++; + } + return station->m_state->m_operationalRateSet[index]; +} + +Mac48Address +WifiRemoteStationManager::GetAddress (const WifiRemoteStation *station) const +{ + return station->m_state->m_address; +} + +uint16_t +WifiRemoteStationManager::GetChannelWidth (const WifiRemoteStation *station) const +{ + return station->m_state->m_channelWidth; +} + +bool +WifiRemoteStationManager::GetShortGuardInterval (const WifiRemoteStation *station) const +{ + return station->m_state->m_shortGuardInterval; +} + +uint16_t +WifiRemoteStationManager::GetGuardInterval (const WifiRemoteStation *station) const +{ + return station->m_state->m_guardInterval; +} + +bool +WifiRemoteStationManager::GetGreenfield (const WifiRemoteStation *station) const +{ + return station->m_state->m_greenfield; +} + +bool +WifiRemoteStationManager::GetAggregation (const WifiRemoteStation *station) const +{ + return station->m_state->m_aggregation; +} + +uint8_t +WifiRemoteStationManager::GetNumberOfSupportedStreams (const WifiRemoteStation *station) const +{ + return station->m_state->m_streams; +} + +uint8_t +WifiRemoteStationManager::GetNess (const WifiRemoteStation *station) const +{ + return station->m_state->m_ness; +} + +Ptr +WifiRemoteStationManager::GetPhy (void) const +{ + return m_wifiPhy; +} + +Ptr +WifiRemoteStationManager::GetMac (void) const +{ + return m_wifiMac; +} + +uint8_t +WifiRemoteStationManager::GetNSupported (const WifiRemoteStation *station) const +{ + return static_cast (station->m_state->m_operationalRateSet.size ()); +} + +bool +WifiRemoteStationManager::GetQosSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_qosSupported; +} + +bool +WifiRemoteStationManager::GetHtSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_htSupported; +} + +bool +WifiRemoteStationManager::GetVhtSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_vhtSupported; +} + +bool +WifiRemoteStationManager::GetHeSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_heSupported; +} + +uint8_t +WifiRemoteStationManager::GetNMcsSupported (const WifiRemoteStation *station) const +{ + return static_cast (station->m_state->m_operationalMcsSet.size ()); +} + +uint32_t +WifiRemoteStationManager::GetNNonErpSupported (const WifiRemoteStation *station) const +{ + uint32_t size = 0; + for (WifiModeListIterator i = station->m_state->m_operationalRateSet.begin (); i != station->m_state->m_operationalRateSet.end (); i++) + { + if (i->GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + { + continue; + } + size++; + } + return size; +} + +uint16_t +WifiRemoteStationManager::GetChannelWidthSupported (Mac48Address address) const +{ + return LookupState (address)->m_channelWidth; +} + +bool +WifiRemoteStationManager::GetShortGuardInterval (Mac48Address address) const +{ + return LookupState (address)->m_shortGuardInterval; +} + +uint8_t +WifiRemoteStationManager::GetNumberOfSupportedStreams (Mac48Address address) const +{ + return LookupState (address)->m_streams; +} + +uint8_t +WifiRemoteStationManager::GetNMcsSupported (Mac48Address address) const +{ + return static_cast (LookupState (address)->m_operationalMcsSet.size ()); +} + +bool +WifiRemoteStationManager::GetHtSupported (Mac48Address address) const +{ + return LookupState (address)->m_htSupported; +} + +bool +WifiRemoteStationManager::GetVhtSupported (Mac48Address address) const +{ + return LookupState (address)->m_vhtSupported; +} + +void +WifiRemoteStationManager::SetDefaultTxPowerLevel (uint8_t txPower) +{ + m_defaultTxPowerLevel = txPower; +} + +uint8_t +WifiRemoteStationManager::GetNumberOfAntennas (void) +{ + return m_wifiPhy->GetNumberOfAntennas (); +} + +uint8_t +WifiRemoteStationManager::GetMaxNumberOfTransmitStreams (void) +{ + return m_wifiPhy->GetMaxSupportedTxSpatialStreams (); +} + +WifiPreamble +WifiRemoteStationManager::GetPreambleForTransmission (WifiMode mode, Mac48Address dest) +{ + NS_LOG_FUNCTION (this << mode << dest); + WifiPreamble preamble; + if (mode.GetModulationClass () == WIFI_MOD_CLASS_HE) + { + preamble = WIFI_PREAMBLE_HE_SU; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_VHT) + { + preamble = WIFI_PREAMBLE_VHT; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT && m_wifiPhy->GetGreenfield () && GetGreenfieldSupported (dest) && !GetUseGreenfieldProtection ()) + { + //If protection for greenfield is used we go for HT_MF preamble which is the default protection for GF format defined in the standard. + preamble = WIFI_PREAMBLE_HT_GF; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + preamble = WIFI_PREAMBLE_HT_MF; + } + else if (GetShortPreambleEnabled ()) + { + preamble = WIFI_PREAMBLE_SHORT; + } + else + { + preamble = WIFI_PREAMBLE_LONG; + } + NS_LOG_DEBUG ("selected preamble=" << preamble); + return preamble; +} + +WifiRemoteStation::~WifiRemoteStation () +{ + NS_LOG_FUNCTION (this); +} + +WifiRemoteStationInfo::WifiRemoteStationInfo () + : m_memoryTime (Seconds (1.0)), + m_lastUpdate (Seconds (0.0)), + m_failAvg (0.0) +{ + NS_LOG_FUNCTION (this); +} + +double +WifiRemoteStationInfo::CalculateAveragingCoefficient () +{ + double retval = std::exp (static_cast (m_lastUpdate.GetMicroSeconds () - Simulator::Now ().GetMicroSeconds ()) / m_memoryTime.GetMicroSeconds ()); + m_lastUpdate = Simulator::Now (); + return retval; +} + +void +WifiRemoteStationInfo::NotifyTxSuccess (uint32_t retryCounter) +{ + double coefficient = CalculateAveragingCoefficient (); + m_failAvg = static_cast (retryCounter) / (1 + retryCounter) * (1 - coefficient) + coefficient * m_failAvg; +} + +void +WifiRemoteStationInfo::NotifyTxFailed () +{ + double coefficient = CalculateAveragingCoefficient (); + m_failAvg = (1 - coefficient) + coefficient * m_failAvg; +} + +double +WifiRemoteStationInfo::GetFrameErrorRate () const +{ + return m_failAvg; +} + +} //namespace ns3