diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index ab1b5fc18..46ef2c014 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -148,6 +148,23 @@ EhtFrameExchangeManager::CreateAliasIfNeeded(Ptr mpdu) const return mpdu; } +bool +EhtFrameExchangeManager::StartTransmission(Ptr edca, uint16_t allowedWidth) +{ + NS_LOG_FUNCTION(this << edca << allowedWidth); + + auto started = HeFrameExchangeManager::StartTransmission(edca, allowedWidth); + + if (started && m_staMac && m_staMac->IsEmlsrLink(m_linkId)) + { + // notify the EMLSR Manager of the UL TXOP start on an EMLSR link + NS_ASSERT(m_staMac->GetEmlsrManager()); + m_staMac->GetEmlsrManager()->NotifyUlTxopStart(m_linkId); + } + + return started; +} + void EhtFrameExchangeManager::ForwardPsduDown(Ptr psdu, WifiTxVector& txVector) { @@ -497,16 +514,25 @@ EhtFrameExchangeManager::NotifyChannelReleased(Ptr txop) { NS_LOG_FUNCTION(this << txop); - // the channel has been released; all EMLSR clients will switch back to listening - // operation after a timeout interval of aSIFSTime + aSlotTime + aRxPHYStartDelay - auto delay = m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(RX_PHY_START_DELAY_USEC); - for (const auto& address : m_protectedStas) + if (m_apMac) { - if (GetWifiRemoteStationManager()->GetEmlsrEnabled(address)) + // the channel has been released; all EMLSR clients will switch back to listening + // operation after a timeout interval of aSIFSTime + aSlotTime + aRxPHYStartDelay + auto delay = m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(RX_PHY_START_DELAY_USEC); + for (const auto& address : m_protectedStas) { - EmlsrSwitchToListening(address, delay); + if (GetWifiRemoteStationManager()->GetEmlsrEnabled(address)) + { + EmlsrSwitchToListening(address, delay); + } } } + else if (m_staMac && m_staMac->IsEmlsrLink(m_linkId)) + { + // notify the EMLSR Manager of the UL TXOP end + NS_ASSERT(m_staMac->GetEmlsrManager()); + m_staMac->GetEmlsrManager()->NotifyTxopEnd(m_linkId); + } HeFrameExchangeManager::NotifyChannelReleased(txop); } diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.h b/src/wifi/model/eht/eht-frame-exchange-manager.h index d6453746a..7866798e0 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.h +++ b/src/wifi/model/eht/eht-frame-exchange-manager.h @@ -45,6 +45,7 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager void SetLinkId(uint8_t linkId) override; Ptr CreateAliasIfNeeded(Ptr mpdu) const override; + bool StartTransmission(Ptr edca, uint16_t allowedWidth) override; /** * Send an EML Operating Mode Notification frame to the given station. diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index 6342a4abb..ebf4a2401 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -270,6 +270,27 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId) mainPhy->SetPreviouslyRxPpduUid(uid); } +void +EmlsrManager::NotifyUlTxopStart(uint8_t linkId) +{ + NS_LOG_FUNCTION(this << linkId); + + if (!m_staMac->IsEmlsrLink(linkId)) + { + NS_LOG_DEBUG("EMLSR is not enabled on link " << +linkId); + return; + } + + // block transmissions on all other EMLSR links + for (auto id : m_staMac->GetLinkIds()) + { + if (id != linkId && m_staMac->IsEmlsrLink(id)) + { + m_staMac->BlockTxOnLink(id, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK); + } + } +} + void EmlsrManager::NotifyTxopEnd(uint8_t linkId) { diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index 38c462385..5a101a085 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -129,6 +129,13 @@ class EmlsrManager : public Object */ void NotifyIcfReceived(uint8_t linkId); + /** + * Notify the start of an UL TXOP on the given link + * + * \param linkId the ID of the given link + */ + void NotifyUlTxopStart(uint8_t linkId); + /** * Notify the end of a TXOP on the given link. *