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",
109 m_apMac->TraceConnectWithoutContext (
"AssociatedSta",
111 m_apMac->TraceConnectWithoutContext (
"DeAssociatedSta",
128 m_apMac->TraceDisconnectWithoutContext (
"AssociatedSta",
130 m_apMac->TraceDisconnectWithoutContext (
"DeAssociatedSta",
176 receiver =
m_apMac->GetStaList ().at (trigger.
begin ()->GetAid12 ());
196 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for BSRP TF exchange");
202 for (
const auto& userInfo : trigger)
205 m_apMac->GetWifiPhy ()->GetPhyBand (),
206 userInfo.GetAid12 ());
207 qosNullTxDuration =
Max (qosNullTxDuration, duration);
219 +
m_apMac->GetWifiPhy ()->GetSifs ()
223 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for BSRP TF exchange");
230 m_apMac->GetWifiPhy ()->GetPhyBand ()));
232 m_heFem->SetTargetRssi (trigger);
234 packet = Create<Packet> ();
236 m_trigger = Create<WifiMacQueueItem> (packet, hdr);
253 uint32_t maxBufferSize = 0;
255 std::multimap<uint8_t, CandidateInfo, std::greater<uint8_t>> ulCandidates;
259 uint8_t queueSize =
m_apMac->GetMaxBufferStatus (candidate.first->address);
260 if (queueSize == 255)
262 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is unknown");
265 else if (queueSize == 254)
267 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is not limited");
268 maxBufferSize = 0xffffffff;
272 NS_LOG_DEBUG (
"Buffer status of station " << candidate.first->address <<
" is " << +queueSize);
273 maxBufferSize =
std::max (maxBufferSize,
static_cast<uint32_t
> (queueSize * 256));
278 ulCandidates.emplace (queueSize, candidate);
283 if (maxBufferSize > 0)
286 std::size_t count = ulCandidates.size ();
287 std::size_t nCentral26TonesRus;
289 count, nCentral26TonesRus);
292 nCentral26TonesRus = 0;
296 nCentral26TonesRus =
std::min (ulCandidates.size () - count, nCentral26TonesRus);
301 auto candidateIt = ulCandidates.begin ();
308 for (std::size_t i = 0; i < count + nCentral26TonesRus; i++)
310 NS_ASSERT (candidateIt != ulCandidates.end ());
311 uint16_t staId = candidateIt->second.first->aid;
329 for (std::size_t i = 0; i < count + nCentral26TonesRus; i++)
331 NS_ASSERT (candidateIt != ulCandidates.end ());
332 uint16_t staId = candidateIt->second.first->aid;
339 userInfoIt->GetNss ()});
346 ulCandidates.erase (candidateIt, ulCandidates.end ());
354 if (ulCandidates.size () == 1)
356 receiver = ulCandidates.begin ()->second.first->address;
380 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for UL MU exchange");
394 -
m_apMac->GetWifiPhy ()->GetSifs ()
398 NS_LOG_DEBUG (
"Remaining TXOP duration is not enough for UL MU exchange");
405 for (
const auto& userInfo : trigger)
408 m_apMac->GetWifiPhy ()->GetPhyBand (),
409 userInfo.GetAid12 ());
410 bufferTxTime =
Max (bufferTxTime, duration);
413 if (bufferTxTime < maxDuration)
416 maxDuration = bufferTxTime;
423 for (
const auto& userInfo : trigger)
426 m_apMac->GetWifiPhy ()->GetPhyBand (),
427 userInfo.GetAid12 ());
428 minDuration = (minDuration.
IsZero () ? duration :
Min (minDuration, duration));
431 if (maxDuration < minDuration)
444 m_apMac->GetWifiPhy ()->GetPhyBand ()));
446 m_heFem->SetTargetRssi (trigger);
448 for (
auto& userInfo : trigger)
453 packet = Create<Packet> ();
455 m_trigger = Create<WifiMacQueueItem> (packet, hdr);
503 NS_LOG_DEBUG (
"No HE stations associated: return SU_TX");
504 return TxFormat::SU_TX;
508 std::size_t nCentral26TonesRus;
515 nCentral26TonesRus = 0;
518 uint8_t currTid =
wifiAcList.at (primaryAc).GetHighTid ();
522 if (mpdu !=
nullptr && mpdu->GetHeader ().IsQosData ())
524 currTid = mpdu->GetHeader ().GetQosTid ();
528 std::vector<uint8_t> tids;
534 uint8_t firstTid = (acIt->first == primaryAc ? currTid : acIt->second.GetHighTid ());
535 tids.push_back (firstTid);
536 tids.push_back (acIt->second.GetOtherTid (firstTid));
541 tids.push_back (currTid);
560 auto staIt =
m_staList[primaryAc].begin ();
563 while (staIt !=
m_staList[primaryAc].end ()
566 NS_LOG_DEBUG (
"Next candidate STA (MAC=" << staIt->address <<
", AID=" << staIt->aid <<
")");
571 for (uint8_t tid : tids)
577 if (
m_apMac->GetQosTxop (ac)->GetBaAgreementEstablished (staIt->address, tid))
579 mpdu =
m_apMac->GetQosTxop (ac)->PeekNextMpdu (tid, staIt->address);
593 {{currRuType, 1, false},
599 NS_LOG_DEBUG (
"Adding the peeked frame violates the time constraints");
605 NS_LOG_DEBUG (
"Adding candidate STA (MAC=" << staIt->address <<
", AID="
606 << staIt->aid <<
") TID=" << +tid);
613 NS_LOG_DEBUG (
"No frames to send to " << staIt->address <<
" with TID=" << +tid);
622 if (m_candidates.empty ())
626 NS_LOG_DEBUG (
"The AP does not have suitable frames to transmit: return NO_TX");
629 NS_LOG_DEBUG (
"The AP does not have suitable frames to transmit: return SU_TX");
633 return TxFormat::DL_MU_TX;
636 MultiUserScheduler::DlMuInfo
637 RrMultiUserScheduler::ComputeDlMuInfo (
void)
641 if (m_candidates.empty ())
646 uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
649 std::size_t nRusAssigned = m_txParams.GetPsduInfoMap ().size ();
650 std::size_t nCentral26TonesRus;
651 HeRu::RuType ruType = HeRu::GetEqualSizedRusForStations (bw, nRusAssigned, nCentral26TonesRus);
653 NS_LOG_DEBUG (nRusAssigned <<
" stations are being assigned a " << ruType <<
" RU");
655 if (!m_useCentral26TonesRus || m_candidates.size () == nRusAssigned)
657 nCentral26TonesRus = 0;
661 nCentral26TonesRus =
std::min (m_candidates.size () - nRusAssigned, nCentral26TonesRus);
662 NS_LOG_DEBUG (nCentral26TonesRus <<
" stations are being assigned a 26-tones RU");
673 auto candidateIt = m_candidates.begin ();
675 for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
677 NS_ASSERT (candidateIt != m_candidates.end ());
679 uint16_t staId = candidateIt->first->aid;
682 {{(i < nRusAssigned ? ruType : HeRu::RU_26_TONE), 1,
false},
683 m_txParams.m_txVector.GetMode (staId),
684 m_txParams.m_txVector.GetNss (staId)});
689 m_candidates.erase (candidateIt, m_candidates.end ());
697 Time actualAvailableTime = (m_initialFrame ?
Time::Min () : m_availableTime);
699 for (
const auto& candidate : m_candidates)
701 mpdu = candidate.second;
704 bool ret = m_heFem->TryAddMpdu (mpdu, dlMuInfo.
txParams, actualAvailableTime);
706 NS_ASSERT_MSG (ret,
"Weird that an MPDU does not meet constraints when "
707 "transmitted over a larger RU");
714 for (
const auto& candidate : m_candidates)
717 mpdu = candidate.second;
719 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
720 receiver = mpdu->GetHeader ().GetAddr1 ();
721 NS_ASSERT (receiver == candidate.first->address);
729 if (!mpdu->GetHeader ().IsRetry ())
733 item = m_heFem->GetMsduAggregator ()->GetNextAmsdu (mpdu, dlMuInfo.
txParams, m_availableTime, queueIt);
738 item = *mpdu->GetQueueIteratorPairs ().front ().it;
744 std::vector<Ptr<WifiMacQueueItem>> mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (item, dlMuInfo.
txParams, m_availableTime, queueIt);
746 if (mpduList.size () > 1)
749 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu> (std::move (mpduList));
753 dlMuInfo.
psduMap[candidate.first->aid] = Create<WifiPsdu> (item,
true);
757 AcIndex primaryAc = m_edca->GetAccessCategory ();
762 / m_staList[primaryAc].size ();
766 / (nRusAssigned * HeRu::GetBandwidth (ruType)
767 + nCentral26TonesRus * HeRu::GetBandwidth (HeRu::RU_26_TONE));
770 for (
auto& sta : m_staList[primaryAc])
772 sta.credits += creditsPerSta;
773 sta.credits =
std::min (sta.credits, m_maxCredits.ToDouble (Time::US));
777 candidateIt = m_candidates.begin ();
779 for (std::size_t i = 0; i < nRusAssigned + nCentral26TonesRus; i++)
781 NS_ASSERT (candidateIt != m_candidates.end ());
783 candidateIt->first->credits -= debitsPerMhz * HeRu::GetBandwidth (i < nRusAssigned ? ruType : HeRu::RU_26_TONE);
792 NS_LOG_DEBUG (
"Next station to serve has AID=" << m_staList[primaryAc].front ().aid);
805 std::set<HeRu::RuType> ruTypeSet;
808 ruTypeSet.insert (userInfo.second.ru.GetRuType ());
811 std::vector<HeRu::RuSpec> ruSet, central26TonesRus;
814 if (ruTypeSet.size () == 2)
817 NS_ASSERT (ruTypeSet.find (HeRu::RU_26_TONE) != ruTypeSet.end ());
818 ruTypeSet.erase (HeRu::RU_26_TONE);
820 central26TonesRus = HeRu::GetCentral26TonesRus (bw, *ruTypeSet.begin ());
824 ruSet = HeRu::GetRusOfType (bw, *ruTypeSet.begin ());
826 auto ruSetIt = ruSet.begin ();
827 auto central26TonesRusIt = central26TonesRus.begin ();
831 if (userInfo.second.ru.GetRuType () == *ruTypeSet.begin ())
834 txVector.
SetRu (*ruSetIt, userInfo.first);
839 NS_ASSERT (central26TonesRusIt != central26TonesRus.end ());
840 txVector.
SetRu (*central26TonesRusIt, userInfo.first);
841 central26TonesRusIt++;
847 RrMultiUserScheduler::ComputeUlMuInfo (
void)
849 return UlMuInfo {m_trigger, m_tbPpduDuration, std::move (m_txParams)};
AttributeValue implementation for Boolean.
static uint16_t ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, WifiPhyBand band)
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
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.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Ptr< const WifiMacQueueItem > PeekNextMpdu(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Peek the next frame to transmit to the given receiver and of the given TID from the block ack manager...
AcIndex GetAccessCategory(void) const override
Get the access category.
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.
Ptr< WifiMacQueueItem > m_trigger
Trigger Frame to send.
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.
TriggerFrameType m_ulTriggerType
Trigger Frame type for UL MU.
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
Time m_tbPpduDuration
Duration of the solicited TB PPDUs.
virtual TxFormat TrySendingDlMuPpdu(void)
Check if it is possible to send a DL MU PPDU given the current time limits.
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
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.
Ptr< const Packet > GetPacket(void) const
Get the packet stored in this item.
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_UNUSED(x)
Mark a local variable as unused.
#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 ...
TriggerFrameType
The different Trigger frame types.
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.
Ptr< WifiMacQueueItem > 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
Information needed to remove an MSDU from the queue.
WifiMacQueue * queue
pointer to the queue where the MSDU is enqueued
ConstIterator it
iterator pointing to the MSDU in the queue