wifi: Increase modularization of RrMultiUserScheduler
This commit is contained in:
committed by
Stefano Avallone
parent
693517ce0f
commit
f6e1f84e50
@@ -182,6 +182,32 @@ MultiUserScheduler::GetUlMuInfo (void)
|
||||
return m_ulInfo;
|
||||
}
|
||||
|
||||
Ptr<WifiMacQueueItem>
|
||||
MultiUserScheduler::GetTriggerFrame (const CtrlTriggerHeader& trigger) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
packet->AddHeader (trigger);
|
||||
|
||||
Mac48Address receiver = Mac48Address::GetBroadcast ();
|
||||
if (trigger.GetNUserInfoFields () == 1)
|
||||
{
|
||||
auto aid = trigger.begin ()->GetAid12 ();
|
||||
auto aidAddrMapIt = m_apMac->GetStaList ().find (aid);
|
||||
NS_ASSERT (aidAddrMapIt != m_apMac->GetStaList ().end ());
|
||||
receiver = aidAddrMapIt->second;
|
||||
}
|
||||
|
||||
WifiMacHeader hdr (WIFI_MAC_CTL_TRIGGER);
|
||||
hdr.SetAddr1 (receiver);
|
||||
hdr.SetAddr2 (m_apMac->GetAddress ());
|
||||
hdr.SetDsNotTo ();
|
||||
hdr.SetDsNotFrom ();
|
||||
|
||||
return Create<WifiMacQueueItem> (packet, hdr);
|
||||
}
|
||||
|
||||
void
|
||||
MultiUserScheduler::CheckTriggerFrame (void)
|
||||
{
|
||||
|
||||
@@ -120,6 +120,14 @@ protected:
|
||||
*/
|
||||
Ptr<WifiRemoteStationManager> GetWifiRemoteStationManager (void) const;
|
||||
|
||||
/**
|
||||
* Get an MPDU containing the given Trigger Frame.
|
||||
*
|
||||
* \param trigger the given Trigger Frame
|
||||
* \return an MPDU containing the given Trigger Frame
|
||||
*/
|
||||
Ptr<WifiMacQueueItem> GetTriggerFrame (const CtrlTriggerHeader& trigger) const;
|
||||
|
||||
/**
|
||||
* Get the format of the last transmission, as determined by the last call
|
||||
* to NotifyAccessGranted that did not return NO_TX.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "he-configuration.h"
|
||||
#include "he-phy.h"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -171,27 +172,12 @@ RrMultiUserScheduler::TrySendingBsrpTf (void)
|
||||
WifiTxVector txVector = GetDlMuInfo ().txParams.m_txVector;
|
||||
txVector.SetGuardInterval (m_trigger.GetGuardInterval ());
|
||||
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
packet->AddHeader (m_trigger);
|
||||
|
||||
Mac48Address receiver = Mac48Address::GetBroadcast ();
|
||||
if (m_trigger.GetNUserInfoFields () == 1)
|
||||
{
|
||||
NS_ASSERT (m_apMac->GetStaList ().find (m_trigger.begin ()->GetAid12 ()) != m_apMac->GetStaList ().end ());
|
||||
receiver = m_apMac->GetStaList ().at (m_trigger.begin ()->GetAid12 ());
|
||||
}
|
||||
|
||||
m_triggerMacHdr = WifiMacHeader (WIFI_MAC_CTL_TRIGGER);
|
||||
m_triggerMacHdr.SetAddr1 (receiver);
|
||||
m_triggerMacHdr.SetAddr2 (m_apMac->GetAddress ());
|
||||
m_triggerMacHdr.SetDsNotTo ();
|
||||
m_triggerMacHdr.SetDsNotFrom ();
|
||||
|
||||
Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (packet, m_triggerMacHdr);
|
||||
auto item = GetTriggerFrame (m_trigger);
|
||||
m_triggerMacHdr = item->GetHeader ();
|
||||
|
||||
m_txParams.Clear ();
|
||||
// set the TXVECTOR used to send the Trigger Frame
|
||||
m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (receiver);
|
||||
m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (m_triggerMacHdr.GetAddr1 ());
|
||||
|
||||
if (!m_heFem->TryAddMpdu (item, m_txParams, m_availableTime))
|
||||
{
|
||||
@@ -343,22 +329,8 @@ RrMultiUserScheduler::TrySendingBasicTf (void)
|
||||
AssignRuIndices (txVector);
|
||||
|
||||
m_trigger = CtrlTriggerHeader (TriggerFrameType::BASIC_TRIGGER, txVector);
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
packet->AddHeader (m_trigger);
|
||||
|
||||
Mac48Address receiver = Mac48Address::GetBroadcast ();
|
||||
if (ulCandidates.size () == 1)
|
||||
{
|
||||
receiver = ulCandidates.begin ()->second.first->address;
|
||||
}
|
||||
|
||||
m_triggerMacHdr = WifiMacHeader (WIFI_MAC_CTL_TRIGGER);
|
||||
m_triggerMacHdr.SetAddr1 (receiver);
|
||||
m_triggerMacHdr.SetAddr2 (m_apMac->GetAddress ());
|
||||
m_triggerMacHdr.SetDsNotTo ();
|
||||
m_triggerMacHdr.SetDsNotFrom ();
|
||||
|
||||
Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (packet, m_triggerMacHdr);
|
||||
auto item = GetTriggerFrame (m_trigger);
|
||||
m_triggerMacHdr = item->GetHeader ();
|
||||
|
||||
// compute the maximum amount of time that can be granted to stations.
|
||||
// This value is limited by the max PPDU duration
|
||||
@@ -366,7 +338,7 @@ RrMultiUserScheduler::TrySendingBasicTf (void)
|
||||
|
||||
m_txParams.Clear ();
|
||||
// set the TXVECTOR used to send the Trigger Frame
|
||||
m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (receiver);
|
||||
m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (m_triggerMacHdr.GetAddr1 ());
|
||||
|
||||
if (!m_heFem->TryAddMpdu (item, m_txParams, m_availableTime))
|
||||
{
|
||||
@@ -623,20 +595,15 @@ RrMultiUserScheduler::TrySendingDlMuPpdu (void)
|
||||
return TxFormat::DL_MU_TX;
|
||||
}
|
||||
|
||||
MultiUserScheduler::DlMuInfo
|
||||
RrMultiUserScheduler::ComputeDlMuInfo (void)
|
||||
void
|
||||
RrMultiUserScheduler::FinalizeTxVector (WifiTxVector& txVector)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_candidates.empty ())
|
||||
{
|
||||
return DlMuInfo ();
|
||||
}
|
||||
|
||||
uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
|
||||
NS_LOG_FUNCTION (this << txVector);
|
||||
NS_ASSERT (txVector.GetHeMuUserInfoMap ().size () == m_candidates.size ());
|
||||
|
||||
// compute how many stations can be granted an RU and the RU size
|
||||
std::size_t nRusAssigned = m_txParams.GetPsduInfoMap ().size ();
|
||||
auto bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
|
||||
std::size_t nRusAssigned = m_candidates.size ();
|
||||
std::size_t nCentral26TonesRus;
|
||||
HeRu::RuType ruType = HeRu::GetEqualSizedRusForStations (bw, nRusAssigned, nCentral26TonesRus);
|
||||
|
||||
@@ -652,35 +619,92 @@ RrMultiUserScheduler::ComputeDlMuInfo (void)
|
||||
NS_LOG_DEBUG (nCentral26TonesRus << " stations are being assigned a 26-tones RU");
|
||||
}
|
||||
|
||||
DlMuInfo dlMuInfo;
|
||||
|
||||
// We have to update the TXVECTOR
|
||||
dlMuInfo.txParams.m_txVector.SetPreambleType (m_txParams.m_txVector.GetPreambleType ());
|
||||
dlMuInfo.txParams.m_txVector.SetChannelWidth (m_txParams.m_txVector.GetChannelWidth ());
|
||||
dlMuInfo.txParams.m_txVector.SetGuardInterval (m_txParams.m_txVector.GetGuardInterval ());
|
||||
dlMuInfo.txParams.m_txVector.SetBssColor (m_txParams.m_txVector.GetBssColor ());
|
||||
// re-allocate RUs based on the actual number of candidate stations
|
||||
WifiTxVector::HeMuUserInfoMap heMuUserInfoMap;
|
||||
std::swap (heMuUserInfoMap, txVector.GetHeMuUserInfoMap ());
|
||||
|
||||
auto candidateIt = m_candidates.begin (); // iterator over the list of candidate receivers
|
||||
auto ruSet = HeRu::GetRusOfType (bw, ruType);
|
||||
auto ruSetIt = ruSet.begin ();
|
||||
auto central26TonesRus = HeRu::GetCentral26TonesRus (bw, ruType);
|
||||
auto central26TonesRusIt = central26TonesRus.begin ();
|
||||
|
||||
for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
|
||||
{
|
||||
NS_ASSERT (candidateIt != m_candidates.end ());
|
||||
auto mapIt = heMuUserInfoMap.find (candidateIt->first->aid);
|
||||
NS_ASSERT (mapIt != heMuUserInfoMap.end ());
|
||||
|
||||
uint16_t staId = candidateIt->first->aid;
|
||||
// AssignRuIndices will be called below to set RuSpec
|
||||
dlMuInfo.txParams.m_txVector.SetHeMuUserInfo (staId,
|
||||
{{(i < nRusAssigned ? ruType : HeRu::RU_26_TONE), 1, false},
|
||||
m_txParams.m_txVector.GetMode (staId),
|
||||
m_txParams.m_txVector.GetNss (staId)});
|
||||
txVector.SetHeMuUserInfo (mapIt->first,
|
||||
{(i < nRusAssigned ? *ruSetIt++ : *central26TonesRusIt++),
|
||||
mapIt->second.mcs, mapIt->second.nss});
|
||||
candidateIt++;
|
||||
}
|
||||
|
||||
// remove candidates that will not be served
|
||||
m_candidates.erase (candidateIt, m_candidates.end ());
|
||||
}
|
||||
|
||||
void
|
||||
RrMultiUserScheduler::UpdateCredits (std::list<MasterInfo>& staList, Time txDuration,
|
||||
const WifiTxVector& txVector)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << txDuration.As (Time::US) << txVector);
|
||||
|
||||
// find how many RUs have been allocated for each RU type
|
||||
std::map<HeRu::RuType, std::size_t> ruMap;
|
||||
for (const auto& userInfo : txVector.GetHeMuUserInfoMap ())
|
||||
{
|
||||
ruMap.insert ({userInfo.second.ru.GetRuType (), 0}).first->second++;
|
||||
}
|
||||
|
||||
// The amount of credits received by each station equals the TX duration (in
|
||||
// microseconds) divided by the number of stations.
|
||||
double creditsPerSta = txDuration.ToDouble (Time::US) / staList.size ();
|
||||
// Transmitting stations have to pay a number of credits equal to the TX duration
|
||||
// (in microseconds) times the allocated bandwidth share.
|
||||
double debitsPerMhz = txDuration.ToDouble (Time::US)
|
||||
/ std::accumulate (ruMap.begin (), ruMap.end (), 0,
|
||||
[](uint16_t sum, auto pair)
|
||||
{ return sum + pair.second * HeRu::GetBandwidth (pair.first); });
|
||||
|
||||
// assign credits to all stations
|
||||
for (auto& sta : staList)
|
||||
{
|
||||
sta.credits += creditsPerSta;
|
||||
sta.credits = std::min (sta.credits, m_maxCredits.ToDouble (Time::US));
|
||||
}
|
||||
|
||||
// subtract debits to the selected stations
|
||||
for (auto& candidate : m_candidates)
|
||||
{
|
||||
auto mapIt = txVector.GetHeMuUserInfoMap ().find (candidate.first->aid);
|
||||
NS_ASSERT (mapIt != txVector.GetHeMuUserInfoMap ().end ());
|
||||
|
||||
candidate.first->credits -= debitsPerMhz * HeRu::GetBandwidth (mapIt->second.ru.GetRuType ());
|
||||
}
|
||||
|
||||
// sort the list in decreasing order of credits
|
||||
staList.sort ([] (const MasterInfo& a, const MasterInfo& b)
|
||||
{ return a.credits > b.credits; });
|
||||
|
||||
}
|
||||
|
||||
MultiUserScheduler::DlMuInfo
|
||||
RrMultiUserScheduler::ComputeDlMuInfo (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_candidates.empty ())
|
||||
{
|
||||
return DlMuInfo ();
|
||||
}
|
||||
|
||||
DlMuInfo dlMuInfo;
|
||||
std::swap (dlMuInfo.txParams.m_txVector, m_txParams.m_txVector);
|
||||
FinalizeTxVector (dlMuInfo.txParams.m_txVector);
|
||||
|
||||
AssignRuIndices (dlMuInfo.txParams.m_txVector);
|
||||
m_txParams.Clear ();
|
||||
|
||||
Ptr<const WifiMacQueueItem> mpdu;
|
||||
|
||||
// Compute the TX params (again) by using the stored MPDUs and the final TXVECTOR
|
||||
@@ -741,39 +765,7 @@ RrMultiUserScheduler::ComputeDlMuInfo (void)
|
||||
}
|
||||
|
||||
AcIndex primaryAc = m_edca->GetAccessCategory ();
|
||||
|
||||
// The amount of credits received by each station equals the TX duration (in
|
||||
// microseconds) divided by the number of stations.
|
||||
double creditsPerSta = dlMuInfo.txParams.m_txDuration.ToDouble (Time::US)
|
||||
/ m_staList[primaryAc].size ();
|
||||
// Transmitting stations have to pay a number of credits equal to the TX duration
|
||||
// (in microseconds) times the allocated bandwidth share.
|
||||
double debitsPerMhz = dlMuInfo.txParams.m_txDuration.ToDouble (Time::US)
|
||||
/ (nRusAssigned * HeRu::GetBandwidth (ruType)
|
||||
+ nCentral26TonesRus * HeRu::GetBandwidth (HeRu::RU_26_TONE));
|
||||
|
||||
// assign credits to all stations
|
||||
for (auto& sta : m_staList[primaryAc])
|
||||
{
|
||||
sta.credits += creditsPerSta;
|
||||
sta.credits = std::min (sta.credits, m_maxCredits.ToDouble (Time::US));
|
||||
}
|
||||
|
||||
// subtract debits to the selected stations
|
||||
candidateIt = m_candidates.begin ();
|
||||
|
||||
for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
|
||||
{
|
||||
NS_ASSERT (candidateIt != m_candidates.end ());
|
||||
|
||||
candidateIt->first->credits -= debitsPerMhz * HeRu::GetBandwidth (i < nRusAssigned ? ruType : HeRu::RU_26_TONE);
|
||||
|
||||
candidateIt++;
|
||||
}
|
||||
|
||||
// sort the list in decreasing order of credits
|
||||
m_staList[primaryAc].sort ([] (const MasterInfo& a, const MasterInfo& b)
|
||||
{ return a.credits > b.credits; });
|
||||
UpdateCredits (m_staList[primaryAc], dlMuInfo.txParams.m_txDuration, dlMuInfo.txParams.m_txVector);
|
||||
|
||||
NS_LOG_DEBUG ("Next station to serve has AID=" << m_staList[primaryAc].front ().aid);
|
||||
|
||||
|
||||
@@ -119,6 +119,28 @@ private:
|
||||
double credits; //!< credits accumulated by the station
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize the given TXVECTOR by only including the largest subset of the
|
||||
* current set of candidate stations that can be allocated equal-sized RUs
|
||||
* (with the possible exception of using central 26-tone RUs) without
|
||||
* leaving RUs unallocated. The given TXVECTOR must be a MU TXVECTOR and must
|
||||
* contain an HeMuUserInfo entry for each candidate station. The finalized
|
||||
* TXVECTOR contains a subset of such HeMuUserInfo entries. The set of candidate
|
||||
* stations is also updated by removing stations that are not allocated an RU.
|
||||
*
|
||||
* \param txVector the given TXVECTOR
|
||||
*/
|
||||
void FinalizeTxVector (WifiTxVector& txVector);
|
||||
/**
|
||||
* Update credits of the stations in the given list considering that a PPDU having
|
||||
* the given duration is being transmitted or solicited by using the given TXVECTOR.
|
||||
*
|
||||
* \param staList the list of stations
|
||||
* \param txDuration the TX duration of the PPDU being transmitted or solicited
|
||||
* \param txVector the TXVECTOR for the PPDU being transmitted or solicited
|
||||
*/
|
||||
void UpdateCredits (std::list<MasterInfo>& staList, Time txDuration, const WifiTxVector& txVector);
|
||||
|
||||
/**
|
||||
* Information stored for candidate stations
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user