diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index 052d38198..41de70410 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -388,6 +388,9 @@ EhtFrameExchangeManager::ForwardPsduDown(Ptr psdu, WifiTxVector& else if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) && m_staMac->GetEmlsrManager()->GetInDeviceInterference()) { + NS_ASSERT(m_staMac->GetEmlsrManager()); + m_staMac->GetEmlsrManager()->NotifyInDeviceInterferenceStart(m_linkId, txDuration); + for (const auto linkId : m_staMac->GetLinkIds()) { if (auto phy = m_mac->GetWifiPhy(linkId); @@ -474,6 +477,9 @@ EhtFrameExchangeManager::ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVect else if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) && m_staMac->GetEmlsrManager()->GetInDeviceInterference()) { + NS_ASSERT(m_staMac->GetEmlsrManager()); + m_staMac->GetEmlsrManager()->NotifyInDeviceInterferenceStart(m_linkId, txDuration); + for (const auto linkId : m_staMac->GetLinkIds()) { if (auto phy = m_mac->GetWifiPhy(linkId); diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index ddda34c3c..f473c0f17 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -518,11 +518,32 @@ EmlsrManager::NotifyTxopEnd(uint8_t linkId, bool ulTxopNotStarted, bool ongoingD } } m_staMac->UnblockTxOnLink(linkIds, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK); - - StartMediumSyncDelayTimer(linkId); }); } +void +EmlsrManager::NotifyInDeviceInterferenceStart(uint8_t linkId, Time duration) +{ + NS_LOG_FUNCTION(this << linkId << duration.As(Time::US)); + NS_ASSERT(m_inDeviceInterference); + + // The STA may choose not to (re)start the MediumSyncDelay timer if the transmission duration + // is less than or equal to aMediumSyncThreshold. (Sec. 35.3.16.8.1 802.11be D5.1) + if (duration <= MicroSeconds(MEDIUM_SYNC_THRESHOLD_USEC)) + { + return; + } + + // iterate over all the other EMLSR links + for (auto id : m_staMac->GetLinkIds()) + { + if (id != linkId && m_staMac->IsEmlsrLink(id)) + { + Simulator::Schedule(duration, &EmlsrManager::StartMediumSyncDelayTimer, this, id); + } + } +} + void EmlsrManager::SetCcaEdThresholdOnLinkSwitch(Ptr phy, uint8_t linkId) { @@ -686,36 +707,37 @@ EmlsrManager::StartMediumSyncDelayTimer(uint8_t linkId) { NS_LOG_FUNCTION(this << linkId); - // iterate over all the other EMLSR links - for (auto id : m_staMac->GetLinkIds()) + if (m_mediumSyncDuration.IsZero()) { - if (id != linkId && m_staMac->IsEmlsrLink(id)) - { - const auto [it, inserted] = m_mediumSyncDelayStatus.try_emplace(id); - - // reset the max number of TXOP attempts - it->second.msdNTxopsLeft = m_msdMaxNTxops; - - // there are cases in which no PHY is operating on a link; e.g., the main PHY starts - // switching to a link on which an aux PHY gained a TXOP and sent an RTS, but the CTS - // is not received and the UL TXOP ends before the main PHY channel switch is - // completed. The MSD timer is started on the link left "uncovered" by the main PHY - if (auto phy = m_staMac->GetWifiPhy(id); phy && !it->second.timer.IsPending()) - { - NS_LOG_DEBUG("Setting CCA ED threshold on link " - << +id << " to " << +m_msdOfdmEdThreshold << " PHY " << phy); - m_prevCcaEdThreshold[phy] = phy->GetCcaEdThreshold(); - phy->SetCcaEdThreshold(m_msdOfdmEdThreshold); - } - - // (re)start the timer - it->second.timer.Cancel(); - it->second.timer = Simulator::Schedule(m_mediumSyncDuration, - &EmlsrManager::MediumSyncDelayTimerExpired, - this, - id); - } + NS_LOG_DEBUG("MediumSyncDuration is zero"); + return; } + + const auto [it, inserted] = m_mediumSyncDelayStatus.try_emplace(linkId); + + // reset the max number of TXOP attempts + it->second.msdNTxopsLeft = m_msdMaxNTxops; + + // there are cases in which no PHY is operating on a link; e.g., the main PHY starts + // switching to a link on which an aux PHY gained a TXOP and sent an RTS, but the CTS + // is not received and the UL TXOP ends before the main PHY channel switch is + // completed. The MSD timer is started on the link left "uncovered" by the main PHY + if (auto phy = m_staMac->GetWifiPhy(linkId); phy && !it->second.timer.IsPending()) + { + NS_LOG_DEBUG("Setting CCA ED threshold on link " + << +linkId << " to " << +m_msdOfdmEdThreshold << " PHY " << phy); + m_prevCcaEdThreshold[phy] = phy->GetCcaEdThreshold(); + phy->SetCcaEdThreshold(m_msdOfdmEdThreshold); + } + + // (re)start the timer + it->second.timer.Cancel(); + NS_LOG_DEBUG("Starting MediumSyncDelay timer for " << m_mediumSyncDuration.As(Time::US) + << " on link " << +linkId); + it->second.timer = Simulator::Schedule(m_mediumSyncDuration, + &EmlsrManager::MediumSyncDelayTimerExpired, + this, + linkId); } void diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index 22e075753..dda050f21 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -41,6 +41,9 @@ class EmlsrManager : public Object friend class ::EmlsrCcaBusyTest; public: + /// The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0 + static constexpr uint16_t MEDIUM_SYNC_THRESHOLD_USEC = 72; + /** * \brief Get the type ID. * \return the object TypeId @@ -214,6 +217,15 @@ class EmlsrManager : public Object */ void NotifyTxopEnd(uint8_t linkId, bool ulTxopNotStarted = false, bool ongoingDlTxop = false); + /** + * Notify that an STA affiliated with the EMLSR client is causing in-device interference + * for the given amount of time. + * + * \param linkId the ID of the link on which the STA is operating + * \param duration the duration of the in-device interference + */ + virtual void NotifyInDeviceInterferenceStart(uint8_t linkId, Time duration); + /** * Check whether the MediumSyncDelay timer is running for the STA operating on the given link. * If so, returns the time elapsed since the timer started. @@ -423,11 +435,9 @@ class EmlsrManager : public Object void SendEmlOmn(); /** - * Start the MediumSyncDelay timer and take the appropriate actions, if the timer is not - * already running. + * Start the MediumSyncDelay timer and take the appropriate actions. * - * \param linkId the ID of the link on which a TXOP was carried out that caused the STAs - * operating on other links to lose medium synchronization + * \param linkId the ID of the link on which medium synchronization was lost */ void StartMediumSyncDelayTimer(uint8_t linkId);