15#include "ns3/assert.h"
16#include "ns3/attribute-container.h"
18#include "ns3/mgt-action-headers.h"
19#include "ns3/wifi-mpdu.h"
20#include "ns3/wifi-net-device.h"
21#include "ns3/wifi-phy-state-helper.h"
37 TypeId(
"ns3::EmlsrManager")
40 .AddAttribute(
"EmlsrPaddingDelay",
41 "The EMLSR Paddind Delay (not used by AP MLDs). "
42 "Possible values are 0 us, 32 us, 64 us, 128 us or 256 us.",
46 .AddAttribute(
"EmlsrTransitionDelay",
47 "The EMLSR Transition Delay (not used by AP MLDs). "
48 "Possible values are 0 us, 16 us, 32 us, 64 us, 128 us or 256 us.",
54 "The ID of the main PHY (position in the vector of PHYs held by "
55 "WifiNetDevice). This attribute cannot be set after construction.",
60 .AddAttribute(
"AuxPhyChannelWidth",
61 "The maximum channel width (MHz) supported by Aux PHYs. Note that the "
62 "maximum channel width is capped to the maximum channel width supported "
63 "by the configured maximum modulation class supported.",
69 .AddAttribute(
"AuxPhyMaxModClass",
70 "The maximum modulation class supported by Aux PHYs. Use "
71 "WIFI_MOD_CLASS_OFDM for non-HT.",
90 .AddAttribute(
"AuxPhyTxCapable",
91 "Whether Aux PHYs are capable of transmitting PPDUs.",
96 .AddAttribute(
"InDeviceInterference",
97 "Whether in-device interference is such that a PHY cannot decode "
98 "anything and cannot decrease the backoff counter when another PHY "
99 "of the same device is transmitting.",
106 "IDs of the links on which EMLSR mode will be enabled. An empty set "
107 "indicates to disable EMLSR.",
111 .AddAttribute(
"ResetCamState",
112 "Whether to reset the state of the ChannelAccessManager associated with "
113 "the link on which the main PHY has just switched to.",
143 m_staMac->TraceDisconnectWithoutContext(
"DroppedMpdu",
149 status.timer.Cancel();
164 "EmlsrManager can only be installed on non-AP MLDs");
167 m_staMac->TraceConnectWithoutContext(
"DroppedMpdu",
228const std::set<uint8_t>&
303std::optional<uint8_t>
312 std::stringstream ss;
315 std::copy(linkIds.cbegin(), linkIds.cend(), std::ostream_iterator<uint16_t>(ss,
" "));
318 NS_ABORT_MSG_IF(linkIds.size() == 1,
"Cannot enable EMLSR mode on a single link");
337 const auto& hdr = mpdu->GetHeader();
354 if (hdr.IsAction() && hdr.GetAddr2() ==
m_staMac->GetBssid(linkId))
359 action.protectedEhtAction ==
380 for (
auto id :
m_staMac->GetLinkIds())
382 if (
id != linkId &&
m_staMac->IsEmlsrLink(
id))
389 auto auxPhy =
m_staMac->GetWifiPhy(linkId);
391 if (
m_staMac->GetWifiPhy(linkId) != mainPhy)
400 auto uid = auxPhy->GetPreviouslyRxPpduUid();
401 mainPhy->SetPreviouslyRxPpduUid(uid);
410 auto phy =
m_staMac->GetWifiPhy(linkId);
418 return {
false, delay};
424 return {
true,
Time{0}};
436 NS_LOG_DEBUG(
"Aux PHY is not capable of transmitting a PPDU");
437 return {
false,
Time{0}};
450 NS_LOG_DEBUG(
"EMLSR is not enabled on link " << +linkId);
455 for (
auto id :
m_staMac->GetLinkIds())
457 if (
id != linkId &&
m_staMac->IsEmlsrLink(
id))
473 NS_LOG_DEBUG(
"EMLSR is not enabled on link " << +linkId);
482 if (it->second.IsPending())
484 NS_LOG_DEBUG(
"Cancelling main PHY channel switch event on link " << +linkId);
502 if (ulTxopNotStarted)
512 std::set<uint8_t> linkIds;
513 for (
auto id :
m_staMac->GetLinkIds())
515 if ((
id != linkId) &&
m_staMac->IsEmlsrLink(
id))
537 <<
" on link " << +linkId);
548 NS_LOG_DEBUG(
"Resetting CCA ED threshold of PHY " << phy <<
" to " << threshIt->second
549 <<
" on link " << +linkId);
550 phy->SetCcaEdThreshold(threshIt->second);
561 NS_LOG_FUNCTION(
this << linkId << noSwitchDelay << resetBackoff << requestAccess);
566 "Main PHY is already operating on link " << +linkId);
569 auto currMainPhyLinkId =
m_staMac->GetLinkForPhy(mainPhy);
571 NS_ASSERT_MSG(currMainPhyLinkId.has_value() || mainPhy->IsStateSwitching(),
572 "If the main PHY is not operating on a link, it must be switching");
576 NS_LOG_DEBUG(
"Main PHY (" << mainPhy <<
") is about to switch to " << newMainPhyChannel
577 <<
" to operate on link " << +linkId);
581 if (currMainPhyLinkId.has_value())
583 m_staMac->GetChannelAccessManager(*currMainPhyLinkId)
584 ->NotifySwitchingEmlsrLink(mainPhy, newMainPhyChannel, linkId);
589 "We should not ask the main PHY to switch channel while transmitting");
592 const auto delay = mainPhy->GetChannelSwitchDelay();
593 const auto pifs = mainPhy->GetSifs() + mainPhy->GetSlot();
595 "Channel switch delay ("
597 <<
") should be shorter than the maximum between the Transition delay ("
604 mainPhy->SetOperatingChannel(newMainPhyChannel);
608 mainPhy->SetAttribute(
"ChannelSwitchDelay",
TimeValue(delay));
611 if (
m_staMac->GetWifiRemoteStationManager(linkId)->GetShortSlotTimeEnabled())
616 const auto timeToSwitchEnd = noSwitchDelay ?
Seconds(0) : delay;
620 if (!currMainPhyLinkId.has_value())
622 m_staMac->NotifySwitchingEmlsrLink(mainPhy, linkId, timeToSwitchEnd);
625 if (resetBackoff && currMainPhyLinkId.has_value())
628 m_staMac->GetChannelAccessManager(*currMainPhyLinkId)->ResetAllBackoffs();
637 m_staMac->GetQosTxop(acIndex)->StartAccessAfterEvent(
656 NS_LOG_DEBUG(
"Aux PHY (" << auxPhy <<
") is about to switch to " << newAuxPhyChannel
657 <<
" to operate on link " << +nextLinkId);
660 ->GetChannelAccessManager(currLinkId)
661 ->NotifySwitchingEmlsrLink(auxPhy, newAuxPhyChannel, nextLinkId);
663 auxPhy->SetOperatingChannel(newAuxPhyChannel);
665 if (
m_staMac->GetWifiRemoteStationManager(nextLinkId)->GetShortSlotTimeEnabled())
672 for (const auto& [acIndex, ac] : wifiAcList)
674 m_staMac->GetQosTxop(acIndex)->StartAccessAfterEvent(
676 Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
677 Txop::CHECK_MEDIUM_BUSY);
681 SetCcaEdThresholdOnLinkSwitch(auxPhy, nextLinkId);
685EmlsrManager::StartMediumSyncDelayTimer(uint8_t linkId)
690 for (
auto id : m_staMac->GetLinkIds())
692 if (
id != linkId && m_staMac->IsEmlsrLink(
id))
694 const auto [it, inserted] = m_mediumSyncDelayStatus.try_emplace(
id);
697 it->second.msdNTxopsLeft = m_msdMaxNTxops;
703 if (
auto phy = m_staMac->GetWifiPhy(
id); phy && !it->second.timer.IsPending())
706 << +
id <<
" to " << +m_msdOfdmEdThreshold <<
" PHY " << phy);
707 m_prevCcaEdThreshold[phy] = phy->GetCcaEdThreshold();
708 phy->SetCcaEdThreshold(m_msdOfdmEdThreshold);
712 it->second.timer.Cancel();
713 it->second.timer = Simulator::Schedule(m_mediumSyncDuration,
714 &EmlsrManager::MediumSyncDelayTimerExpired,
722EmlsrManager::CancelMediumSyncDelayTimer(uint8_t linkId)
726 auto timerIt = m_mediumSyncDelayStatus.find(linkId);
728 NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && timerIt->second.timer.IsPending());
730 timerIt->second.timer.Cancel();
731 MediumSyncDelayTimerExpired(linkId);
735EmlsrManager::MediumSyncDelayTimerExpired(uint8_t linkId)
739 auto timerIt = m_mediumSyncDelayStatus.find(linkId);
741 NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && !timerIt->second.timer.IsPending());
744 auto phy = m_staMac->GetWifiPhy(linkId);
755 auto threshIt = m_prevCcaEdThreshold.find(phy);
757 "No value to restore for CCA ED threshold on PHY " << phy);
758 NS_LOG_DEBUG(
"Resetting CCA ED threshold of PHY " << phy <<
" to " << threshIt->second
759 <<
" on link " << +linkId);
760 phy->SetCcaEdThreshold(threshIt->second);
761 m_prevCcaEdThreshold.erase(threshIt);
765EmlsrManager::DecrementMediumSyncDelayNTxops(uint8_t linkId)
769 const auto timerIt = m_mediumSyncDelayStatus.find(linkId);
771 NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && timerIt->second.timer.IsPending());
772 NS_ASSERT(timerIt->second.msdNTxopsLeft != 0);
774 if (timerIt->second.msdNTxopsLeft)
776 --timerIt->second.msdNTxopsLeft.value();
781EmlsrManager::ResetMediumSyncDelayNTxops(uint8_t linkId)
785 auto timerIt = m_mediumSyncDelayStatus.find(linkId);
787 NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && timerIt->second.timer.IsPending());
788 timerIt->second.msdNTxopsLeft.reset();
792EmlsrManager::MediumSyncDelayNTxopsExceeded(uint8_t linkId)
796 auto timerIt = m_mediumSyncDelayStatus.find(linkId);
798 NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && timerIt->second.timer.IsPending());
799 return timerIt->second.msdNTxopsLeft == 0;
803EmlsrManager::GetEmlOmn()
808 if (m_lastAdvPaddingDelay != m_emlsrPaddingDelay ||
809 m_lastAdvTransitionDelay != m_emlsrTransitionDelay)
811 m_lastAdvPaddingDelay = m_emlsrPaddingDelay;
812 m_lastAdvTransitionDelay = m_emlsrTransitionDelay;
816 CommonInfoBasicMle::EncodeEmlsrPaddingDelay(m_lastAdvPaddingDelay);
818 CommonInfoBasicMle::EncodeEmlsrTransitionDelay(m_lastAdvTransitionDelay);
822 auto setupLinkIds = m_staMac->GetSetupLinkIds();
824 for (
auto emlsrLinkIt = m_nextEmlsrLinks->begin(); emlsrLinkIt != m_nextEmlsrLinks->end();)
826 if (
auto setupLinkIt = setupLinkIds.find(*emlsrLinkIt); setupLinkIt != setupLinkIds.cend())
828 setupLinkIds.erase(setupLinkIt);
834 NS_LOG_DEBUG(
"Link ID " << +(*emlsrLinkIt) <<
" has not been setup");
835 emlsrLinkIt = m_nextEmlsrLinks->erase(emlsrLinkIt);
846EmlsrManager::SendEmlOmn()
851 "AP did not advertise a Transition Timeout, cannot send EML notification");
852 NS_ASSERT_MSG(m_nextEmlsrLinks,
"Need to set EMLSR links before calling this method");
863 auto frame = GetEmlOmn();
864 auto linkId = GetLinkToSendEmlOmn();
865 GetEhtFem(linkId)->SendEmlOmn(m_staMac->GetBssid(linkId), frame);
873 const auto& hdr = mpdu->GetHeader();
875 if (hdr.IsAssocReq())
879 mpdu->GetPacket()->PeekHeader(assocReq);
881 NS_ASSERT_MSG(mle,
"AssocReq should contain a Multi-Link Element");
882 m_lastAdvPaddingDelay = mle->GetEmlsrPaddingDelay();
883 m_lastAdvTransitionDelay = mle->GetEmlsrTransitionDelay();
886 if (hdr.IsMgt() && hdr.IsAction())
888 if (
auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
889 category == WifiActionHeader::PROTECTED_EHT &&
890 action.protectedEhtAction ==
891 WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION)
895 NS_ASSERT_MSG(m_emlsrTransitionTimeout,
"No transition timeout received from AP");
896 m_transitionTimeoutEvent = Simulator::Schedule(*m_emlsrTransitionTimeout,
897 &EmlsrManager::ChangeEmlsrMode,
908 const auto& hdr = mpdu->GetHeader();
910 if (hdr.IsMgt() && hdr.IsAction())
912 auto pkt = mpdu->GetPacket()->Copy();
913 if (
auto [category, action] = WifiActionHeader::Remove(pkt);
914 category == WifiActionHeader::PROTECTED_EHT &&
915 action.protectedEhtAction ==
916 WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION)
920 auto linkId = ResendNotification(mpdu);
924 pkt->RemoveHeader(frame);
925 GetEhtFem(*linkId)->SendEmlOmn(m_staMac->GetBssid(*linkId), frame);
929 m_nextEmlsrLinks.reset();
936EmlsrManager::ChangeEmlsrMode()
947 NS_ASSERT_MSG(m_nextEmlsrLinks,
"No set of EMLSR links stored");
948 m_emlsrLinks.swap(*m_nextEmlsrLinks);
949 m_nextEmlsrLinks.reset();
953 m_staMac->NotifyEmlsrModeChanged(m_emlsrLinks);
955 ApplyMaxChannelWidthAndModClassOnAuxPhys();
957 NotifyEmlsrModeChanged();
961EmlsrManager::ApplyMaxChannelWidthAndModClassOnAuxPhys()
964 auto currMainPhyLinkId = m_staMac->GetLinkForPhy(m_mainPhyId);
967 for (
const auto linkId : m_staMac->GetLinkIds())
969 auto auxPhy = m_staMac->GetWifiPhy(linkId);
970 auto channel = GetChannelForAuxPhy(linkId);
972 if (linkId == currMainPhyLinkId || !m_staMac->IsEmlsrLink(linkId) ||
973 auxPhy->GetOperatingChannel() == channel)
978 auxPhy->SetMaxModulationClassSupported(m_auxPhyMaxModClass);
980 NS_LOG_DEBUG(
"Aux PHY (" << auxPhy <<
") is about to switch to " << channel
981 <<
" to operate on link " << +linkId);
987 auto cam = m_staMac->GetChannelAccessManager(linkId);
988 cam->NotifySwitchingEmlsrLink(auxPhy, channel, linkId);
990 auxPhy->SetOperatingChannel(channel);
997 cam->ResetAllBackoffs();
998 Simulator::Schedule(auxPhy->GetChannelSwitchDelay(), [=,
this]() {
999 for (const auto& [acIndex, ac] : wifiAcList)
1001 m_staMac->GetQosTxop(acIndex)->StartAccessAfterEvent(
1003 Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
1004 Txop::CHECK_MEDIUM_BUSY);
1011EmlsrManager::ComputeOperatingChannels()
1015 m_mainPhyChannels.clear();
1016 m_auxPhyChannels.clear();
1018 auto linkIds = m_staMac->GetSetupLinkIds();
1020 for (
auto linkId : linkIds)
1022 const auto& channel = m_staMac->GetWifiPhy(linkId)->GetOperatingChannel();
1023 m_mainPhyChannels.emplace(linkId, channel);
1025 auto mainPhyChWidth = channel.GetWidth();
1026 auto auxPhyMaxWidth =
1028 if (auxPhyMaxWidth >= mainPhyChWidth)
1031 m_auxPhyChannels.emplace(linkId, channel);
1035 auto freq = channel.GetPrimaryChannelCenterFrequency(auxPhyMaxWidth);
1036 auto chIt = WifiPhyOperatingChannel::FindFirst(0,
1040 channel.GetPhyBand());
1041 NS_ASSERT_MSG(chIt != WifiPhyOperatingChannel::m_frequencyChannels.end(),
1042 "Primary" << auxPhyMaxWidth <<
" channel not found");
1043 m_auxPhyChannels.emplace(linkId, chIt);
1045 auto p20Index = channel.GetPrimaryChannelIndex(20);
1046 while (mainPhyChWidth > auxPhyMaxWidth)
1048 mainPhyChWidth /= 2;
1051 m_auxPhyChannels[linkId].SetPrimary20Index(p20Index);
1056EmlsrManager::GetChannelForMainPhy(uint8_t linkId)
const
1058 auto it = m_mainPhyChannels.find(linkId);
1060 "Channel for main PHY on link ID " << +linkId <<
" not found");
1065EmlsrManager::GetChannelForAuxPhy(uint8_t linkId)
const
1067 auto it = m_auxPhyChannels.find(linkId);
1069 "Channel for aux PHY on link ID " << +linkId <<
" not found");
A container for one type of attribute.
void SendEmlOmn()
Send an EML Operating Mode Notification frame.
Time GetMediumSyncDuration() const
void ComputeOperatingChannels()
Compute the operating channels that the main PHY and the aux PHY(s) must switch to in order to operat...
void SetTransitionTimeout(Time timeout)
Set the Transition Timeout advertised by the associated AP with EMLSR activated.
virtual void NotifyMainPhySwitch(std::optional< uint8_t > currLinkId, uint8_t nextLinkId, Time duration)=0
Notify subclass that the main PHY is switching channel to operate on another link.
bool m_auxPhyTxCapable
whether Aux PHYs are capable of transmitting PPDUs
std::optional< Time > GetTransitionTimeout() const
std::pair< bool, Time > GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci)
Notify that an UL TXOP is gained on the given link by the given AC.
virtual std::pair< bool, Time > DoGetDelayUntilAccessRequest(uint8_t linkId)=0
Subclasses have to provide an implementation for this method, that is called by the base class when t...
Ptr< EhtFrameExchangeManager > GetEhtFem(uint8_t linkId) const
void TxDropped(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Notify that the given MPDU has been discarded for the given reason.
void NotifyUlTxopStart(uint8_t linkId)
Notify the start of an UL TXOP on the given link.
void TxOk(Ptr< const WifiMpdu > mpdu)
Notify the acknowledgment of the given MPDU.
void NotifyTxopEnd(uint8_t linkId, bool ulTxopNotStarted=false, bool ongoingDlTxop=false)
Notify the end of a TXOP on the given link.
std::map< uint8_t, EventId > m_ulMainPhySwitch
link ID-indexed map of timers started when an aux PHY gains an UL TXOP and schedules a channel switch...
bool m_inDeviceInterference
whether in-device interference is such that a PHY cannot decode anything and cannot decrease the back...
void SwitchMainPhy(uint8_t linkId, bool noSwitchDelay, bool resetBackoff, bool requestAccess)
Switch channel on the Main PHY so that it operates on the given link.
bool GetCamStateReset() const
void SetEmlsrLinks(const std::set< uint8_t > &linkIds)
Take actions to enable EMLSR mode on the given set of links, if non-empty, or disable EMLSR mode,...
void SetMediumSyncOfdmEdThreshold(int8_t threshold)
Set the Medium Synchronization OFDM ED threshold (dBm) to use while the MediumSyncDelay timer is runn...
uint8_t m_mainPhyId
ID of main PHY (position in the vector of PHYs held by WifiNetDevice)
int8_t GetMediumSyncOfdmEdThreshold() const
void NotifyIcfReceived(uint8_t linkId)
Notify the reception of an initial Control frame on the given link.
std::map< uint8_t, MediumSyncDelayStatus > m_mediumSyncDelayStatus
the status of MediumSyncDelay timers (link ID-indexed)
virtual std::pair< bool, Time > GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)=0
Subclasses have to provide an implementation for this method, that is called by the base class when t...
virtual void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci)=0
Subclasses have to provide an implementation for this method, that is called by the base class when t...
void NotifyMgtFrameReceived(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Notify the reception of a management frame addressed to us.
virtual void DoNotifyUlTxopStart(uint8_t linkId)=0
Notify the subclass of the start of an UL TXOP on the given link.
Ptr< StaWifiMac > m_staMac
the MAC of the managed non-AP MLD
virtual void DoNotifyMgtFrameReceived(Ptr< const WifiMpdu > mpdu, uint8_t linkId)=0
Notify the subclass of the reception of a management frame addressed to us.
Time m_emlsrPaddingDelay
EMLSR Padding delay.
bool GetInDeviceInterference() const
MHz_u m_auxPhyMaxWidth
max channel width supported by aux PHYs
void SetMediumSyncMaxNTxops(std::optional< uint8_t > nTxops)
Set the maximum number of TXOPs a non-AP STA is allowed to attempt to initiate while the MediumSyncDe...
Time m_emlsrTransitionDelay
EMLSR Transition delay.
void SetWifiMac(Ptr< StaWifiMac > mac)
Set the wifi MAC.
bool GetAuxPhyTxCapable() const
const std::set< uint8_t > & GetEmlsrLinks() const
Time m_mediumSyncDuration
duration of the MediumSyncDelay timer
std::optional< Time > m_emlsrTransitionTimeout
Transition timeout advertised by APs with EMLSR activated.
void SwitchAuxPhy(Ptr< WifiPhy > auxPhy, uint8_t currLinkId, uint8_t nextLinkId)
Switch channel on the Aux PHY operating on the given current link so that it operates on the given ne...
std::map< Ptr< WifiPhy >, dBm_u > m_prevCcaEdThreshold
the CCA sensitivity threshold to restore once the MediumSyncDelay timer expires or the PHY moves to a...
std::optional< Time > GetElapsedMediumSyncDelayTimer(uint8_t linkId) const
Check whether the MediumSyncDelay timer is running for the STA operating on the given link.
virtual void DoNotifyTxopEnd(uint8_t linkId)=0
Notify the subclass of the end of a TXOP on the given link.
virtual void DoSetWifiMac(Ptr< StaWifiMac > mac)
Allow subclasses to take actions when the MAC is set.
void SetAuxPhyTxCapable(bool capable)
Set the member variable indicating whether Aux PHYs are capable of transmitting PPDUs.
std::optional< std::set< uint8_t > > m_nextEmlsrLinks
ID of the links that will become the EMLSR links when the pending notification frame is acknowledged.
void SetCcaEdThresholdOnLinkSwitch(Ptr< WifiPhy > phy, uint8_t linkId)
Set the CCA ED threshold (if needed) on the given PHY that is switching channel to operate on the giv...
void SetMainPhyId(uint8_t mainPhyId)
Set the ID of main PHY (position in the vector of PHYs held by WifiNetDevice).
const WifiPhyOperatingChannel & GetChannelForMainPhy(uint8_t linkId) const
void SetMediumSyncDuration(Time duration)
Set the duration of the MediumSyncDelay timer.
static constexpr bool RESET_BACKOFF
reset backoff on main PHY switch
Time m_lastAdvTransitionDelay
last advertised transition delay
static constexpr bool DONT_REQUEST_ACCESS
do not request channel access when PHY switch ends
void DoDispose() override
Destructor implementation.
void StartMediumSyncDelayTimer(uint8_t linkId)
Start the MediumSyncDelay timer and take the appropriate actions, if the timer is not already running...
int8_t m_msdOfdmEdThreshold
MediumSyncDelay OFDM ED threshold.
std::optional< uint8_t > m_msdMaxNTxops
MediumSyncDelay max number of TXOPs.
Ptr< StaWifiMac > GetStaMac() const
WifiModulationClass m_auxPhyMaxModClass
max modulation class supported by aux PHYs
uint8_t GetMainPhyId() const
std::optional< uint8_t > GetMediumSyncMaxNTxops() const
void SetCamStateReset(bool enable)
Set the member variable indicating whether the state of the CAM should be reset when the main PHY swi...
EventId m_transitionTimeoutEvent
Timer started after the successful transmission of an EML Operating Mode Notification frame.
virtual void DoNotifyIcfReceived(uint8_t linkId)=0
Notify the subclass of the reception of an initial Control frame on the given link.
void SetInDeviceInterference(bool enable)
Set the member variable indicating whether in-device interference is such that a PHY cannot decode an...
const WifiPhyOperatingChannel & GetChannelForAuxPhy(uint8_t linkId) const
bool m_resetCamState
whether to reset the state of CAM when main PHY switches channel
static TypeId GetTypeId()
Get the type ID.
std::set< uint8_t > m_emlsrLinks
ID of the EMLSR links (empty if EMLSR mode is disabled)
Hold variables of type enum.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsPending() const
This method is syntactic sugar for !IsExpired().
EventImpl * PeekEventImpl() const
void Invoke()
Called by the simulation engine to notify the event that it is time to execute.
Implement the header for Action frames of type EML Operating Mode Notification.
void SetLinkIdInBitmap(uint8_t linkId)
Set the bit position in the link bitmap corresponding to the given link.
EmlControl m_emlControl
EML Control field.
std::optional< EmlsrParamUpdate > m_emlsrParamUpdate
EMLSR Parameter Update field.
A base class which provides memory management and object aggregation.
virtual void DoDispose()
Destructor implementation.
bool IsInitialized() const
Check if the object has been initialized.
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.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
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.
static constexpr bool DIDNT_HAVE_FRAMES_TO_TRANSMIT
no packet available for transmission was in the queue
static constexpr bool CHECK_MEDIUM_BUSY
generation of backoff (also) depends on the busy/idle state of the medium
a unique identifier for an interface.
@ ATTR_GET
The attribute can be read.
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
Class that keeps track of all information about the current PHY operating 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...
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< const AttributeAccessor > MakeAttributeContainerAccessor(T1 a1)
Make AttributeContainerAccessor using explicit types.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#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 MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
WifiMacDropReason
The reason why an MPDU was dropped.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ WIFI_MOD_CLASS_ERP_OFDM
ERP-OFDM (18.4)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Ptr< const AttributeChecker > MakeUintegerChecker()
static constexpr uint8_t DEFAULT_MSD_MAX_N_TXOPS
default MediumSyncDelay max number of TXOP attempts
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
MHz_u GetMaximumChannelWidth(WifiModulationClass modulation)
Get the maximum channel width allowed for the given modulation class.
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...
static constexpr int8_t DEFAULT_MSD_OFDM_ED_THRESH
default MediumSyncDelay timer OFDM ED threshold
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
static constexpr uint16_t DEFAULT_MSD_DURATION_USEC
default MediumSyncDelay timer duration (max PPDU TX time rounded to a multiple of 32 us)
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
uint8_t emlsrMode
EMLSR Mode.
uint8_t emlsrParamUpdateCtrl
EMLSR Parameter Update Control.
EMLSR Parameter Update field.