16#include "ns3/ap-wifi-mac.h" 
   18#include "ns3/mgt-action-headers.h" 
   19#include "ns3/spectrum-signal-parameters.h" 
   20#include "ns3/sta-wifi-mac.h" 
   21#include "ns3/wifi-mac-queue.h" 
   22#include "ns3/wifi-net-device.h" 
   23#include "ns3/wifi-spectrum-phy-interface.h" 
   27#undef NS_LOG_APPEND_CONTEXT 
   28#define NS_LOG_APPEND_CONTEXT WIFI_FEM_NS_LOG_APPEND_CONTEXT 
   57        TypeId(
"ns3::EhtFrameExchangeManager")
 
   59            .AddConstructor<EhtFrameExchangeManager>()
 
   61            .AddAttribute(
"EarlyTxopEndDetect",
 
   62                          "Whether the Duration/ID value of the frame being transmitted " 
   63                          "or received can be used to early detect an ongoing TXOP end.",
 
 
  102        protectionManager->SetLinkId(linkId);
 
  106        ackManager->SetLinkId(linkId);
 
 
  120        !mpdu->GetHeader().IsQosData() ||
 
  122        mpdu->GetHeader().GetAddr1().IsGroup() ||
 
  129    auto& hdr = mpdu->GetHeader();
 
  133    hdr.SetAddr1(*address);
 
  141    if (hdr.IsQosAmsdu())
 
  143        if (hdr.IsToDs() && !hdr.IsFromDs())
 
  146            hdr.SetAddr3(hdr.GetAddr1());
 
  148        else if (!hdr.IsToDs() && hdr.IsFromDs())
 
  151            hdr.SetAddr3(hdr.GetAddr2());
 
 
  165    return m_staMac->GetMacQueueScheduler()->GetAllQueuesBlockedOnLink(
 
 
  179        for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); linkId++)
 
  187            std::set<Mac48Address> emlsrClients;
 
  192            if (ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
 
  193                m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(
 
  194                    ehtFem->m_txopHolder.value()))
 
  196                NS_LOG_DEBUG(
"Involved in UL TXOP: " << ehtFem->m_txopHolder.value());
 
  197                emlsrClients.insert(ehtFem->m_txopHolder.value());
 
  201            for (
const auto& address : ehtFem->m_protectedStas)
 
  203                if (
m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(address))
 
  206                    emlsrClients.insert(address);
 
  210            for (
const auto& address : emlsrClients)
 
  213                    m_mac->GetWifiRemoteStationManager(linkId)->GetMldAddress(address);
 
  214                NS_ASSERT_MSG(mldAddress, 
"MLD address not found for " << address);
 
  230                              "No mask for client " << *mldAddress << 
" on link " << +
m_linkId);
 
  235                                  "Transmissions to " << *mldAddress << 
" on link " << +
m_linkId 
  236                                                      << 
" are not blocked");
 
  252            NS_LOG_DEBUG(
"StartTransmission called while another EMLSR link is being used");
 
  257        auto emlsrManager = 
m_staMac->GetEmlsrManager();
 
  259        if (
auto elapsed = emlsrManager->GetElapsedMediumSyncDelayTimer(
m_linkId);
 
  260            elapsed && emlsrManager->MediumSyncDelayNTxopsExceeded(
m_linkId))
 
  262            NS_LOG_DEBUG(
"No new TXOP attempts allowed while MediumSyncDelay is running");
 
  266                emlsrManager->GetMediumSyncDuration() - *elapsed,
 
  285        if (
const auto [startTxop, delay] = emlsrManager->GetDelayUntilAccessRequest(
 
  291            if (delay.IsStrictlyPositive())
 
 
  347        auto sigBMode = phy->GetSigBMode(txVector);
 
  353    if (
m_apMac && psdu->GetHeader(0).IsTrigger())
 
  365            for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
  368                    m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*clientMld))
 
  379        psdu->GetHeader(0).IsRts())
 
  390        auto delay = 
m_apMac->GetApEmlsrManager()->GetDelayOnTxPsduNotForEmlsr(psdu,
 
  392                                                                               m_phy->GetPhyBand());
 
  413             m_staMac->GetEmlsrManager()->GetInDeviceInterference())
 
  416        m_staMac->GetEmlsrManager()->NotifyInDeviceInterferenceStart(
m_linkId, txDuration);
 
 
  437            psduMap.cbegin()->second->GetPayload(0)->PeekHeader(trigger);
 
  442                for (
const auto& client : recipients)
 
  452                    for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
  455                            m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*clientMld))
 
  457                            m_mac->BlockUnicastTxOnLinks(
 
  472            const auto psduMapIt = psduMap.find(aid);
 
  473            const auto aidNotFoundAndNotTf = (psduMapIt == psduMap.cend()) && !
IsTrigger(psduMap);
 
  475            const auto psdu = (psduMapIt != psduMap.cend() ? psduMapIt : psduMap.begin())->second;
 
  491             m_staMac->GetEmlsrManager()->GetInDeviceInterference())
 
  494        m_staMac->GetEmlsrManager()->NotifyInDeviceInterferenceStart(
m_linkId, txDuration);
 
 
  508    for (
const auto& phy : 
m_staMac->GetDevice()->GetPhys())
 
  514        if (
auto id = 
m_staMac->GetLinkForPhy(phy);
 
  517            const auto txPower = phy->GetPower(txVector.
GetTxPowerLevel()) + phy->GetTxGain();
 
 
  541    for (
const auto& [range, interface] : rxPhy->GetSpectrumPhyInterfaces())
 
  543        if (!interface->GetRxSpectrumModel())
 
  555        spectrumSignalParams->duration = duration;
 
  556        spectrumSignalParams->txPhy = txPhy->GetCurrentInterface();
 
  557        spectrumSignalParams->txAntenna = txPhy->GetAntenna();
 
  558        spectrumSignalParams->psd = psd;
 
  560        rxPhy->StartRx(spectrumSignalParams, interface);
 
 
  594    NS_ASSERT_MSG(mldAddress, 
"MLD address not found for " << address);
 
  596    std::set<uint8_t> linkIds{
m_linkId};
 
  625    for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
  627        if (!
m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
 
  634        if (ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
 
  635            m_mac->GetWifiRemoteStationManager(linkId)->GetMldAddress(*ehtFem->m_txopHolder) ==
 
  638            NS_LOG_DEBUG(
"EMLSR client " << *mldAddress << 
" is the holder of an UL TXOP on link " 
  639                                         << +linkId << 
", do not unblock links");
 
  643        if (linkId == 
m_linkId && !checkThisLink)
 
  648        linkIds.insert(linkId);
 
  651                m_apMac->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(*mldAddress);
 
  653            (ehtFem->m_sentRtsTo.contains(*linkAddr) || ehtFem->m_sentFrameTo.contains(*linkAddr) ||
 
  654             ehtFem->m_protectedStas.contains(*linkAddr)))
 
  657                                         << 
" has been sent an ICF, do not unblock links");
 
 
  675    NS_ASSERT_MSG(mldAddress, 
"MLD address not found for " << address);
 
  678    auto blockLinks = [=, 
this](
bool checkThisLink) {
 
  681            NS_LOG_DEBUG(
"Could not unblock transmissions to " << address);
 
  686        std::set<uint8_t> linkIds;
 
  687        for (uint8_t linkId = 0; linkId < 
m_mac->GetNLinks(); linkId++)
 
  689            if (
m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
 
  691                linkIds.insert(linkId);
 
  700        auto unblockLinks = [=, 
this]() {
 
  710            emlCapabilities->get().emlsrTransitionDelay);
 
  712        endDelay.IsZero() ? unblockLinks()
 
  725    delay.
IsZero() ? blockLinks(
false)
 
 
  749    m_staMac->NotifySwitchingEmlsrLink(phy, linkId, delay);
 
 
  766    const auto sequence = 
m_txMiddle->GetNextSequenceNumberFor(&hdr);
 
  775    packet->AddHeader(frame);
 
  776    packet->AddHeader(actionHdr);
 
 
  800    for (uint8_t linkId = 0; linkId < 
m_mac->GetNLinks(); linkId++)
 
  802        std::optional<Mac48Address> linkAddress;
 
  804            (linkAddress = 
m_mac->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(
 
  806            (optRssi = 
m_mac->GetWifiRemoteStationManager(linkId)->GetMostRecentRssi(*linkAddress)))
 
 
  828    uint8_t maxPaddingDelay = 0;
 
  829    bool isUnprotectedEmlsrDst = 
false;
 
  831    for (
const auto& address : recipients)
 
  839        isUnprotectedEmlsrDst = 
true;
 
  842        maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->get().emlsrPaddingDelay);
 
  845    if (isUnprotectedEmlsrDst)
 
  854    if (maxPaddingDelay > 0)
 
  858        std::size_t nDbps = rate / 1e6 * 4; 
 
 
  883        auto mainPhy = 
m_staMac->GetDevice()->GetPhy(
m_staMac->GetEmlsrManager()->GetMainPhyId());
 
  892        if (mainPhy->IsStateSwitching() || 
m_mac->GetLinkForPhy(mainPhy) != 
m_linkId)
 
  894            NS_LOG_DEBUG(
"Main PHY is switching or operating on another link, abort ICF response");
 
 
  933    for (
const auto& address : clients)
 
 
  961        if (
const auto apEmlsrManager = 
m_apMac->GetApEmlsrManager();
 
  964            return apEmlsrManager->UpdateCwAfterFailedIcf();
 
 
  978        if (
const auto apEmlsrManager = 
m_apMac->GetApEmlsrManager();
 
  981            return apEmlsrManager->ReportFailedIcf();
 
 
  993    const auto& staMissedTbPpduFrom = 
m_txTimer.GetStasExpectedToRespond();
 
  996    if (staMissedTbPpduFrom.size() != nSolicitedStations)
 
 1003    const auto apEmlsrManager = 
m_apMac->GetApEmlsrManager();
 
 1004    const auto updateFailedCw =
 
 1005        crossLinkCollision && apEmlsrManager ? apEmlsrManager->UpdateCwAfterFailedIcf() : 
true;
 
 
 1011                                                  std::size_t nSolicitedStations)
 
 1015    const auto& staMissedTbPpduFrom = 
m_txTimer.GetStasExpectedToRespond();
 
 1017    if (staMissedTbPpduFrom.size() != nSolicitedStations)
 
 
 1029    const std::set<Mac48Address>& staMissedResponseFrom)
 const 
 1035    auto crossLinkCollision = 
true;
 
 1040    for (
const auto& address : staMissedResponseFrom)
 
 1044            crossLinkCollision = 
false;
 
 1051        std::set<uint8_t> linkIds; 
 
 1052        for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); linkId++)
 
 1054            if (
m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress) &&
 
 1057                linkIds.insert(linkId);
 
 1061        if (std::any_of(linkIds.cbegin(),
 
 1064                        [=, 
this](uint8_t 
id) {
 
 1065                            auto ehtFem = StaticCast<EhtFrameExchangeManager>(
 
 1066                                m_mac->GetFrameExchangeManager(id));
 
 1067                            return ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
 
 1068                                   m_mac->GetMldAddress(ehtFem->m_txopHolder.value()) == mldAddress;
 
 1078        if (std::none_of(linkIds.cbegin(),
 
 1082                         [=, 
this](uint8_t 
id) {
 
 1083                             auto macHdr = m_mac->GetFrameExchangeManager(id)->GetReceivedMacHdr();
 
 1084                             if (!macHdr.has_value())
 
 1088                             auto addr2 = macHdr->get().GetAddr2();
 
 1089                             return m_mac->GetMldAddress(addr2) == mldAddress;
 
 1092            crossLinkCollision = 
false;
 
 1096    return crossLinkCollision;
 
 
 1114        NS_ASSERT_MSG(mldAddress, 
"MLD address not found for " << addr2);
 
 1116        for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
 1119                m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
 
 1127                    m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(
AC_BE, queueId, linkId);
 
 1128                NS_ASSERT_MSG(mask, 
"No mask for client " << *mldAddress << 
" on link " << +linkId);
 
 1133                                  "Transmissions to " << *mldAddress << 
" on link " << +linkId
 
 1134                                                      << 
" are not blocked");
 
 
 1161    if (psdu->GetAddr1() == address)
 
 1170        if (mpdu->GetHeader().IsTrigger())
 
 1173            mpdu->GetPacket()->PeekHeader(trigger);
 
 1183    if (psdu->GetHeader(0).IsCts())
 
 1197    if (psdu->GetHeader(0).IsBlockAck())
 
 1200        psdu->GetPayload(0)->PeekHeader(blockAck);
 
 
 1222        NS_LOG_DEBUG(
"Reset the counter of TXOP attempts allowed while " 
 1223                     "MediumSyncDelay is running");
 
 
 1238        NS_LOG_DEBUG(
"Decrement the remaining number of TXOP attempts allowed while " 
 1239                     "MediumSyncDelay is running");
 
 
 1317                !
m_txTimer.GetStasExpectedToRespond().contains(*clientIt))
 
 
 1348        const auto unrespondedRts = (psdu->GetHeader(0).IsRts() && !
m_sendCtsEvent.IsPending());
 
 
 1405    if (
auto holder = 
FindTxopHolder(hdr, txVector); holder != sender)
 
 1407        NS_LOG_DEBUG(
"Sender (" << sender << 
") differs from the TXOP holder (" 
 1414        NS_LOG_DEBUG(
"Sender (" << sender << 
") is not an EMLSR client");
 
 1418    NS_LOG_DEBUG(
"EMLSR client " << sender << 
" is starting a TXOP");
 
 1424    for (uint8_t linkId = 0; linkId < 
m_apMac->GetNLinks(); ++linkId)
 
 1427            m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
 
 1437                m_mac->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(*mldAddress);
 
 1441            NS_LOG_DEBUG(
"Remove " << *linkAddr << 
" from protected STAs");
 
 1442            ehtFem->m_protectedStas.erase(*linkAddr);
 
 1443            ehtFem->m_sentRtsTo.erase(*linkAddr);
 
 1444            ehtFem->m_sentFrameTo.erase(*linkAddr);
 
 1459        it->second.PeekEventImpl()->Invoke();
 
 1460        it->second.Cancel();
 
 
 1489    NS_LOG_FUNCTION(
this << *mpdu << rxSignalInfo << txVector << inAmpdu);
 
 1492    NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == 
m_self);
 
 1494    const auto& hdr = mpdu->GetHeader();
 
 1495    auto sender = hdr.GetAddr2();
 
 1497    if (hdr.IsTrigger())
 
 1505        mpdu->GetPacket()->PeekHeader(trigger);
 
 1507        if (hdr.GetAddr1() != 
m_self &&
 
 1508            (!hdr.GetAddr1().IsBroadcast() || !
m_staMac->IsAssociated() ||
 
 1528             m_phy->GetPhyId() == 
m_staMac->GetEmlsrManager()->GetMainPhyId() &&
 
 1529             (hdr.IsRts() || hdr.IsBlockAckReq() || hdr.IsData()) && hdr.GetAddr1() == 
m_self)
 
 1544            for (
auto id : 
m_staMac->GetLinkIds())
 
 
 1602        NS_LOG_DEBUG(
"Dropping " << *mpdu << 
" received when CTS is scheduled for TX on link " 
 1607    const auto& hdr = mpdu->GetHeader();
 
 1617    if (hdr.IsMgt() || hdr.IsCts() || hdr.IsCfEnd() || (hdr.IsData() && hdr.GetAddr1().IsGroup()))
 
 1632            return m_mac->GetQosTxop(aciAcPair.first)->GetTxopStartTime(m_linkId).has_value();
 
 1636                                 << 
" while no TXOP is ongoing");
 
 
 1649    auto emlsrManager = 
m_staMac->GetEmlsrManager();
 
 1656        auto addr2 = icf->GetHeader().GetAddr2();
 
 1659                      "If the ICF is not sent by an adhoc peer, it must be sent by an (AP) MLD");
 
 1661        if (
auto it = std::find_if(
 
 1665                [=, 
this](uint8_t linkId) {
 
 1667                        StaticCast<EhtFrameExchangeManager>(m_mac->GetFrameExchangeManager(linkId));
 
 1668                    return linkId != m_linkId && m_staMac->IsEmlsrLink(linkId) &&
 
 1669                           ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
 
 1670                           m_mac->GetWifiRemoteStationManager(linkId)
 
 1671                                   ->GetMldAddress(*ehtFem->m_txopHolder)
 
 1672                                   .value_or(*ehtFem->m_txopHolder) == sender;
 
 1674            it != 
m_staMac->GetLinkIds().cend())
 
 1680                ->m_ongoingTxopEnd.Cancel();
 
 1693            NS_LOG_DEBUG(
"Drop ICF because another EMLSR link is being used");
 
 1718    else if (
auto mainPhy = 
m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId());
 
 1721        auto reason = emlsrManager->CheckMainPhyTakesOverDlTxop(
m_linkId);
 
 1723        if (reason.has_value())
 
 1726                "Drop ICF due to not enough time for the main PHY to switch link; reason = " 
 
 1740    if (
m_phy && 
m_phy->GetInfoIfRxingPhyHeader())
 
 1746        NS_LOG_DEBUG(
"PHY is decoding the PHY header of PPDU, postpone TXOP end");
 
 
 1790        NS_LOG_DEBUG(
"Assume TXOP will end based on Duration/ID value");
 
 1803            delay = 
Min(delay, txDuration + durationId);
 
 
 1850        NS_LOG_DEBUG(
"Assume TXOP ended based on Duration/ID value");
 
 1861        delay = 
Min(delay, durationId);
 
 
a polymophic address class
AttributeValue implementation for Boolean.
EhtFrameExchangeManager handles the frame exchange sequences for EHT stations.
void GenerateInDeviceInterferenceForAll(const Time &txDuration, const WifiTxVector &txVector)
Generate in-device interference caused by a transmission on this link for all the other PHYs of this ...
void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
bool m_earlyTxopEndDetect
whether the Duration/ID value of the frame being transmitted or received can be used to early detect ...
void TransmissionFailed(bool forceCurrentCw=false) override
Take necessary actions upon a transmission failure.
void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector) override
Forward a map of PSDUs down to the PHY layer.
void SendCtsAfterRts(const WifiMacHeader &rtsHdr, const WifiTxVector &rtsTxVector, double rtsSnr) override
Send CTS after receiving RTS.
void ReceivedQosNullAfterBsrpTf(Mac48Address sender) override
Perform the actions required when receiving QoS Null frame(s) from the given sender after a BSRP Trig...
void SetIcfPaddingAndTxVector(CtrlTriggerHeader &trigger, WifiTxVector &txVector) const
Set the padding and the TXVECTOR of the given Trigger Frame, in case it is an Initial Control Frame f...
bool UsingOtherEmlsrLink() const
void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
void NavResetTimeout() override
Reset the NAV upon expiration of the NAV reset timer.
bool GetUpdateCwOnCtsTimeout() const override
void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector) override
Forward a PSDU down to the PHY layer.
void PsduRxError(Ptr< const WifiPsdu > psdu) override
This method is called when the reception of a PSDU fails.
void EmlsrSwitchToListening(Mac48Address address, const Time &delay)
This method is intended to be called when an AP MLD detects that an EMLSR client previously involved ...
void BlockAcksInTbPpduTimeout(WifiPsduMap *psduMap, std::size_t nSolicitedStations) override
Take the necessary actions after that some BlockAck frames are missing in response to a DL MU PPDU.
void SendEmlOmn(const Mac48Address &dest, const MgtEmlOmn &frame)
Send an EML Operating Mode Notification frame to the given station.
EventId & GetOngoingTxopEndEvent()
Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const override
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
void ProtectionCompleted() override
Transmit prepared frame immediately, if no protection was used, or in a SIFS, if protection was compl...
void TbPpduTimeout(WifiPsduMap *psduMap, std::size_t nSolicitedStations) override
Take the necessary actions after that some TB PPDUs are missing in response to Trigger Frame.
bool GetReportRtsFailed() const override
void IntraBssNavResetTimeout() override
Reset the intra-BSS NAV upon expiration of the intra-BSS NAV reset timer.
bool DropReceivedIcf(Ptr< const WifiMpdu > icf)
void GenerateInDeviceInterference(Ptr< WifiPhy > phy, Time duration, Watt_u txPower)
Generate an in-device interference of the given power for the given duration for the given PHY.
bool ShallDropReceivedMpdu(Ptr< const WifiMpdu > mpdu) const
Check if the MPDU that has been received on this link shall be dropped.
void SendCtsAfterMuRts(const WifiMacHeader &muRtsHdr, const CtrlTriggerHeader &trigger, double muRtsSnr) override
Send CTS after receiving an MU-RTS.
void SwitchToListeningOrUnblockLinks(const std::set< Mac48Address > &clients)
For each EMLSR client in the given set of clients that did not respond to a frame requesting a respon...
EhtFrameExchangeManager()
bool IsCrossLinkCollision(const std::set< Mac48Address > &staMissedResponseFrom) const
Check whether all the stations that did not respond (to a certain frame) are EMLSR clients trying to ...
std::optional< dBm_u > GetMostRecentRssi(const Mac48Address &address) const override
Get the RSSI of the most recent packet received from the station having the given address.
void UpdateTxopEndOnRxEnd(Time durationId)
Update the TXOP end timer when a frame reception ends.
WifiMac::IcfDropTracedCallback m_icfDropCallback
ICF drop reason traced callback (WifiMac exposes this trace source)
bool CheckEmlsrClientStartingTxop(const WifiMacHeader &hdr, const WifiTxVector &txVector)
Check if the frame received (or being received) is sent by an EMLSR client to start an UL TXOP.
bool EmlsrClientCannotRespondToIcf() const
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
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.
std::unordered_map< Mac48Address, EventId, WifiAddressHash > m_transDelayTimer
MLD address-indexed map of transition delay timers.
void NotifyChannelReleased(Ptr< Txop > txop) override
Notify the given Txop that channel has been released.
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 ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
void UpdateTxopEndOnTxStart(Time txDuration, Time durationId)
Update the TXOP end timer when starting a frame transmission.
void SendQosNullFramesInTbPpdu(const CtrlTriggerHeader &trigger, const WifiMacHeader &hdr) override
Send QoS Null frames in response to a Basic or BSRP Trigger Frame.
void UpdateTxopEndOnRxStartIndication(Time psduDuration)
Update the TXOP end timer when receiving a PHY-RXSTART.indication.
~EhtFrameExchangeManager() override
void TxopEnd(const std::optional< Mac48Address > &txopHolder)
Take actions when a TXOP (of which we are not the holder) ends.
bool m_dlTxopStart
whether a DL TXOP start is detected and needs to be notified to the EMLSR manager after post-processi...
bool UnblockEmlsrLinksIfAllowed(Mac48Address address, bool checkThisLink)
Unblock transmissions on all the links of the given EMLSR client, provided that the latter is not inv...
void CtsAfterMuRtsTimeout(Ptr< WifiMpdu > muRts, const WifiTxVector &txVector) override
Called when no CTS frame is received after an MU-RTS.
void NotifySwitchingEmlsrLink(Ptr< WifiPhy > phy, uint8_t linkId, Time delay)
Notify that the given PHY will switch channel to operate on another EMLSR link after the given delay.
bool StartTransmission(Ptr< Txop > edca, MHz_u allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
void SetLinkId(uint8_t linkId) override
Set the ID of the link this Frame Exchange Manager is associated with.
An identifier for simulation events.
std::set< Mac48Address > m_sentRtsTo
the STA(s) which we sent an RTS to (waiting for CTS)
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
virtual void ResetPhy()
Remove WifiPhy associated with this FrameExchangeManager.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
Ptr< MacTxMiddle > m_txMiddle
the MAC TX Middle on this station
virtual bool GetReportRtsFailed() const
Mac48Address m_self
the MAC address of this device
WifiTxTimer m_txTimer
the timer set upon frame transmission
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.
virtual void NotifyChannelReleased(Ptr< Txop > txop)
Notify the given Txop that channel has been released.
Time m_txNav
the TXNAV timer
virtual void SendCtsAfterRts(const WifiMacHeader &rtsHdr, const WifiTxVector &rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Ptr< WifiAckManager > GetAckManager() const
Get the Acknowledgment Manager used by this node.
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
EventId m_sendCtsEvent
the event to send a CTS after an (MU-)RTS
Ptr< WifiPhy > m_phy
the PHY layer on this station
virtual void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
Ptr< ApWifiMac > m_apMac
AP MAC layer pointer (null if not an AP)
Mac48Address m_bssid
BSSID address (Mac48Address)
virtual void TransmissionFailed(bool forceCurrentCw=false)
Take necessary actions upon a transmission failure.
virtual bool StartTransmission(Ptr< Txop > dcf, MHz_u allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
MHz_u m_allowedWidth
the allowed width for the current transmission
Ptr< StaWifiMac > m_staMac
STA MAC layer pointer (null if not a STA)
virtual bool GetUpdateCwOnCtsTimeout() const
virtual void SendQosNullFramesInTbPpdu(const CtrlTriggerHeader &trigger, const WifiMacHeader &hdr)
Send QoS Null frames in response to a Basic or BSRP Trigger Frame.
void DoDispose() override
Destructor implementation.
virtual void IntraBssNavResetTimeout()
Reset the intra-BSS NAV upon expiration of the intra-BSS NAV reset timer.
virtual void ReceivedQosNullAfterBsrpTf(Mac48Address sender)
Perform the actions required when receiving QoS Null frame(s) from the given sender after a BSRP Trig...
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override
std::optional< Mac48Address > FindTxopHolder(const WifiMacHeader &hdr, const WifiTxVector &txVector) override
Determine the holder of the TXOP, if possible, based on the received frame.
virtual void CtsAfterMuRtsTimeout(Ptr< WifiMpdu > muRts, const WifiTxVector &txVector)
Called when no CTS frame is received after an MU-RTS.
void NavResetTimeout() override
Reset the NAV upon expiration of the NAV reset timer.
void ProtectionCompleted() override
Transmit prepared frame immediately, if no protection was used, or in a SIFS, if protection was compl...
virtual void SendCtsAfterMuRts(const WifiMacHeader &muRtsHdr, const CtrlTriggerHeader &trigger, double muRtsSnr)
Send CTS after receiving an MU-RTS.
virtual void BlockAcksInTbPpduTimeout(WifiPsduMap *psduMap, std::size_t nSolicitedStations)
Take the necessary actions after that some BlockAck frames are missing in response to a DL MU PPDU.
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
virtual void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector)
Forward a map of PSDUs down to the PHY layer.
void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
std::set< Mac48Address > GetTfRecipients(const CtrlTriggerHeader &trigger) const
Get the (link) address of the non-AP stations solicited by the given Trigger Frame.
void DoTbPpduTimeout(WifiPsduMap *psduMap, std::size_t nSolicitedStations, bool updateFailedCw)
Take the necessary actions after that some TB PPDUs are missing in response to Trigger Frame.
virtual std::optional< dBm_u > GetMostRecentRssi(const Mac48Address &address) const
Get the RSSI of the most recent packet received from the station having the given address.
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
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.
std::optional< Mac48Address > m_txopHolder
MAC address of the TXOP holder.
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.
static Time Now()
Return the current simulation virtual time.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
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.
Time TimeStep(uint64_t ts)
Scheduler interface.
bool IsZero() const
Exactly equivalent to t == 0.
void StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy)
Request channel access on the given link after the occurrence of an event that possibly requires to g...
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
static constexpr bool DONT_CHECK_MEDIUM_BUSY
generation of backoff is independent of the busy/idle state of the medium
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
WifiPreamble GetPreambleType() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
uint8_t GetTxPowerLevel() const
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...
Ptr< const AttributeChecker > MakeBooleanChecker()
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#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_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.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
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)
static constexpr uint8_t WAIT_FOR_RXSTART_DELAY_USEC
Additional time (exceeding 20 us) to wait for a PHY-RXSTART.indication when the PHY is decoding a PHY...
double MHz_u
MHz weak type.
bool IsTrigger(const WifiPsduMap &psduMap)
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
std::tuple< WifiContainerQueueType, WifiRcvAddr, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
double Watt_u
Watt weak type.
const Time EMLSR_RX_PHY_START_DELAY
aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations (Sec.
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 Time DecodeEmlsrTransitionDelay(uint8_t value)
RxSignalInfo structure containing info on the received signal.