27 #include "ns3/eht-frame-exchange-manager.h"
29 #include "ns3/simulator.h"
33 #undef NS_LOG_APPEND_CONTEXT
34 #define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "] "
120 const std::vector<Time>& per20MhzDurations)
override
178 TypeId(
"ns3::ChannelAccessManager")
180 .SetGroupName(
"Wifi")
182 .AddAttribute(
"GenerateBackoffIfTxopWithoutTx",
183 "Specify whether the backoff should be invoked when the AC gains the "
184 "right to start a TXOP but it does not transmit any frame "
185 "(e.g., due to constraints associated with EMLSR operations), "
186 "provided that the queue is not actually empty.",
195 : m_lastAckTimeoutEnd(0),
196 m_lastCtsTimeoutEnd(0),
199 m_lastRxReceivedOk(
true),
201 m_lastSwitchingEnd(0),
202 m_usingOtherEmlsrLink(
false),
208 InitLastBusyStructs();
237 std::shared_ptr<PhyListener>
242 return listenerIt->second;
256 "There is already an active listener registered for given PHY");
258 phyListener->SetActive(
true);
262 phyListener = std::make_shared<PhyListener>(
this);
264 phy->RegisterListener(phyListener);
272 if (
phy->IsStateSwitching())
274 auto duration =
phy->GetDelayUntilIdle();
286 phy->UnregisterListener(phyListener);
302 listener->SetActive(
false);
317 "The given PHY is already expected to switch channel");
417 bool hadFramesToTransmit,
418 bool checkMediumBusy)
420 NS_LOG_FUNCTION(
this << txop << hadFramesToTransmit << checkMediumBusy);
455 if (checkMediumBusy && !
IsBusy())
500 uint32_t nIntSlots = (diff /
GetSlot()).GetHigh() + 1;
528 NS_LOG_DEBUG(
"dcf " <<
k <<
" needs access. backoff expired. access granted. slots="
532 std::vector<Ptr<Txop>> internalCollisionTxops;
533 for (
auto j = i; j !=
m_txops.end(); j++,
k++)
540 "dcf " <<
k <<
" needs access. backoff expired. internal collision. slots="
547 internalCollisionTxops.push_back(otherTxop);
572 for (
auto& collidingTxop : internalCollisionTxops)
574 m_feManager->NotifyInternalCollision(collidingTxop);
586 k = std::distance(
m_txops.begin(), i);
620 Time accessGrantedStart;
623 accessGrantedStart =
std::max({rxAccessStart,
626 ackTimeoutAccessStart,
627 ctsTimeoutAccessStart,
628 switchingAccessStart});
632 accessGrantedStart =
std::max({rxAccessStart,
636 ackTimeoutAccessStart,
637 ctsTimeoutAccessStart,
638 switchingAccessStart});
641 <<
", rx access start=" << rxAccessStart.
As(
Time::US)
642 <<
", busy access start=" << busyAccessStart.
As(
Time::US)
643 <<
", tx access start=" << txAccessStart.
As(
Time::US)
644 <<
", nav access start=" << navAccessStart.
As(
Time::US)
645 <<
", switching access start="
647 return accessGrantedStart;
654 Time mostRecentEvent =
660 return mostRecentEvent;
696 if (txop->IsQosTxop())
702 Time backoffUpdateBound = backoffStart + (n *
GetSlot());
703 txop->UpdateBackoffSlotsNow(n, backoffUpdateBound,
m_linkId);
717 bool accessTimeoutNeeded =
false;
726 accessTimeoutNeeded =
true;
727 expectedBackoffEnd =
std::min(expectedBackoffEnd, tmp);
731 NS_LOG_DEBUG(
"Access timeout needed: " << accessTimeoutNeeded);
732 if (accessTimeoutNeeded)
734 NS_LOG_DEBUG(
"expected backoff end=" << expectedBackoffEnd);
771 if (lastIdle.second.start <= end - interval && lastIdle.second.end >= end)
774 width = (width == 0) ? 20 : (2 * width);
792 "Index 0 only can be specified if the channel width is less than 40 MHz");
796 for (
const auto index : indices)
801 NS_LOG_DEBUG(
"20 MHz channel with index " << +index <<
" is busy");
815 NS_LOG_DEBUG(
"Backoff will resume at time " << resume <<
" with "
817 <<
" remaining slot(s)");
891 const std::vector<Time>& per20MhzDurations)
899 lastBusyEndIt->second = now + duration;
901 "Size of received vector (" << per20MhzDurations.size()
902 <<
") differs from the expected size ("
904 for (std::size_t chIdx = 0; chIdx < per20MhzDurations.size(); ++chIdx)
906 if (per20MhzDurations[chIdx].IsStrictlyPositive())
932 phy->GetOperatingChannel() == emlsrInfoIt->second.channel)
939 auto ehtFem = DynamicCast<EhtFrameExchangeManager>(
m_feManager);
941 ehtFem->NotifySwitchingEmlsrLink(
phy, emlsrInfoIt->second.linkId, duration);
951 for (
const auto& txop :
m_txops)
991 if (remainingSlots > 0)
1005 for (
const auto& txop :
m_txops)
1079 NS_LOG_DEBUG(
"Do not reset NAV, CTS may have been missed due to the main PHY switching "
1080 "to another link to take over a TXOP while receiving the CTS");
1157 if (idleStart >= now)
1165 if (busyEnd.second < now)
1167 auto lastIdleIt =
m_lastIdle.find(busyEnd.first);
1169 lastIdleIt->second = {
std::max(idleStart, busyEnd.second), now};
1171 << lastIdleIt->second.end.As(
Time::S)
1172 <<
") on channel " << lastIdleIt->first);
Manage a set of ns3::Txop.
uint16_t GetLargestIdlePrimaryChannel(Time interval, Time end)
Return the width of the largest primary channel that has been idle for the given time interval before...
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 DoRestartAccessTimeoutIfNeeded()
void NotifyRxEndErrorNow()
Notify the Txop that a packet reception was just completed unsuccessfuly.
bool m_off
flag whether it is in off state
void NotifyRxStartNow(Time duration)
void NotifySwitchingStartNow(PhyListener *phyListener, Time duration)
Time GetBackoffEndFor(Ptr< Txop > txop)
Return the time when the backoff procedure ended (or will ended) 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 NotifyStopUsingOtherEmlsrLink()
Notify that another EMLSR link is no longer being used, hence medium access can be resumed.
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 NotifyTxStartNow(Time duration)
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
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.
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.
void NotifyStartUsingOtherEmlsrLink()
Notify that another EMLSR link is being used, hence medium access should be disabled.
Time m_lastCtsTimeoutEnd
the last CTS timeout end time
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
bool m_usingOtherEmlsrLink
whether another EMLSR link is being used
void UpdateLastIdlePeriod()
This method determines whether the medium has been idle during a period (of non-null duration) immedi...
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.
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
~ChannelAccessManager() override
void NotifyCtsTimeoutResetNow()
Notify that CTS timer has reset.
void NotifyOffNow()
Notify the Txop that the device has been put in off mode.
void NotifyNavResetNow(Time duration)
Time GetAccessGrantStart(bool ignoreNav=false) const
Access will never be granted to the medium before the time returned by this method.
void Add(Ptr< Txop > txop)
void NotifyOnNow()
Notify the Txop that the device has been resumed from off mode.
Time GetBackoffStartFor(Ptr< Txop > txop)
Return the time when the backoff procedure started for the given Txop.
PhyListenerMap m_phyListeners
the PHY listeners
virtual Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
void NotifyNavStartNow(Time duration)
EventId m_accessTimeout
the access timeout ID
bool GetGenerateBackoffOnNoTx() const
void InitLastBusyStructs()
Initialize the structures holding busy end times per channel type (primary, secondary,...
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
A base class which provides memory management and object aggregation.
bool m_active
whether this PHY listener is active
PhyListener(ns3::ChannelAccessManager *cam)
Create a PhyListener for the given ChannelAccessManager.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifySleep() override
Notify listeners that we went to sleep.
ns3::ChannelAccessManager * m_cam
ChannelAccessManager to forward events to.
void NotifyTxStart(Time duration, double txPowerDbm) override
void NotifyRxStart(Time duration) override
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyOn() override
Notify listeners that we went to switch on.
void NotifySwitchingStart(Time duration) override
void SetActive(bool active)
Set this listener to be active or not.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyWakeup() override
Notify listeners that we woke up.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &per20MhzDurations) override
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
static Time GetMaximumSimulationTime()
Get the maximum representable simulation time.
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
virtual ChannelAccessStatus GetAccessStatus(uint8_t linkId) const
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the Txop has frames to transmit over the given link.
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
void ResetCw(uint8_t linkId)
Update the value of the CW variable for the given link to take into account a transmission success or...
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
virtual bool IsQosTxop() const
Check for QoS TXOP.
void UpdateBackoffSlotsNow(uint32_t nSlots, Time backoffUpdateBound, uint8_t linkId)
Update backoff slots for the given link that nSlots has passed.
Time GetBackoffStart(uint8_t linkId) const
Return the time when the backoff procedure started on the given link.
virtual void NotifyAccessRequested(uint8_t linkId)
Notify that access request has been received for the given link.
uint8_t GetAifsn() const
Return the number of slots that make up an AIFS.
uint32_t GetBackoffSlots(uint8_t linkId) const
Return the current number of backoff slots on the given link.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Time GetSlot() const
Return the slot duration for this PHY.
uint16_t GetChannelWidth() const
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Time GetPifs() const
Return the PCF Interframe Space (PIFS) for this PHY.
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
void NotifyChannelAccessRequested()
Notify the PHY that an access to the channel was requested.
Time GetAckTxTime() const
Return the estimated Ack TX time for this PHY.
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
receive notifications about PHY events.
Class that keeps track of all information about the current PHY operating channel.
bool IsOfdm() const
Return whether the operating channel is an OFDM channel.
#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...
#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(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_CHANLIST_SECONDARY40
@ WIFI_CHANLIST_SECONDARY
@ WIFI_CHANLIST_SECONDARY80
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Information associated with each PHY that is going to operate on another EMLSR link.
ChannelAccessStatus access
channel access status