A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
multi-user-scheduler.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "he-configuration.h"
13
14#include "ns3/abort.h"
15#include "ns3/log.h"
16#include "ns3/qos-txop.h"
17#include "ns3/wifi-acknowledgment.h"
18#include "ns3/wifi-mac-trailer.h"
19#include "ns3/wifi-protection.h"
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("MultiUserScheduler");
25
26NS_OBJECT_ENSURE_REGISTERED(MultiUserScheduler);
27
28TypeId
30{
31 static TypeId tid =
32 TypeId("ns3::MultiUserScheduler")
34 .SetGroupName("Wifi")
35 .AddAttribute("AccessReqInterval",
36 "Duration of the interval between two consecutive requests for "
37 "channel access made by the MultiUserScheduler. Such requests are "
38 "made independently of the presence of frames in the queues of the "
39 "AP and are intended to allow the AP to coordinate UL MU transmissions "
40 "even without DL traffic. A null duration indicates that such "
41 "requests shall not be made.",
46 .AddAttribute("AccessReqAc",
47 "The Access Category for which the MultiUserScheduler makes requests "
48 "for channel access.",
52 "AC_BE",
54 "AC_VI",
56 "AC_VO",
58 "AC_BK"))
59 .AddAttribute("DelayAccessReqUponAccess",
60 "If enabled, the access request interval is measured starting "
61 "from the last time an EDCA function obtained channel access. "
62 "Otherwise, the access request interval is measured starting "
63 "from the last time the MultiUserScheduler made a request for "
64 "channel access.",
65 BooleanValue(true),
68 return tid;
69}
70
74
79
80void
82{
83 NS_LOG_FUNCTION(this);
84 m_apMac = nullptr;
85 m_edca = nullptr;
86 m_lastTxInfo.clear();
87 for (auto& accessReqTimer : m_accessReqTimers)
88 {
89 accessReqTimer.Cancel();
90 }
92}
93
94void
96{
97 NS_LOG_FUNCTION(this);
98 if (!m_apMac)
99 {
100 Ptr<ApWifiMac> apMac = this->GetObject<ApWifiMac>();
101 // verify that it's a valid AP mac and that
102 // the AP mac was not set before
103 if (apMac)
104 {
105 this->SetWifiMac(apMac);
106 }
107 }
109}
110
111void
113{
114 NS_LOG_FUNCTION(this);
115
117 {
119 for (uint8_t id = 0; id < m_apMac->GetNLinks(); ++id)
120 {
121 m_accessReqTimers.emplace_back(
124 this,
125 id));
126 }
127 }
128}
129
130void
132{
133 NS_LOG_FUNCTION(this << interval.As(Time::MS));
134 m_accessReqInterval = interval;
135 // if interval is non-zero, start the timers that are not running if we are past initialization
137 {
138 m_accessReqTimers.resize(m_apMac->GetNLinks());
139 for (uint8_t id = 0; id < m_apMac->GetNLinks(); ++id)
140 {
141 if (!m_accessReqTimers[id].IsPending())
142 {
145 this,
146 id);
147 }
148 }
149 }
150}
151
152Time
157
158void
160{
161 NS_LOG_FUNCTION(this << mac);
162 m_apMac = mac;
163
164 // When VHT DL MU-MIMO will be supported, we will have to lower this requirement
165 // and allow a Multi-user scheduler to be installed on a VHT AP.
166 NS_ABORT_MSG_IF(!m_apMac || !m_apMac->GetHeConfiguration(),
167 "MultiUserScheduler can only be installed on HE APs");
168
169 for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
170 {
171 auto heFem = DynamicCast<HeFrameExchangeManager>(m_apMac->GetFrameExchangeManager(linkId));
172 NS_ASSERT(heFem);
173 heFem->SetMultiUserScheduler(this);
174 }
175}
176
179{
180 return m_apMac->GetWifiRemoteStationManager(linkId);
181}
182
184MultiUserScheduler::GetHeFem(uint8_t linkId) const
185{
186 return StaticCast<HeFrameExchangeManager>(m_apMac->GetFrameExchangeManager(linkId));
187}
188
189void
191{
192 NS_LOG_FUNCTION(this << linkId);
193
194 // request channel access if not requested yet
195 auto edca = m_apMac->GetQosTxop(m_accessReqAc);
196
197 if (edca->GetAccessStatus(linkId) == Txop::NOT_REQUESTED)
198 {
199 m_apMac->GetChannelAccessManager(linkId)->RequestAccess(edca);
200 }
201
202 // restart timer
204 {
205 NS_ASSERT(m_accessReqTimers.size() > linkId);
208 this,
209 linkId);
210 }
211}
212
215 Time availableTime,
216 bool initialFrame,
217 MHz_u allowedWidth,
218 uint8_t linkId)
219{
220 NS_LOG_FUNCTION(this << edca << availableTime << initialFrame << allowedWidth << linkId);
221
222 m_edca = edca;
223 m_availableTime = availableTime;
224 m_initialFrame = initialFrame;
225 m_allowedWidth = allowedWidth;
226 m_linkId = linkId;
227
228 if (m_accessReqTimers.size() > linkId && m_accessReqTimers[linkId].IsPending() &&
230 {
231 // restart access timer
232 m_accessReqTimers[linkId].Cancel();
234 {
237 this,
238 linkId);
239 }
240 }
241
242 TxFormat txFormat = SelectTxFormat();
243
244 if (txFormat == DL_MU_TX)
245 {
246 m_lastTxInfo[linkId].dlInfo = ComputeDlMuInfo();
247 }
248 else if (txFormat == UL_MU_TX)
249 {
250 m_lastTxInfo[linkId].ulInfo = ComputeUlMuInfo();
252 }
253
254 if (txFormat != NO_TX)
255 {
256 m_lastTxInfo[linkId].lastTxFormat = txFormat;
257 }
258 return txFormat;
259}
260
263{
264 return m_lastTxInfo[linkId].lastTxFormat;
265}
266
269{
270 NS_ABORT_MSG_IF(m_lastTxInfo[linkId].lastTxFormat != DL_MU_TX,
271 "Next transmission is not DL MU");
272
273#ifdef NS3_BUILD_PROFILE_DEBUG
274 // check that all the addressed stations support HE
275 for (auto& psdu : m_lastTxInfo[linkId].dlInfo.psduMap)
276 {
277 auto receiver = psdu.second->GetAddr1();
278 auto linkId = m_apMac->IsAssociated(receiver);
279 NS_ABORT_MSG_IF(!linkId, "Station " << receiver << " should be associated");
280 NS_ABORT_MSG_IF(!GetWifiRemoteStationManager(*linkId)->GetHeSupported(receiver),
281 "Station " << psdu.second->GetAddr1() << " does not support HE");
282 }
283#endif
284
285 return m_lastTxInfo[linkId].dlInfo;
286}
287
290{
291 NS_ABORT_MSG_IF(m_lastTxInfo[linkId].lastTxFormat != UL_MU_TX,
292 "Next transmission is not UL MU");
293
294 return m_lastTxInfo[linkId].ulInfo;
295}
296
298MultiUserScheduler::GetTriggerFrame(const CtrlTriggerHeader& trigger, uint8_t linkId) const
299{
300 NS_LOG_FUNCTION(this << linkId);
301
302 Ptr<Packet> packet = Create<Packet>();
303 packet->AddHeader(trigger);
304
306 if (trigger.GetNUserInfoFields() == 1)
307 {
308 auto aid = trigger.begin()->GetAid12();
309 auto aidAddrMapIt = m_apMac->GetStaList(linkId).find(aid);
310 NS_ASSERT(aidAddrMapIt != m_apMac->GetStaList(linkId).end());
311 receiver = aidAddrMapIt->second;
312 }
313
315 hdr.SetAddr1(receiver);
316 hdr.SetAddr2(GetHeFem(linkId)->GetAddress());
317 hdr.SetDsNotTo();
318 hdr.SetDsNotFrom();
319
320 return Create<WifiMpdu>(packet, hdr);
321}
322
323void
325{
326 NS_LOG_FUNCTION(this);
327
328 // Set the CS Required subfield to true, unless the UL Length subfield is less
329 // than or equal to 76 (see Section 26.5.2.5 of 802.11ax-2021)
330 m_lastTxInfo[m_linkId].ulInfo.trigger.SetCsRequired(
331 m_lastTxInfo[m_linkId].ulInfo.trigger.GetUlLength() > 76);
332
333 GetHeFem(m_linkId)->SetTargetRssi(m_lastTxInfo[m_linkId].ulInfo.trigger);
334}
335
338{
339 // find the maximum number of TIDs for which a BlockAck agreement has been established
340 // with an STA, among all the STAs solicited by the given Trigger Frame
341 uint8_t maxNTids = 0;
342 for (const auto& userInfo : trigger)
343 {
344 auto address = m_apMac->GetMldOrLinkAddressByAid(userInfo.GetAid12());
345 NS_ASSERT_MSG(address, "AID " << userInfo.GetAid12() << " not found");
346
347 uint8_t staNTids = 0;
348 for (uint8_t tid = 0; tid < 8; tid++)
349 {
350 if (m_apMac->GetBaAgreementEstablishedAsRecipient(*address, tid))
351 {
352 staNTids++;
353 }
354 }
355 maxNTids = std::max(maxNTids, staNTids);
356 }
357
358 // compute the size in bytes of maxNTids QoS Null frames
360 header.SetDsTo();
361 header.SetDsNotFrom();
362 uint32_t headerSize = header.GetSerializedSize();
363 uint32_t maxSize = 0;
364
365 for (uint8_t i = 0; i < maxNTids; i++)
366 {
367 maxSize = MpduAggregator::GetSizeIfAggregated(headerSize + WIFI_MAC_FCS_LENGTH, maxSize);
368 }
369
370 return maxSize;
371}
372
373} // namespace ns3
Headers for Trigger frames.
ConstIterator begin() const
Get a const iterator pointing to the first User Info field in the list.
std::size_t GetNUserInfoFields() const
Get the number of User Info fields in this Trigger Frame.
Hold variables of type enum.
Definition enum.h:52
an EUI-48 address
static Mac48Address GetBroadcast()
static uint32_t GetSizeIfAggregated(uint32_t mpduSize, uint32_t ampduSize)
Compute the size of the A-MPDU resulting from the aggregation of an MPDU of size mpduSize and an A-MP...
bool m_initialFrame
true if a TXOP is being started
void NotifyNewAggregate() override
Notify all Objects aggregated to this one of a new Object being aggregated.
void DoInitialize() override
Initialize() implementation.
TxFormat GetLastTxFormat(uint8_t linkId)
Get the format of the last transmission on the given link, as determined by the last call to NotifyAc...
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
std::vector< EventId > m_accessReqTimers
the per-link timer controlling additional channel access requests
void CheckTriggerFrame()
Ensure that the Trigger Frame returned in case of UL MU transmission is correct.
static TypeId GetTypeId()
Get the type ID.
Time m_availableTime
the time available for frame exchange
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId) const
Get the station manager attached to the AP on the given link.
UlMuInfo & GetUlMuInfo(uint8_t linkId)
Get the information required to solicit an UL MU transmission on the given link.
uint8_t m_linkId
the ID of the link over which channel access has been granted
virtual TxFormat SelectTxFormat()=0
Select the format of the next transmission.
void SetAccessReqInterval(Time interval)
Set the duration of the interval between two consecutive requests for channel access made by the Mult...
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...
bool m_restartTimerUponAccess
whether the channel access timer has to be restarted upon channel access
virtual DlMuInfo ComputeDlMuInfo()=0
Compute the information required to perform a DL MU transmission.
Ptr< QosTxop > m_edca
the AC that gained channel access
virtual UlMuInfo ComputeUlMuInfo()=0
Prepare the information required to solicit an UL MU transmission.
void DoDispose() override
Destructor implementation.
Ptr< WifiMpdu > GetTriggerFrame(const CtrlTriggerHeader &trigger, uint8_t linkId) const
Get an MPDU containing the given Trigger Frame.
AcIndex m_accessReqAc
AC we request channel access for.
DlMuInfo & GetDlMuInfo(uint8_t linkId)
Get the information required to perform a DL MU transmission on the given link.
MHz_u m_allowedWidth
the allowed width for the current transmission
Ptr< HeFrameExchangeManager > GetHeFem(uint8_t linkId) const
Get the HE Frame Exchange Manager attached to the AP on the given link.
Time m_accessReqInterval
duration of the interval between channel access requests
TxFormat NotifyAccessGranted(Ptr< QosTxop > edca, Time availableTime, bool initialFrame, MHz_u allowedWidth, uint8_t linkId)
Notify the Multi-user Scheduler that the given AC of the AP gained channel access.
void SetWifiMac(Ptr< ApWifiMac > mac)
Set the wifi MAC.
TxFormat
Enumeration of the possible transmission formats.
std::map< uint8_t, LastTxInfo > m_lastTxInfo
Information about the last transmission.
void AccessReqTimeout(uint8_t linkId)
Perform actions required on expiration of the channel access request timer associated with the given ...
A base class which provides memory management and object aggregation.
Definition object.h:78
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition object.cc:412
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
bool IsInitialized() const
Check if the object has been initialized.
Definition object.cc:240
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
@ MS
millisecond
Definition nstime.h:106
@ NOT_REQUESTED
Definition txop.h:77
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Implements the IEEE 802.11 MAC header.
uint32_t GetSerializedSize() const override
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetDsTo()
Set the To DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
@ AC_BE
Best Effort.
Definition qos-utils.h:64
@ AC_VO
Voice.
Definition qos-utils.h:70
@ AC_VI
Video.
Definition qos-utils.h:68
@ AC_BK
Background.
Definition qos-utils.h:66
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1396
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition enum.h:179
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_QOSDATA_NULL
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition enum.h:221
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
Information to be provided in case of DL MU transmission.
Information to be provided in case of UL MU transmission.