23 #include "ns3/wifi-protection.h"
24 #include "ns3/wifi-acknowledgment.h"
25 #include "ns3/wifi-psdu.h"
42 .SetGroupName (
"Wifi")
44 .AddAttribute (
"NStations",
45 "The maximum number of stations that can be granted an RU in a DL MU OFDMA transmission",
48 MakeUintegerChecker<uint8_t> (1, 74))
49 .AddAttribute (
"EnableTxopSharing",
50 "If enabled, allow A-MPDUs of different TIDs in a DL MU PPDU.",
54 .AddAttribute (
"ForceDlOfdma",
55 "If enabled, return DL_MU_TX even if no DL MU PPDU could be built.",
59 .AddAttribute (
"EnableUlOfdma",
60 "If enabled, return UL_MU_TX if DL_MU_TX was returned the previous time.",
64 .AddAttribute (
"EnableBsrp",
65 "If enabled, send a BSRP Trigger Frame before an UL MU transmission.",
69 .AddAttribute (
"UlPsduSize",
70 "The default size in bytes of the solicited PSDU (to be sent in a TB PPDU)",
73 MakeUintegerChecker<uint32_t> ())
74 .AddAttribute (
"UseCentral26TonesRus",
75 "If enabled, central 26-tone RUs are allocated, too, when the "
76 "selected RU type is at least 52 tones.",
80 .AddAttribute (
"MaxCredits",
81 "Maximum amount of credits a station can have. When transmitting a DL MU PPDU, "
82 "the amount of credits received by each station equals the TX duration (in "
83 "microseconds) divided by the total number of stations. Stations that are the "
84 "recipient of the DL MU PPDU have to pay a number of credits equal to the TX "
85 "duration (in microseconds) times the allocated bandwidth share",
108 m_apMac->TraceConnectWithoutContext (
"AssociatedSta",
110 m_apMac->TraceConnectWithoutContext (
"DeAssociatedSta",
126 m_apMac->TraceDisconnectWithoutContext (
"AssociatedSta",
128 m_apMac->TraceDisconnectWithoutContext (
"DeAssociatedSta",
201 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for BSRP TF exchange");
210 m_apMac->GetWifiPhy ()->GetPhyBand (),
211 userInfo.GetAid12 ());
212 qosNullTxDuration =
Max (qosNullTxDuration, duration);
224 +
m_apMac->GetWifiPhy ()->GetSifs ()
228 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for BSRP TF exchange");
236 m_apMac->GetWifiPhy ()->GetPhyBand ());
252 uint32_t maxBufferSize = 0;
254 std::multimap<uint8_t, CandidateInfo, std::greater<uint8_t>> ulCandidates;
258 uint8_t queueSize =
m_apMac->GetMaxBufferStatus (candidate.first->address);
259 if (queueSize == 255)
261 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is unknown");
264 else if (queueSize == 254)
266 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is not limited");
267 maxBufferSize = 0xffffffff;
271 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is " << +queueSize);
272 maxBufferSize =
std::max (maxBufferSize,
static_cast<uint32_t
> (queueSize * 256));
277 ulCandidates.emplace (queueSize, candidate);
282 if (maxBufferSize > 0)
285 std::size_t count = ulCandidates.size ();
286 std::size_t nCentral26TonesRus;
288 count, nCentral26TonesRus);
291 nCentral26TonesRus = 0;
295 nCentral26TonesRus =
std::min (ulCandidates.size () - count, nCentral26TonesRus);
300 auto candidateIt = ulCandidates.begin ();
307 for (std::size_t i = 0; i < count + nCentral26TonesRus; i++)
309 NS_ASSERT (candidateIt != ulCandidates.end ());
310 uint16_t staId = candidateIt->second.first->aid;
325 for (std::size_t i = 0; i < count + nCentral26TonesRus; i++)
327 NS_ASSERT (candidateIt != ulCandidates.end ());
328 uint16_t staId = candidateIt->second.first->aid;
335 userInfoIt->GetNss ()});
342 ulCandidates.erase (candidateIt, ulCandidates.end ());
350 if (ulCandidates.size () == 1)
352 receiver = ulCandidates.begin ()->second.first->address;
376 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for UL MU exchange");
390 -
m_apMac->GetWifiPhy ()->GetSifs ()
394 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for UL MU exchange");
404 m_apMac->GetWifiPhy ()->GetPhyBand (),
405 userInfo.GetAid12 ());
406 bufferTxTime =
Max (bufferTxTime, duration);
409 if (bufferTxTime < maxDuration)
412 maxDuration = bufferTxTime;
422 m_apMac->GetWifiPhy ()->GetPhyBand (),
423 userInfo.GetAid12 ());
424 minDuration = (minDuration.
IsZero () ? duration :
Min (minDuration, duration));
427 if (maxDuration < minDuration)
441 m_apMac->GetWifiPhy ()->GetPhyBand ());
493 NS_LOG_DEBUG (
"No HE stations associated: return SU_TX");
494 return TxFormat::SU_TX;
498 std::size_t nCentral26TonesRus;
505 nCentral26TonesRus = 0;
508 uint8_t currTid =
wifiAcList.at (primaryAc).GetHighTid ();
512 if (mpdu !=
nullptr && mpdu->GetHeader ().IsQosData ())
514 currTid = mpdu->GetHeader ().GetQosTid ();
518 std::vector<uint8_t> tids;
524 uint8_t firstTid = (acIt->first == primaryAc ? currTid : acIt->second.GetHighTid ());
525 tids.push_back (firstTid);
526 tids.push_back (acIt->second.GetOtherTid (firstTid));
531 tids.push_back (currTid);
550 auto staIt =
m_staList[primaryAc].begin ();
553 while (staIt !=
m_staList[primaryAc].end ()
556 NS_LOG_DEBUG (
"Next candidate STA (MAC=" << staIt->address <<
", AID=" << staIt->aid <<
")");
561 for (uint8_t tid : tids)
567 if (
m_apMac->GetQosTxop (ac)->GetBaAgreementEstablished (staIt->address, tid))
569 mpdu =
m_apMac->GetQosTxop (ac)->PeekNextMpdu (tid, staIt->address);
583 {{currRuType, 1, false},
589 NS_LOG_DEBUG (
"Adding the peeked frame violates the time constraints");
595 NS_LOG_DEBUG (
"Adding candidate STA (MAC=" << staIt->address <<
", AID="
596 << staIt->aid <<
") TID=" << +tid);
603 NS_LOG_DEBUG (
"No frames to send to " << staIt->address <<
" with TID=" << +tid);
612 if (m_candidates.empty ())
616 NS_LOG_DEBUG (
"The AP does not have suitable frames to transmit: return NO_TX");
619 NS_LOG_DEBUG (
"The AP does not have suitable frames to transmit: return SU_TX");
623 return TxFormat::DL_MU_TX;
626 MultiUserScheduler::DlMuInfo
627 RrMultiUserScheduler::ComputeDlMuInfo (
void)
631 if (m_candidates.empty ())
636 uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
639 std::size_t nRusAssigned = m_txParams.GetPsduInfoMap ().size ();
640 std::size_t nCentral26TonesRus;
641 HeRu::RuType ruType = HeRu::GetEqualSizedRusForStations (bw, nRusAssigned, nCentral26TonesRus);
643 NS_LOG_DEBUG (nRusAssigned <<
" stations are being assigned a " << ruType <<
" RU");
645 if (!m_useCentral26TonesRus || m_candidates.size () == nRusAssigned)
647 nCentral26TonesRus = 0;
651 nCentral26TonesRus =
std::min (m_candidates.size () - nRusAssigned, nCentral26TonesRus);
652 NS_LOG_DEBUG (nCentral26TonesRus <<
" stations are being assigned a 26-tones RU");
663 auto candidateIt = m_candidates.begin ();
665 for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
667 NS_ASSERT (candidateIt != m_candidates.end ());
669 uint16_t staId = candidateIt->first->aid;
672 {{(i < nRusAssigned ? ruType : HeRu::RU_26_TONE), 1,
false},
673 m_txParams.m_txVector.GetMode (staId),
674 m_txParams.m_txVector.GetNss (staId)});
679 m_candidates.erase (candidateIt, m_candidates.end ());
687 Time actualAvailableTime = (m_initialFrame ?
Time::Min () : m_availableTime);
689 for (
const auto& candidate : m_candidates)
691 mpdu = candidate.second;
694 [[maybe_unused]]
bool ret = m_heFem->TryAddMpdu (mpdu, dlMuInfo.
txParams, actualAvailableTime);
695 NS_ASSERT_MSG (ret,
"Weird that an MPDU does not meet constraints when "
696 "transmitted over a larger RU");
703 for (
const auto& candidate : m_candidates)
706 mpdu = candidate.second;
708 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
709 receiver = mpdu->GetHeader ().GetAddr1 ();
710 NS_ASSERT (receiver == candidate.first->address);
715 if (!mpdu->GetHeader ().IsRetry ())
719 item = m_heFem->GetMsduAggregator ()->GetNextAmsdu (mpdu, dlMuInfo.
txParams, m_availableTime);
724 item = mpdu->GetItem ();
730 std::vector<Ptr<WifiMacQueueItem>> mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (item, dlMuInfo.
txParams, m_availableTime);
732 if (mpduList.size () > 1)
735 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu> (std::move (mpduList));
739 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu> (item,
true);
743 AcIndex primaryAc = m_edca->GetAccessCategory ();
748 / m_staList[primaryAc].size ();
752 / (nRusAssigned * HeRu::GetBandwidth (ruType)
753 + nCentral26TonesRus * HeRu::GetBandwidth (HeRu::RU_26_TONE));
756 for (
auto& sta : m_staList[primaryAc])
758 sta.credits += creditsPerSta;
759 sta.credits =
std::min (sta.credits, m_maxCredits.ToDouble (Time::US));
763 candidateIt = m_candidates.begin ();
765 for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
767 NS_ASSERT (candidateIt != m_candidates.end ());
769 candidateIt->first->credits -= debitsPerMhz * HeRu::GetBandwidth (i < nRusAssigned ? ruType : HeRu::RU_26_TONE);
778 NS_LOG_DEBUG (
"Next station to serve has AID=" << m_staList[primaryAc].front ().aid);
791 std::set<HeRu::RuType> ruTypeSet;
794 ruTypeSet.insert (userInfo.second.ru.GetRuType ());
797 std::vector<HeRu::RuSpec> ruSet, central26TonesRus;
800 if (ruTypeSet.size () == 2)
803 NS_ASSERT (ruTypeSet.find (HeRu::RU_26_TONE) != ruTypeSet.end ());
804 ruTypeSet.erase (HeRu::RU_26_TONE);
806 central26TonesRus = HeRu::GetCentral26TonesRus (bw, *ruTypeSet.begin ());
810 ruSet = HeRu::GetRusOfType (bw, *ruTypeSet.begin ());
812 auto ruSetIt = ruSet.begin ();
813 auto central26TonesRusIt = central26TonesRus.begin ();
817 if (userInfo.second.ru.GetRuType () == *ruTypeSet.begin ())
820 txVector.
SetRu (*ruSetIt, userInfo.first);
825 NS_ASSERT (central26TonesRusIt != central26TonesRus.end ());
826 txVector.
SetRu (*central26TonesRusIt, userInfo.first);
827 central26TonesRusIt++;
833 RrMultiUserScheduler::ComputeUlMuInfo (
void)
835 return UlMuInfo {m_trigger, m_triggerMacHdr, std::move (m_txParams)};
AttributeValue implementation for Boolean.
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
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,...
static Mac48Address GetBroadcast(void)
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
void DoInitialize(void) override
Initialize() implementation.
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
Time m_availableTime
the time available for frame exchange
void DoDispose(void) override
Destructor implementation.
TxFormat GetLastTxFormat(void) const
Get the format of the last transmission, as determined by the last call to NotifyAccessGranted that d...
Ptr< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(void) const
Get the station manager attached to the AP.
Ptr< QosTxop > m_edca
the AC that gained channel access
uint32_t m_sizeOf8QosNull
size in bytes of 8 QoS Null frames
UlMuInfo & GetUlMuInfo(void)
Get the information required to solicit an UL MU transmission.
DlMuInfo & GetDlMuInfo(void)
Get the information required to perform a DL MU transmission.
TxFormat
Enumeration of the possible transmission formats.
void AddHeader(const Header &header)
Add header to this packet.
Smart pointer class similar to boost::intrusive_ptr.
AcIndex GetAccessCategory(void) const
Get the access category of this object.
Ptr< const WifiMacQueueItem > PeekNextMpdu(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMacQueueItem > item=nullptr)
Peek the next frame to transmit to the given receiver and of the given TID from the EDCA queue.
RrMultiUserScheduler is a simple OFDMA scheduler that indicates to perform a DL OFDMA transmission if...
virtual TxFormat TrySendingBsrpTf(void)
Check if it is possible to send a BSRP Trigger Frame given the current time limits.
void DoDispose(void) override
Destructor implementation.
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.
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
virtual TxFormat TrySendingDlMuPpdu(void)
Check if it is possible to send a DL MU PPDU given the current time limits.
WifiMacHeader m_triggerMacHdr
MAC header for Trigger Frame.
TxFormat SelectTxFormat(void) override
Select the format of the next transmission.
uint8_t m_nStations
Number of stations/slots to fill.
WifiTxParameters m_txParams
TX parameters.
virtual TxFormat TrySendingBasicTf(void)
Check if it is possible to send a Basic Trigger Frame given the current time limits.
void AssignRuIndices(WifiTxVector &txVector)
Assign an RU index to all the RUs allocated by the given TXVECTOR.
virtual ~RrMultiUserScheduler()
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.
std::map< AcIndex, std::list< MasterInfo > > m_staList
Per-AC list of stations (next to serve first)
bool m_enableTxopSharing
allow A-MPDUs of different TIDs in a DL MU PPDU
CtrlTriggerHeader m_trigger
Trigger Frame to send.
void DoInitialize(void) override
Initialize() implementation.
static TypeId GetTypeId(void)
Get the type ID.
Simulation virtual time values and global simulation resolution.
double ToDouble(enum Unit unit) const
Get the Time value expressed in a particular unit.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
bool IsZero(void) const
Exactly equivalent to t == 0.
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
bool IsNegative(void) 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.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiTxVector GetDataTxVector(const WifiMacHeader &header)
void Clear(void)
Reset the TX parameters.
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.
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)
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(void) const
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the 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.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetBssColor(uint8_t color)
Set the BSS color.
uint16_t GetChannelWidth(void) const
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
make Callback use a separate empty type
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#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...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
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...
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
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.
CtrlTriggerHeader trigger
the Trigger Frame used to solicit TB PPDUs
Information used to sort stations.
Mac48Address address
station's MAC Address
double credits
credits accumulated by the station
uint16_t aid
station's AID