27#include "ns3/wifi-acknowledgment.h"
28#include "ns3/wifi-mac-queue.h"
29#include "ns3/wifi-protection.h"
30#include "ns3/wifi-psdu.h"
46 TypeId(
"ns3::RrMultiUserScheduler")
50 .AddAttribute(
"NStations",
51 "The maximum number of stations that can be granted an RU in a DL MU "
55 MakeUintegerChecker<uint8_t>(1, 74))
56 .AddAttribute(
"EnableTxopSharing",
57 "If enabled, allow A-MPDUs of different TIDs in a DL MU PPDU.",
61 .AddAttribute(
"ForceDlOfdma",
62 "If enabled, return DL_MU_TX even if no DL MU PPDU could be built.",
66 .AddAttribute(
"EnableUlOfdma",
67 "If enabled, return UL_MU_TX if DL_MU_TX was returned the previous time.",
71 .AddAttribute(
"EnableBsrp",
72 "If enabled, send a BSRP Trigger Frame before an UL MU transmission.",
78 "The default size in bytes of the solicited PSDU (to be sent in a TB PPDU)",
81 MakeUintegerChecker<uint32_t>())
82 .AddAttribute(
"UseCentral26TonesRus",
83 "If enabled, central 26-tone RUs are allocated, too, when the "
84 "selected RU type is at least 52 tones.",
90 "Maximum amount of credits a station can have. When transmitting a DL MU PPDU, "
91 "the amount of credits received by each station equals the TX duration (in "
92 "microseconds) divided by the total number of stations. Stations that are the "
93 "recipient of the DL MU PPDU have to pay a number of credits equal to the TX "
94 "duration (in microseconds) times the allocated bandwidth share",
189 std::size_t nCentral26TonesRus;
195 nCentral26TonesRus = 0;
204 txVector.
SetGuardInterval(heConfiguration->GetGuardInterval().GetNanoSeconds());
205 txVector.
SetBssColor(heConfiguration->GetBssColor());
213 std::min<std::size_t>(
m_nStations, count + nCentral26TonesRus))
215 NS_LOG_DEBUG(
"Next candidate STA (MAC=" << staIt->address <<
", AID=" << staIt->aid <<
")");
217 if (!canbeSolicited(*staIt))
219 NS_LOG_DEBUG(
"Skipping station based on provided function object");
229 if (
m_heFem->GetBaAgreementEstablished(staIt->address, tid))
237 NS_LOG_DEBUG(
"No Block Ack agreement established with " << staIt->address);
251 suTxVector.GetMode(),
252 suTxVector.GetNss()});
276 NS_LOG_DEBUG(
"No HE stations associated: return SU_TX");
277 return TxFormat::SU_TX;
285 return TxFormat::DL_MU_TX;
304 NS_LOG_DEBUG(
"Remaining TXOP duration is not enough for BSRP TF exchange");
315 userInfo.GetAid12());
316 qosNullTxDuration =
Max(qosNullTxDuration, duration);
332 NS_LOG_DEBUG(
"Remaining TXOP duration is not enough for BSRP TF exchange");
355 NS_LOG_DEBUG(
"No HE stations associated: return SU_TX");
356 return TxFormat::SU_TX;
369 return TxFormat::DL_MU_TX;
379 if (queueSize == 255)
381 NS_LOG_DEBUG(
"Buffer status of station " << staIt->second <<
" is unknown");
384 else if (queueSize == 254)
386 NS_LOG_DEBUG(
"Buffer status of station " << staIt->second <<
" is not limited");
387 maxBufferSize = 0xffffffff;
391 NS_LOG_DEBUG(
"Buffer status of station " << staIt->second <<
" is " << +queueSize);
392 maxBufferSize =
std::max(maxBufferSize,
static_cast<uint32_t>(queueSize * 256));
396 if (maxBufferSize == 0)
421 NS_LOG_DEBUG(
"Remaining TXOP duration is not enough for UL MU exchange");
434 maxDuration =
Min(maxDuration,
440 NS_LOG_DEBUG(
"Remaining TXOP duration is not enough for UL MU exchange");
452 userInfo.GetAid12());
453 bufferTxTime =
Max(bufferTxTime, duration);
456 if (bufferTxTime < maxDuration)
459 maxDuration = bufferTxTime;
471 userInfo.GetAid12());
472 minDuration = (minDuration.
IsZero() ? duration :
Min(minDuration, duration));
475 if (maxDuration < minDuration)
487 std::tie(ulLength, maxDuration) =
547 NS_LOG_DEBUG(
"No HE stations associated: return SU_TX");
548 return TxFormat::SU_TX;
553 std::size_t nCentral26TonesRus;
560 nCentral26TonesRus = 0;
563 uint8_t currTid =
wifiAcList.at(primaryAc).GetHighTid();
567 if (mpdu && mpdu->GetHeader().IsQosData())
569 currTid = mpdu->GetHeader().GetQosTid();
573 std::vector<uint8_t> tids;
579 uint8_t firstTid = (acIt->first == primaryAc ? currTid : acIt->second.GetHighTid());
580 tids.push_back(firstTid);
581 tids.push_back(acIt->second.GetOtherTid(firstTid));
586 tids.push_back(currTid);
608 std::vector<uint8_t> ruAllocations;
610 ruAllocations.resize(numRuAllocs);
617 NS_LOG_DEBUG(
"Next candidate STA (MAC=" << staIt->address <<
", AID=" << staIt->aid <<
")");
622 for (uint8_t tid : tids)
648 {{currRuType, 1, true}, suTxVector.
GetMode(), suTxVector.
GetNss()});
652 NS_LOG_DEBUG(
"Adding the peeked frame violates the time constraints");
658 NS_LOG_DEBUG(
"Adding candidate STA (MAC=" << staIt->address
659 <<
", AID=" << staIt->aid
660 <<
") TID=" << +tid);
667 NS_LOG_DEBUG(
"No frames to send to " << staIt->address <<
" with TID=" << +tid);
676 if (m_candidates.empty())
680 NS_LOG_DEBUG(
"The AP does not have suitable frames to transmit: return NO_TX");
683 NS_LOG_DEBUG(
"The AP does not have suitable frames to transmit: return SU_TX");
687 return TxFormat::DL_MU_TX;
699 std::size_t nRusAssigned = m_candidates.size();
700 std::size_t nCentral26TonesRus;
702 HeRu::GetEqualSizedRusForStations(m_allowedWidth, nRusAssigned, nCentral26TonesRus);
704 NS_LOG_DEBUG(nRusAssigned <<
" stations are being assigned a " << ruType <<
" RU");
706 if (!m_useCentral26TonesRus || m_candidates.size() == nRusAssigned)
708 nCentral26TonesRus = 0;
712 nCentral26TonesRus =
std::min(m_candidates.size() - nRusAssigned, nCentral26TonesRus);
713 NS_LOG_DEBUG(nCentral26TonesRus <<
" stations are being assigned a 26-tones RU");
720 auto candidateIt = m_candidates.begin();
721 auto ruSet = HeRu::GetRusOfType(m_allowedWidth, ruType);
722 auto ruSetIt = ruSet.begin();
723 auto central26TonesRus = HeRu::GetCentral26TonesRus(m_allowedWidth, ruType);
724 auto central26TonesRusIt = central26TonesRus.begin();
726 for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
728 NS_ASSERT(candidateIt != m_candidates.end());
729 auto mapIt = heMuUserInfoMap.find(candidateIt->first->aid);
730 NS_ASSERT(mapIt != heMuUserInfoMap.end());
733 {(i < nRusAssigned ? *ruSetIt++ : *central26TonesRusIt++),
740 m_candidates.erase(candidateIt, m_candidates.end());
744RrMultiUserScheduler::UpdateCredits(std::list<MasterInfo>& staList,
751 std::map<HeRu::RuType, std::size_t> ruMap;
754 ruMap.insert({userInfo.second.ru.GetRuType(), 0}).
first->second++;
759 double creditsPerSta = txDuration.
ToDouble(Time::US) / staList.size();
762 double debitsPerMhz =
764 std::accumulate(ruMap.begin(), ruMap.end(), 0, [](uint16_t sum,
auto pair) {
765 return sum + pair.second * HeRu::GetBandwidth(pair.first);
769 for (
auto& sta : staList)
771 sta.credits += creditsPerSta;
772 sta.credits =
std::min(sta.credits, m_maxCredits.ToDouble(Time::US));
776 for (
auto& candidate : m_candidates)
781 candidate.first->credits -= debitsPerMhz * HeRu::GetBandwidth(mapIt->second.ru.GetRuType());
789RrMultiUserScheduler::ComputeDlMuInfo()
793 if (m_candidates.empty())
806 Time actualAvailableTime = (m_initialFrame ?
Time::Min() : m_availableTime);
808 for (
const auto& candidate : m_candidates)
810 mpdu = candidate.second;
813 bool ret [[maybe_unused]] =
814 m_heFem->TryAddMpdu(mpdu, dlMuInfo.
txParams, actualAvailableTime);
816 "Weird that an MPDU does not meet constraints when "
817 "transmitted over a larger RU");
824 for (
const auto& candidate : m_candidates)
827 mpdu = candidate.second;
829 uint8_t tid = mpdu->GetHeader().GetQosTid();
830 receiver = mpdu->GetHeader().GetAddr1();
831 NS_ASSERT(receiver == candidate.first->address);
836 if (!mpdu->GetHeader().IsRetry())
840 item = m_heFem->GetMsduAggregator()->GetNextAmsdu(mpdu,
853 std::vector<Ptr<WifiMpdu>> mpduList =
854 m_heFem->GetMpduAggregator()->GetNextAmpdu(item, dlMuInfo.
txParams, m_availableTime);
856 if (mpduList.size() > 1)
859 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu>(std::move(mpduList));
863 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu>(item,
true);
867 AcIndex primaryAc = m_edca->GetAccessCategory();
868 UpdateCredits(m_staListDl[primaryAc],
872 NS_LOG_DEBUG(
"Next station to serve has AID=" << m_staListDl[primaryAc].front().aid);
878RrMultiUserScheduler::ComputeUlMuInfo()
880 return UlMuInfo{m_trigger, m_triggerMacHdr, std::move(m_txParams)};
uint8_t GetMaxBufferStatus(Mac48Address address) const
Return the maximum among the values of the Queue Size subfield of the last QoS Data or QoS Null frame...
const std::map< uint16_t, Mac48Address > & GetStaList(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get a const reference to the map of associated stations on the given link.
AttributeValue implementation for Boolean.
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
RuType
The different HE Resource Unit (RU) types.
static RuType GetEqualSizedRusForStations(uint16_t bandwidth, std::size_t &nStations, std::size_t &nCentral26TonesRus)
Given the channel bandwidth and the number of stations candidate for being assigned an RU,...
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
bool m_initialFrame
true if a TXOP is being started
Ptr< WifiMpdu > GetTriggerFrame(const CtrlTriggerHeader &trigger) const
Get an MPDU containing the given Trigger Frame.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
Get the station manager attached to the AP.
void DoInitialize() override
Initialize() implementation.
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
uint16_t m_allowedWidth
the allowed width in MHz for the current transmission
Time m_availableTime
the time available for frame exchange
Ptr< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
TxFormat GetLastTxFormat() const
Get the format of the last transmission, as determined by the last call to NotifyAccessGranted that d...
uint32_t GetMaxSizeOfQosNullAmpdu(const CtrlTriggerHeader &trigger) const
Get the maximum size in bytes among the A-MPDUs containing QoS Null frames and solicited by the given...
Ptr< QosTxop > m_edca
the AC that gained channel access
void DoDispose() override
Destructor implementation.
TxFormat
Enumeration of the possible transmission formats.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Smart pointer class similar to boost::intrusive_ptr.
AcIndex GetAccessCategory() const
Get the access category of this object.
bool GetBaAgreementEstablished(Mac48Address address, uint8_t tid) const
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< WifiMpdu > item=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
RrMultiUserScheduler is a simple OFDMA scheduler that indicates to perform a DL OFDMA transmission if...
TxFormat SelectTxFormat() override
Select the format of the next transmission.
bool m_enableBsrp
send a BSRP before an UL MU transmission
void NotifyStationAssociated(uint16_t aid, Mac48Address address)
Notify the scheduler that a station associated with the AP.
static TypeId GetTypeId()
Get the type ID.
~RrMultiUserScheduler() override
uint32_t m_ulPsduSize
the size in byte of the solicited PSDU
std::list< CandidateInfo > m_candidates
Candidate stations for MU TX.
bool m_useCentral26TonesRus
whether to allocate central 26-tone RUs
bool m_forceDlOfdma
return DL_OFDMA even if no DL MU PPDU was built
bool m_enableUlOfdma
enable the scheduler to also return UL_OFDMA
void DoInitialize() override
Initialize() implementation.
void DoDispose() override
Destructor implementation.
void UpdateCredits(std::list< MasterInfo > &staList, Time txDuration, const WifiTxVector &txVector)
Update credits of the stations in the given list considering that a PPDU having the given duration is...
WifiMacHeader m_triggerMacHdr
MAC header for Trigger Frame.
uint8_t m_nStations
Number of stations/slots to fill.
WifiTxParameters m_txParams
TX parameters.
virtual TxFormat TrySendingDlMuPpdu()
Check if it is possible to send a DL MU PPDU given the current time limits.
void NotifyStationDeassociated(uint16_t aid, Mac48Address address)
Notify the scheduler that a station deassociated with the AP.
Time m_maxCredits
Max amount of credits a station can have.
bool m_enableTxopSharing
allow A-MPDUs of different TIDs in a DL MU PPDU
CtrlTriggerHeader m_trigger
Trigger Frame to send.
std::map< AcIndex, std::list< MasterInfo > > m_staListDl
Per-AC list of stations (next to serve for DL first)
virtual TxFormat TrySendingBsrpTf()
Check if it is possible to send a BSRP Trigger Frame given the current time limits.
WifiTxVector GetTxVectorForUlMu(Func canBeSolicited)
Compute a TXVECTOR that can be used to construct a Trigger Frame to solicit transmissions from suitab...
virtual TxFormat TrySendingBasicTf()
Check if it is possible to send a Basic Trigger Frame given the current time limits.
void FinalizeTxVector(WifiTxVector &txVector)
Finalize the given TXVECTOR by only including the largest subset of the current set of candidate stat...
std::list< MasterInfo > m_staListUl
List of stations to serve for UL.
Simulation virtual time values and global simulation resolution.
double ToDouble(enum Unit unit) const
Get the Time value expressed in a particular unit.
bool IsNegative() const
Exactly equivalent to t <= 0.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
bool IsZero() const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Mac48Address GetAddress() const
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
WifiTxVector GetDataTxVector(const WifiMacHeader &header, uint16_t allowedWidth)
WifiTxVector GetRtsTxVector(Mac48Address address)
std::unique_ptr< WifiProtection > m_protection
protection method
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
Time m_txDuration
TX duration of the frame.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void Clear()
Reset the TX parameters.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
std::map< uint16_t, HeMuUserInfo > HeMuUserInfoMap
map of HE MU specific user info paramters indexed by STA-ID
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
void SetBssColor(uint8_t color)
Set the BSS color.
uint16_t GetChannelWidth() const
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
Empty class, used as a default parent class for SimpleRefCount.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Ptr< const AttributeChecker > MakeBooleanChecker()
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Seconds(double value)
Construct a Time in the indicated unit.
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Declaration of ns3::HePhy class and ns3::HeSigAParameters struct.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
Information to be provided in case of DL MU transmission.
WifiTxParameters txParams
the transmission parameters
WifiPsduMap psduMap
the DL MU PPDU to transmit
Information to be provided in case of UL MU transmission.
Information used to sort stations.
Mac48Address address
station's MAC Address
double credits
credits accumulated by the station
uint16_t aid
station's AID