26#include "ns3/ap-wifi-mac.h"
28#include "ns3/sta-wifi-mac.h"
29#include "ns3/wifi-mac-queue.h"
31#undef NS_LOG_APPEND_CONTEXT
32#define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
48 static TypeId tid =
TypeId(
"ns3::EhtFrameExchangeManager")
50 .AddConstructor<EhtFrameExchangeManager>()
51 .SetGroupName(
"Wifi");
87 protectionManager->SetLinkId(linkId);
91 ackManager->SetLinkId(linkId);
105 mpdu->GetHeader().GetAddr1().IsGroup() ||
112 auto& hdr = mpdu->GetHeader();
116 hdr.SetAddr1(*address);
124 if (hdr.IsQosAmsdu())
126 if (hdr.IsToDs() && !hdr.IsFromDs())
129 hdr.SetAddr3(hdr.GetAddr1());
131 else if (!hdr.IsToDs() && hdr.IsFromDs())
134 hdr.SetAddr3(hdr.GetAddr2());
167 auto sigBMode = phy->GetSigBMode(txVector);
217 if (
auto psduMapIt = psduMap.find(aid);
219 (psduMapIt == psduMap.cend() ||
267 emlCapabilities->get().emlsrTransitionDelay),
269 m_mac->UnblockUnicastTxOnLinks(
270 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
279EhtFrameExchangeManager::NotifySwitchingEmlsrLink(
Ptr<WifiPhy> phy, uint8_t linkId,
Time delay)
296 m_staMac->NotifySwitchingEmlsrLink(phy, linkId);
313 const auto sequence = m_txMiddle->GetNextSequenceNumberFor(&hdr);
318 action.protectedEhtAction = WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION;
319 actionHdr.
SetAction(WifiActionHeader::PROTECTED_EHT, action);
321 auto packet = Create<Packet>();
322 packet->AddHeader(frame);
323 packet->AddHeader(actionHdr);
326 m_mac->GetQosTxop(
AC_VO)->Queue(Create<WifiMpdu>(packet, hdr));
330EhtFrameExchangeManager::GetMostRecentRssi(
const Mac48Address& address)
const
332 auto optRssi = HeFrameExchangeManager::GetMostRecentRssi(address);
339 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
347 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
349 std::optional<Mac48Address> linkAddress;
350 if (linkId != m_linkId &&
351 (linkAddress = m_mac->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(
353 (optRssi = m_mac->GetWifiRemoteStationManager(linkId)->GetMostRecentRssi(*linkAddress)))
367 uint8_t maxPaddingDelay = 0;
370 for (
const auto& address : m_sentRtsTo)
372 if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
377 auto emlCapabilities = GetWifiRemoteStationManager()->GetStationEmlCapabilities(address);
379 maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->get().emlsrPaddingDelay);
381 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
384 for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
386 if (linkId != m_linkId &&
387 m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
389 m_mac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
397 if (maxPaddingDelay > 0)
400 txParams.
m_protection->method == WifiProtection::MU_RTS_CTS);
405 auto rate = protection->muRtsTxVector.GetMode().GetDataRate(protection->muRtsTxVector);
406 std::size_t nDbps = rate / 1e6 * 4;
407 protection->muRts.SetPaddingSize((1 << (maxPaddingDelay + 2)) * nDbps / 8);
410 HeFrameExchangeManager::SendMuRts(txParams);
426 if (psdu->GetAddr1() == address)
435 if (mpdu->GetHeader().IsTrigger())
438 mpdu->GetPacket()->PeekHeader(trigger);
448 if (psdu->GetHeader(0).IsCts())
450 if (m_apMac && psdu->GetAddr1() == m_self)
454 if (m_staMac && psdu->GetAddr1() == m_bssid)
462 if (psdu->GetHeader(0).IsBlockAck())
465 psdu->GetPayload(0)->PeekHeader(blockAck);
480EhtFrameExchangeManager::TransmissionFailed()
484 for (
const auto& address : m_txTimer.GetStasExpectedToRespond())
486 if (GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
498 NS_LOG_DEBUG(
"EMLSR client " << address <<
" did not respond, continue TXOP");
499 TransmissionSucceeded();
504 HeFrameExchangeManager::TransmissionFailed();
508EhtFrameExchangeManager::NotifyChannelReleased(
Ptr<Txop> txop)
517 for (
const auto& address : m_protectedStas)
519 if (GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
521 EmlsrSwitchToListening(address, delay);
525 else if (m_staMac && m_staMac->IsEmlsrLink(m_linkId))
529 m_staMac->GetEmlsrManager()->NotifyTxopEnd(m_linkId);
532 HeFrameExchangeManager::NotifyChannelReleased(txop);
540 HeFrameExchangeManager::PostProcessFrame(psdu, txVector);
542 if (m_apMac && m_txopHolder == psdu->GetAddr2() &&
543 GetWifiRemoteStationManager()->GetEmlsrEnabled(*m_txopHolder))
545 if (!m_ongoingTxopEnd.IsRunning())
552 NS_LOG_DEBUG(
"Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
553 m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd,
this);
556 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(psdu->GetAddr2());
559 for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
561 if (linkId != m_linkId &&
562 m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
564 m_mac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
572 UpdateTxopEndOnRxEnd();
576 if (m_staMac && m_ongoingTxopEnd.IsRunning())
578 if (GetEmlsrSwitchToListening(psdu, m_staMac->GetAssociationId(), m_self))
581 m_ongoingTxopEnd.Cancel();
582 m_staMac->GetEmlsrManager()->NotifyTxopEnd(m_linkId);
586 UpdateTxopEndOnRxEnd();
598 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
600 const auto& hdr = mpdu->GetHeader();
610 mpdu->GetPacket()->PeekHeader(trigger);
612 if (hdr.GetAddr1() != m_self &&
613 (!hdr.GetAddr1().IsBroadcast() || !m_staMac->IsAssociated() ||
614 hdr.GetAddr2() != m_bssid
620 if (trigger.
IsMuRts() && m_staMac->IsEmlsrLink(m_linkId))
623 auto apAddress = GetWifiRemoteStationManager()->GetMldAddress(m_bssid);
624 NS_ASSERT_MSG(apAddress,
"MLD address not found for BSSID " << m_bssid);
628 m_staMac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, m_linkId);
629 mask && mask->test(
static_cast<std::size_t
>(
630 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK)))
636 NS_LOG_DEBUG(
"Drop ICF because another EMLSR link is being used");
641 Simulator::ScheduleNow(&EmlsrManager::NotifyIcfReceived,
642 m_staMac->GetEmlsrManager(),
646 m_ongoingTxopEnd.Cancel();
647 NS_LOG_DEBUG(
"Expected TXOP end=" << (Simulator::Now() + m_phy->GetSifs()).As(Time::S));
648 m_ongoingTxopEnd = Simulator::Schedule(m_phy->GetSifs() +
NanoSeconds(1),
649 &EhtFrameExchangeManager::TxopEnd,
654 HeFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
658EhtFrameExchangeManager::TxopEnd()
662 if (m_staMac && m_staMac->IsEmlsrLink(m_linkId))
664 m_staMac->GetEmlsrManager()->NotifyTxopEnd(m_linkId);
666 else if (m_apMac && m_txopHolder &&
667 GetWifiRemoteStationManager()->GetEmlsrEnabled(*m_txopHolder))
670 EmlsrSwitchToListening(*m_txopHolder,
Seconds(0));
675EhtFrameExchangeManager::UpdateTxopEndOnTxStart(
Time txDuration)
679 if (!m_ongoingTxopEnd.IsRunning())
685 m_ongoingTxopEnd.Cancel();
688 if (m_txTimer.IsRunning())
693 delay = m_txTimer.GetDelayLeft();
701 delay = txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
705 NS_LOG_DEBUG(
"Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
706 m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd,
this);
710EhtFrameExchangeManager::UpdateTxopEndOnRxStartIndication(
Time psduDuration)
721 m_ongoingTxopEnd.Cancel();
723 NS_LOG_DEBUG(
"Expected TXOP end=" << (Simulator::Now() + psduDuration).As(Time::S));
725 Simulator::Schedule(psduDuration +
NanoSeconds(1), &EhtFrameExchangeManager::TxopEnd,
this);
729EhtFrameExchangeManager::UpdateTxopEndOnRxEnd()
733 if (!m_ongoingTxopEnd.IsRunning())
739 m_ongoingTxopEnd.Cancel();
744 NS_LOG_DEBUG(
"Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
745 m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd,
this);
EhtFrameExchangeManager handles the frame exchange sequences for EHT stations.
void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector) override
Forward a map of PSDUs down to the PHY layer.
void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector) override
Forward a PSDU down to the PHY layer.
Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const override
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
EhtFrameExchangeManager()
void UpdateTxopEndOnTxStart(Time txDuration)
Update the TXOP end timer when starting a frame transmission.
bool GetEmlsrSwitchToListening(Ptr< const WifiPsdu > psdu, uint16_t aid, const Mac48Address &address) const
static TypeId GetTypeId()
Get the type ID.
void DoDispose() override
Destructor implementation.
bool StartTransmission(Ptr< Txop > edca, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
EventId m_ongoingTxopEnd
event indicating the possible end of the current TXOP (of which we are not the holder)
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override
void UpdateTxopEndOnRxStartIndication(Time psduDuration)
Update the TXOP end timer when receiving a PHY-RXSTART.indication.
~EhtFrameExchangeManager() override
void EmlsrSwitchToListening(const Mac48Address &address, const Time &delay)
This method is intended to be called when an AP MLD detects that an EMLSR client previously involved ...
void SetLinkId(uint8_t linkId) override
Set the ID of the link this Frame Exchange Manager is associated with.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
std::set< Mac48Address > m_protectedStas
STAs that have replied to an RTS in this TXOP.
Mac48Address GetAddress() const
Get the MAC address.
virtual void SetLinkId(uint8_t linkId)
Set the ID of the link this Frame Exchange Manager is associated with.
Ptr< WifiAckManager > GetAckManager() const
Get the Acknowledgment Manager used by this node.
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
Ptr< WifiPhy > m_phy
the PHY layer on this station
virtual bool StartTransmission(Ptr< Txop > dcf, uint16_t allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
HeFrameExchangeManager handles the frame exchange sequences for HE stations.
Ptr< ApWifiMac > m_apMac
MAC pointer (null if not an AP)
void DoDispose() override
Destructor implementation.
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override
Ptr< StaWifiMac > m_staMac
MAC pointer (null if not a STA)
virtual void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector)
Forward a map of PSDUs down to the PHY layer.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
virtual void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector)
Forward a PSDU down to the PHY layer.
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Implement the header for Action frames of type EML Operating Mode Notification.
Smart pointer class similar to boost::intrusive_ptr.
virtual Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Ptr< EmlsrManager > GetEmlsrManager() const
bool IsEmlsrLink(uint8_t linkId) const
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.
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Unblock the transmission on the given links of all unicast frames addressed to the station with the g...
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Block the transmission on the given links of all unicast frames addressed to the station with the giv...
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
bool GetEmlsrEnabled(const Mac48Address &address) const
uint16_t GetAssociationId(Mac48Address remoteAddress) const
Get the AID of a remote station.
std::optional< Mac48Address > GetAffiliatedStaAddress(const Mac48Address &mldAddress) const
Get the address of the remote station operating on this link and affiliated with the MLD having the g...
std::optional< std::reference_wrapper< CommonInfoBasicMle::EmlCapabilities > > GetStationEmlCapabilities(const Mac48Address &from)
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::unique_ptr< WifiProtection > m_protection
protection method
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiPreamble GetPreambleType() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
Declaration of ns3::EhtPhy class.
#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_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 NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WAITING_EMLSR_TRANSITION_DELAY
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
static constexpr uint8_t RX_PHY_START_DELAY_USEC
generic value for aRxPHYStartDelay PHY characteristic (used when we do not know the preamble type of ...
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
static Time DecodeEmlsrTransitionDelay(uint8_t value)
RxSignalInfo structure containing info on the received signal.
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.