A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
channel-access-manager.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9#ifndef CHANNEL_ACCESS_MANAGER_H
10#define CHANNEL_ACCESS_MANAGER_H
11
12#include "wifi-phy-common.h"
14
15#include "ns3/event-id.h"
16#include "ns3/nstime.h"
17#include "ns3/object.h"
18
19#include <algorithm>
20#include <map>
21#include <memory>
22#include <unordered_map>
23#include <vector>
24
25class EmlsrUlTxopTest;
27
28namespace ns3
29{
30
31class WifiPhy;
32class PhyListener;
33class Txop;
34class FrameExchangeManager;
35
36/**
37 * \brief Manage a set of ns3::Txop
38 * \ingroup wifi
39 *
40 * Handle a set of independent ns3::Txop, each of which represents
41 * a single DCF within a MAC stack. Each ns3::Txop has a priority
42 * implicitly associated with it (the priority is determined when the
43 * ns3::Txop is added to the ChannelAccessManager: the first Txop to be
44 * added gets the highest priority, the second, the second highest
45 * priority, and so on.) which is used to handle "internal" collisions.
46 * i.e., when two local Txop are expected to get access to the
47 * medium at the same time, the highest priority local Txop wins
48 * access to the medium and the other Txop suffers a "internal"
49 * collision.
50 */
52{
53 /// Allow test cases to access private members
54 friend class ::EmlsrUlTxopTest;
55 friend class ::EmlsrCcaBusyTest;
56
57 public:
59 ~ChannelAccessManager() override;
60
61 /**
62 * \brief Get the type ID.
63 * \return the object TypeId
64 */
65 static TypeId GetTypeId();
66
67 /**
68 * Set up (or reactivate) listener for PHY events on the given PHY. The new (or reactivated)
69 * listener becomes the active listener and the previous active listener attached to another
70 * PHY, if any, is deactivated.
71 *
72 * \param phy the WifiPhy to listen to
73 */
75 /**
76 * Remove current registered listener for PHY events on the given PHY.
77 *
78 * \param phy the WifiPhy to listen to
79 */
81 /**
82 * Deactivate current registered listener for PHY events on the given PHY. All notifications
83 * but channel switch notifications coming from an inactive listener are ignored.
84 *
85 * \param phy the WifiPhy to listen to
86 */
88 /**
89 * Set the ID of the link this Channel Access Manager is associated with.
90 *
91 * \param linkId the ID of the link this Channel Access Manager is associated with
92 */
93 void SetLinkId(uint8_t linkId);
94 /**
95 * Set up the Frame Exchange Manager.
96 *
97 * \param feManager the Frame Exchange Manager
98 */
100
101 /**
102 * \param txop a new Txop.
103 *
104 * The ChannelAccessManager does not take ownership of this pointer so, the callee
105 * must make sure that the Txop pointer will stay valid as long
106 * as the ChannelAccessManager is valid. Note that the order in which Txop
107 * objects are added to a ChannelAccessManager matters: the first Txop added
108 * has the highest priority, the second Txop added, has the second
109 * highest priority, etc.
110 */
111 void Add(Ptr<Txop> txop);
112
113 /**
114 * Determine if a new backoff needs to be generated as per letter a) of Section 10.23.2.2
115 * of IEEE 802.11-2020 ("EDCA backoff procedure"). This method is called upon the occurrence
116 * of events such as the enqueuing of a packet or the unblocking of some links after they
117 * have been blocked for some reason (e.g., wait for ADDBA Response, wait for TX on another
118 * EMLSR link to finish, etc.). The <i>checkMediumBusy</i> argument allows to generate a new
119 * backoff regardless of the busy/idle state of the medium, as per Section 35.3.16.4 of
120 * 802.11be D4.0.
121 *
122 * \param txop the Txop requesting to generate a backoff
123 * \param hadFramesToTransmit whether packets available for transmission were queued just
124 * before the occurrence of the event triggering this call
125 * \param checkMediumBusy whether generation of backoff (also) depends on the busy/idle state
126 * of the medium
127 * \return true if backoff needs to be generated, false otherwise
128 */
129 bool NeedBackoffUponAccess(Ptr<Txop> txop, bool hadFramesToTransmit, bool checkMediumBusy);
130
131 /**
132 * \param txop a Txop
133 *
134 * Notify the ChannelAccessManager that a specific Txop needs access to the
135 * medium. The ChannelAccessManager is then responsible for starting an access
136 * timer and, invoking FrameExchangeManager::StartTransmission when the access
137 * is granted if it ever gets granted.
138 */
139 void RequestAccess(Ptr<Txop> txop);
140
141 /**
142 * Access will never be granted to the medium _before_
143 * the time returned by this method.
144 *
145 * \param ignoreNav flag whether NAV should be ignored
146 *
147 * \returns the absolute time at which access could start to be granted
148 */
149 Time GetAccessGrantStart(bool ignoreNav = false) const;
150
151 /**
152 * Return the time when the backoff procedure
153 * started for the given Txop.
154 *
155 * \param txop the Txop
156 *
157 * \return the time when the backoff procedure started
158 */
160
161 /**
162 * Return the time when the backoff procedure
163 * ended (or will end) for the given Txop.
164 *
165 * \param txop the Txop
166 *
167 * \return the time when the backoff procedure ended (or will end)
168 */
169 Time GetBackoffEndFor(Ptr<Txop> txop) const;
170
171 /**
172 * \param qosTxop a QosTxop that needs to be disabled
173 * \param duration the amount of time during which the QosTxop is disabled
174 *
175 * Disable the given EDCA for the given amount of time. This EDCA will not be
176 * granted channel access during this period and the backoff timer will be frozen.
177 * After this period, the EDCA will start normal operations again by resuming
178 * the backoff timer.
179 */
180 void DisableEdcaFor(Ptr<Txop> qosTxop, Time duration);
181
182 /**
183 * Set the member variable indicating whether the backoff should be invoked when an AC gains
184 * the right to start a TXOP but it does not transmit any frame (e.g., due to constraints
185 * associated with EMLSR operations), provided that the queue is not actually empty.
186 *
187 * \param enable whether to enable backoff generation when no TX is performed in a TXOP
188 */
189 void SetGenerateBackoffOnNoTx(bool enable);
190
191 /**
192 * \return whether the backoff should be invoked when an AC gains the right to start a TXOP
193 * but it does not transmit any frame (e.g., due to constraints associated with EMLSR
194 * operations), provided that the queue is not actually empty
195 */
196 bool GetGenerateBackoffOnNoTx() const;
197
198 /**
199 * Return the width of the largest primary channel that has been idle for the
200 * given time interval before the given time, if any primary channel has been
201 * idle, or zero, otherwise.
202 *
203 * \param interval the given time interval
204 * \param end the given end time
205 * \return the width of the largest primary channel that has been idle for the given time
206 * interval before the given time, if any primary channel has been idle, or zero, otherwise
207 */
209
210 /**
211 * \param indices a set of indices (starting at 0) specifying the 20 MHz channels to test
212 * \return true if per-20 MHz CCA indicates busy for at least one of the
213 * specified 20 MHz channels, false otherwise
214 */
215 bool GetPer20MHzBusy(const std::set<uint8_t>& indices) const;
216
217 /**
218 * \param duration expected duration of reception
219 *
220 * Notify the Txop that a packet reception started
221 * for the expected duration.
222 */
223 void NotifyRxStartNow(Time duration);
224 /**
225 * Notify the Txop that a packet reception was just
226 * completed successfully.
227 */
228 void NotifyRxEndOkNow();
229 /**
230 * Notify the Txop that a packet reception was just
231 * completed unsuccessfuly.
232 */
233 void NotifyRxEndErrorNow();
234 /**
235 * \param duration expected duration of transmission
236 *
237 * Notify the Txop that a packet transmission was
238 * just started and is expected to last for the specified
239 * duration.
240 */
241 void NotifyTxStartNow(Time duration);
242 /**
243 * \param duration expected duration of CCA busy period
244 * \param channelType the channel type for which the CCA busy state is reported.
245 * \param per20MhzDurations vector that indicates for how long each 20 MHz subchannel
246 * (corresponding to the index of the element in the vector) is busy and where a zero
247 * duration indicates that the subchannel is idle. The vector is non-empty if the PHY supports
248 * 802.11ax or later and if the operational channel width is larger than 20 MHz.
249 *
250 * Notify the Txop that a CCA busy period has just started.
251 */
252 void NotifyCcaBusyStartNow(Time duration,
253 WifiChannelListType channelType,
254 const std::vector<Time>& per20MhzDurations);
255 /**
256 * \param phyListener the PHY listener that sent this notification
257 * \param duration expected duration of channel switching period
258 *
259 * Notify the Txop that a channel switching period has just started.
260 * During switching state, new packets can be enqueued in Txop/QosTxop
261 * but they won't access to the medium until the end of the channel switching.
262 */
263 void NotifySwitchingStartNow(PhyListener* phyListener, Time duration);
264 /**
265 * Notify the Txop that the device has been put in sleep mode.
266 */
267 void NotifySleepNow();
268 /**
269 * Notify the Txop that the device has been put in off mode.
270 */
271 void NotifyOffNow();
272 /**
273 * Notify the Txop that the device has been resumed from sleep mode.
274 */
275 void NotifyWakeupNow();
276 /**
277 * Notify the Txop that the device has been resumed from off mode.
278 */
279 void NotifyOnNow();
280 /**
281 * \param duration the value of the received NAV.
282 *
283 * Called at end of RX
284 */
285 void NotifyNavResetNow(Time duration);
286 /**
287 * \param duration the value of the received NAV.
288 *
289 * Called at end of RX
290 */
291 void NotifyNavStartNow(Time duration);
292 /**
293 * Notify that ack timer has started for the given duration.
294 *
295 * \param duration the duration of the timer
296 */
297 void NotifyAckTimeoutStartNow(Time duration);
298 /**
299 * Notify that ack timer has reset.
300 */
302 /**
303 * Notify that CTS timer has started for the given duration.
304 *
305 * \param duration the duration of the timer
306 */
307 void NotifyCtsTimeoutStartNow(Time duration);
308 /**
309 * Notify that CTS timer has reset.
310 */
312
313 /**
314 * Check if the device is busy sending or receiving,
315 * or NAV or CCA busy.
316 *
317 * \return true if the device is busy,
318 * false otherwise
319 */
320 bool IsBusy() const;
321
322 /**
323 * Reset the state variables of this channel access manager.
324 */
325 void ResetState();
326 /**
327 * Reset the backoff for the given DCF/EDCAF.
328 *
329 * \param txop the given DCF/EDCAF
330 */
331 void ResetBackoff(Ptr<Txop> txop);
332
333 /**
334 * Reset the backoff for all the DCF/EDCAF. Additionally, cancel the access timeout event.
335 */
336 void ResetAllBackoffs();
337
338 /**
339 * Notify that the given PHY is about to switch to the given operating channel, which is
340 * used by the given link. This notification is sent by the EMLSR Manager when a PHY object
341 * switches operating channel to operate on another link.
342 *
343 * \param phy the PHY object that is going to switch channel
344 * \param channel the new operating channel of the given PHY
345 * \param linkId the ID of the link on which the given PHY is going to operate
346 */
348 const WifiPhyOperatingChannel& channel,
349 uint8_t linkId);
350
351 protected:
352 void DoInitialize() override;
353 void DoDispose() override;
354
355 private:
356 /**
357 * Get current registered listener for PHY events on the given PHY.
358 *
359 * \param phy the given PHY
360 * \return the current registered listener for PHY events on the given PHY
361 */
362 std::shared_ptr<PhyListener> GetPhyListener(Ptr<WifiPhy> phy) const;
363
364 /**
365 * Initialize the structures holding busy end times per channel type (primary, secondary, etc.)
366 * and per 20 MHz channel. All values are set to the current time.
367 */
368 void InitLastBusyStructs();
369
370 /**
371 * Resize the structures holding busy end times per channel type (primary, secondary, etc.)
372 * and per 20 MHz channel. If a value (e.g., the busy end time for secondary40 channel) already
373 * exists, it is not changed; otherwise, it is set to the current time.
374 */
376 /**
377 * Update backoff slots for all Txops.
378 */
379 void UpdateBackoff();
380
381 /**
382 * This overload is provided to enable caching the value returned by GetAccessGrantStart(),
383 * which is independent of the given Txop object.
384 *
385 * \param txop the Txop
386 * \param accessGrantStart the value returned by GetAccessGrantStart()
387 *
388 * \return the time when the backoff procedure started
389 */
390 Time GetBackoffStartFor(Ptr<Txop> txop, Time accessGrantStart) const;
391
392 /**
393 * This overload is provided to enable caching the value returned by GetAccessGrantStart(),
394 * which is independent of the given Txop object.
395 *
396 * \param txop the Txop
397 * \param accessGrantStart the value returned by GetAccessGrantStart()
398 *
399 * \return the time when the backoff procedure ended (or will end)
400 */
401 Time GetBackoffEndFor(Ptr<Txop> txop, Time accessGrantStart) const;
402
403 /**
404 * This method determines whether the medium has been idle during a period (of
405 * non-null duration) immediately preceding the time this method is called. If
406 * so, the last idle start time and end time for each channel type are updated.
407 * Otherwise, no change is made by this method.
408 * This method is normally called when we are notified of the start of a
409 * transmission, reception, CCA Busy or switching to correctly maintain the
410 * information about the last idle period.
411 */
413
415
416 /**
417 * Called when access timeout should occur
418 * (e.g. backoff procedure expired).
419 */
420 void AccessTimeout();
421
422 /**
423 * Grant access to Txop using DCF/EDCF contention rules
424 */
425 void DoGrantDcfAccess();
426
427 /**
428 * Return the Short Interframe Space (SIFS) for this PHY.
429 *
430 * \return the SIFS duration
431 */
432 virtual Time GetSifs() const;
433
434 /**
435 * Return the slot duration for this PHY.
436 *
437 * \return the slot duration
438 */
439 virtual Time GetSlot() const;
440
441 /**
442 * Return the EIFS duration minus a DIFS.
443 *
444 * \return the EIFS duration minus a DIFS
445 */
446 virtual Time GetEifsNoDifs() const;
447
448 /**
449 * Structure defining start time and end time for a given state.
450 */
451 struct Timespan
452 {
453 Time start{0}; //!< start time
454 Time end{0}; //!< end time
455 };
456
457 /**
458 * typedef for a vector of Txops
459 */
460 typedef std::vector<Ptr<Txop>> Txops;
461
462 Txops m_txops; //!< the vector of managed Txops
463 Time m_lastAckTimeoutEnd; //!< the last Ack timeout end time
464 Time m_lastCtsTimeoutEnd; //!< the last CTS timeout end time
465 Time m_lastNavEnd; //!< the last NAV end time
466 Timespan m_lastRx; //!< the last receive start and end time
467 bool m_lastRxReceivedOk; //!< the last receive OK
468 Time m_lastTxEnd; //!< the last transmit end time
469 std::map<WifiChannelListType, Time>
470 m_lastBusyEnd; //!< the last busy end time for each channel type
471 std::vector<Time> m_lastPer20MHzBusyEnd; /**< the last busy end time per 20 MHz channel
472 (HE stations and channel width > 20 MHz only) */
473 std::map<WifiChannelListType, Timespan>
474 m_lastIdle; //!< the last idle start and end time for each channel type
475 Time m_lastSwitchingEnd; //!< the last switching end time
476 bool m_sleeping; //!< flag whether it is in sleeping state
477 bool m_off; //!< flag whether it is in off state
478 Time m_eifsNoDifs; //!< EIFS no DIFS time
479 EventId m_accessTimeout; //!< the access timeout ID
480 bool m_generateBackoffOnNoTx; //!< whether the backoff should be invoked when the AC gains the
481 //!< right to start a TXOP but it does not transmit any frame
482 //!< (e.g., due to constraints associated with EMLSR operations),
483 //!< provided that the queue is not actually empty
484 bool m_proactiveBackoff; //!< whether a new backoff value is generated when a CCA busy period
485 //!< starts and the backoff counter is zero
486
487 /// Information associated with each PHY that is going to operate on another EMLSR link
489 {
490 WifiPhyOperatingChannel channel; //!< new operating channel
491 uint8_t linkId; //!< ID of the EMLSR link on which the PHY is going to operate
492 };
493
494 /// Store information about the PHY objects that are going to operate on another EMLSR link
495 std::unordered_map<Ptr<WifiPhy>, EmlsrLinkSwitchInfo> m_switchingEmlsrLinks;
496
497 /// Maps each PHY listener to the associated PHY
498 using PhyListenerMap = std::unordered_map<Ptr<WifiPhy>, std::shared_ptr<PhyListener>>;
499
500 PhyListenerMap m_phyListeners; //!< the PHY listeners
501 Ptr<WifiPhy> m_phy; //!< pointer to the unique active PHY
502 Ptr<FrameExchangeManager> m_feManager; //!< pointer to the Frame Exchange Manager
503 uint8_t m_linkId; //!< the ID of the link this object is associated with
504};
505
506} // namespace ns3
507
508#endif /* CHANNEL_ACCESS_MANAGER_H */
Test CCA busy notifications on EMLSR clients.
Test the transmission of UL frames from EMLSR clients.
Manage a set of ns3::Txop.
bool m_proactiveBackoff
whether a new backoff value is generated when a CCA busy period starts and the backoff counter is zer...
std::vector< Time > m_lastPer20MHzBusyEnd
the last busy end time per 20 MHz channel (HE stations and channel width > 20 MHz only)
bool IsBusy() const
Check if the device is busy sending or receiving, or NAV or CCA busy.
void ResetBackoff(Ptr< Txop > txop)
Reset the backoff for the given DCF/EDCAF.
void NotifyRxEndErrorNow()
Notify the Txop that a packet reception was just completed unsuccessfuly.
bool m_off
flag whether it is in off state
void NotifySwitchingStartNow(PhyListener *phyListener, Time duration)
Time GetBackoffStartFor(Ptr< Txop > txop) const
Return the time when the backoff procedure started for the given Txop.
void ResetState()
Reset the state variables of this channel access manager.
void NotifySwitchingEmlsrLink(Ptr< WifiPhy > phy, const WifiPhyOperatingChannel &channel, uint8_t linkId)
Notify that the given PHY is about to switch to the given operating channel, which is used by the giv...
void ResetAllBackoffs()
Reset the backoff for all the DCF/EDCAF.
void NotifyWakeupNow()
Notify the Txop that the device has been resumed from sleep mode.
bool m_lastRxReceivedOk
the last receive OK
std::unordered_map< Ptr< WifiPhy >, EmlsrLinkSwitchInfo > m_switchingEmlsrLinks
Store information about the PHY objects that are going to operate on another EMLSR link.
std::map< WifiChannelListType, Timespan > m_lastIdle
the last idle start and end time for each channel type
Ptr< WifiPhy > m_phy
pointer to the unique active PHY
void NotifyAckTimeoutResetNow()
Notify that ack timer has reset.
void SetGenerateBackoffOnNoTx(bool enable)
Set the member variable indicating whether the backoff should be invoked when an AC gains the right t...
void NotifyRxEndOkNow()
Notify the Txop that a packet reception was just completed successfully.
virtual Time GetEifsNoDifs() const
Return the EIFS duration minus a DIFS.
uint8_t m_linkId
the ID of the link this object is associated with
void NotifyCcaBusyStartNow(Time duration, WifiChannelListType channelType, const std::vector< Time > &per20MhzDurations)
Time m_lastAckTimeoutEnd
the last Ack timeout end time
Time m_eifsNoDifs
EIFS no DIFS time.
virtual Time GetSlot() const
Return the slot duration for this PHY.
void NotifyAckTimeoutStartNow(Time duration)
Notify that ack timer has started for the given duration.
void AccessTimeout()
Called when access timeout should occur (e.g.
Time GetBackoffEndFor(Ptr< Txop > txop) const
Return the time when the backoff procedure ended (or will end) for the given Txop.
void UpdateBackoff()
Update backoff slots for all Txops.
void DeactivatePhyListener(Ptr< WifiPhy > phy)
Deactivate current registered listener for PHY events on the given PHY.
bool m_sleeping
flag whether it is in sleeping state
void SetLinkId(uint8_t linkId)
Set the ID of the link this Channel Access Manager is associated with.
void SetupFrameExchangeManager(Ptr< FrameExchangeManager > feManager)
Set up the Frame Exchange Manager.
bool NeedBackoffUponAccess(Ptr< Txop > txop, bool hadFramesToTransmit, bool checkMediumBusy)
Determine if a new backoff needs to be generated as per letter a) of Section 10.23....
void NotifyCtsTimeoutStartNow(Time duration)
Notify that CTS timer has started for the given duration.
void RequestAccess(Ptr< Txop > txop)
Time m_lastSwitchingEnd
the last switching end time
Timespan m_lastRx
the last receive start and end time
std::map< WifiChannelListType, Time > m_lastBusyEnd
the last busy end time for each channel type
void RemovePhyListener(Ptr< WifiPhy > phy)
Remove current registered listener for PHY events on the given PHY.
bool m_generateBackoffOnNoTx
whether the backoff should be invoked when the AC gains the right to start a TXOP but it does not tra...
Time m_lastTxEnd
the last transmit end time
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up (or reactivate) listener for PHY events on the given PHY.
Time m_lastCtsTimeoutEnd
the last CTS timeout end time
MHz_u GetLargestIdlePrimaryChannel(Time interval, Time end)
Return the width of the largest primary channel that has been idle for the given time interval before...
void DoDispose() override
Destructor implementation.
void NotifySleepNow()
Notify the Txop that the device has been put in sleep mode.
Ptr< FrameExchangeManager > m_feManager
pointer to the Frame Exchange Manager
void UpdateLastIdlePeriod()
This method determines whether the medium has been idle during a period (of non-null duration) immedi...
std::vector< Ptr< Txop > > Txops
typedef for a vector of Txops
std::unordered_map< Ptr< WifiPhy >, std::shared_ptr< PhyListener > > PhyListenerMap
Maps each PHY listener to the associated PHY.
void DisableEdcaFor(Ptr< Txop > qosTxop, Time duration)
void DoInitialize() override
Initialize() implementation.
Txops m_txops
the vector of managed Txops
bool GetPer20MHzBusy(const std::set< uint8_t > &indices) const
static TypeId GetTypeId()
Get the type ID.
void DoGrantDcfAccess()
Grant access to Txop using DCF/EDCF contention rules.
void ResizeLastBusyStructs()
Resize the structures holding busy end times per channel type (primary, secondary,...
std::shared_ptr< PhyListener > GetPhyListener(Ptr< WifiPhy > phy) const
Get current registered listener for PHY events on the given PHY.
Time m_lastNavEnd
the last NAV end time
void NotifyCtsTimeoutResetNow()
Notify that CTS timer has reset.
void NotifyOffNow()
Notify the Txop that the device has been put in off mode.
Time GetAccessGrantStart(bool ignoreNav=false) const
Access will never be granted to the medium before the time returned by this method.
void NotifyOnNow()
Notify the Txop that the device has been resumed from off mode.
PhyListenerMap m_phyListeners
the PHY listeners
virtual Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
EventId m_accessTimeout
the access timeout ID
void InitLastBusyStructs()
Initialize the structures holding busy end times per channel type (primary, secondary,...
An identifier for simulation events.
Definition event-id.h:45
A base class which provides memory management and object aggregation.
Definition object.h:78
Listener for PHY events.
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
a unique identifier for an interface.
Definition type-id.h:48
Class that keeps track of all information about the current PHY operating channel.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure defining start time and end time for a given state.
Declaration of the following enums: