diff --git a/src/wifi/model/eht/advanced-emlsr-manager.cc b/src/wifi/model/eht/advanced-emlsr-manager.cc index d206d0c54..d8d603fa2 100644 --- a/src/wifi/model/eht/advanced-emlsr-manager.cc +++ b/src/wifi/model/eht/advanced-emlsr-manager.cc @@ -107,7 +107,7 @@ AdvancedEmlsrManager::DoSetWifiMac(Ptr mac) } } -Time +std::pair AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) { NS_LOG_FUNCTION(this << linkId); @@ -131,7 +131,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) hdr.IsTrigger() && (hdr.GetAddr1().IsBroadcast() || hdr.GetAddr1() == GetEhtFem(id)->GetAddress())) { - return phy->GetDelayUntilIdle(); + return {false, phy->GetDelayUntilIdle()}; } continue; } @@ -143,7 +143,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) if (!m_allowUlTxopInRx) { // retry channel access after the end of the current PHY header field - return phy->GetDelayUntilIdle(); + return {false, phy->GetDelayUntilIdle()}; } continue; } @@ -157,7 +157,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) if (!m_useNotifiedMacHdr) { // restart channel access at the end of PSDU reception - return phy->GetDelayUntilIdle(); + return {false, phy->GetDelayUntilIdle()}; } // retry channel access after the expected end of the MAC header reception @@ -192,14 +192,14 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) .CalculateBytesTxTime(macHdrSize); const auto timeSinceRxStart = Simulator::Now() - phy->GetState()->GetLastTime({WifiPhyState::CCA_BUSY}); - return Max(macHdrDuration - timeSinceRxStart, Time{0}); + return {false, Max(macHdrDuration - timeSinceRxStart, Time{0})}; } continue; } } } - return Time{0}; + return {true, Time{0}}; } void @@ -290,7 +290,7 @@ AdvancedEmlsrManager::DoNotifyTxopEnd(uint8_t linkId) } } -Time +std::pair AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) { NS_LOG_FUNCTION(this << linkId); @@ -316,7 +316,7 @@ AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: " << mainPhy->GetState()->GetState() << ")"); // retry channel access when the CTS was expected to be received - return timeToCtsEnd; + return {false, timeToCtsEnd}; } // TXOP can be started, schedule main PHY switch. Main PHY shall terminate the channel switch @@ -333,7 +333,7 @@ AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) RESET_BACKOFF, DONT_REQUEST_ACCESS); - return Time{0}; + return {true, Time{0}}; } void diff --git a/src/wifi/model/eht/advanced-emlsr-manager.h b/src/wifi/model/eht/advanced-emlsr-manager.h index 180f9fca8..62a47cfc7 100644 --- a/src/wifi/model/eht/advanced-emlsr-manager.h +++ b/src/wifi/model/eht/advanced-emlsr-manager.h @@ -34,8 +34,8 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager protected: void DoDispose() override; void DoSetWifiMac(Ptr mac) override; - Time DoGetDelayUntilAccessRequest(uint8_t linkId) override; - Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override; + std::pair DoGetDelayUntilAccessRequest(uint8_t linkId) override; + std::pair GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override; void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override; /** diff --git a/src/wifi/model/eht/default-emlsr-manager.cc b/src/wifi/model/eht/default-emlsr-manager.cc index 5b13bc2ab..66f276427 100644 --- a/src/wifi/model/eht/default-emlsr-manager.cc +++ b/src/wifi/model/eht/default-emlsr-manager.cc @@ -171,11 +171,11 @@ DefaultEmlsrManager::NotifyMainPhySwitch(std::optional currLinkId, } } -Time +std::pair DefaultEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId) { NS_LOG_FUNCTION(this << linkId); - return Time{0}; // start the TXOP + return {true, Time{0}}; // start the TXOP } void @@ -271,7 +271,7 @@ DefaultEmlsrManager::GetTimeToCtsEnd(uint8_t linkId) const return rtsTxTime + phy->GetSifs() + ctsTxTime + MicroSeconds(2 * MAX_PROPAGATION_DELAY_USEC); } -Time +std::pair DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) { NS_LOG_FUNCTION(this << linkId); @@ -296,7 +296,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: " << mainPhy->GetState()->GetState() << ")"); // retry channel access when the CTS was expected to be received - return timeToCtsEnd; + return {false, timeToCtsEnd}; } break; default: @@ -317,7 +317,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) RESET_BACKOFF, DONT_REQUEST_ACCESS); - return Time{0}; + return {true, Time{0}}; } } // namespace ns3 diff --git a/src/wifi/model/eht/default-emlsr-manager.h b/src/wifi/model/eht/default-emlsr-manager.h index 8bc0dde8a..ee9e92ff7 100644 --- a/src/wifi/model/eht/default-emlsr-manager.h +++ b/src/wifi/model/eht/default-emlsr-manager.h @@ -36,9 +36,9 @@ class DefaultEmlsrManager : public EmlsrManager protected: uint8_t GetLinkToSendEmlOmn() override; std::optional ResendNotification(Ptr mpdu) override; - Time DoGetDelayUntilAccessRequest(uint8_t linkId) override; + std::pair DoGetDelayUntilAccessRequest(uint8_t linkId) override; void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override; - Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override; + std::pair GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override; /** * This function is intended to be called when an aux PHY is about to transmit an RTS on diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index ec550099f..6d9320f74 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -276,28 +276,24 @@ EhtFrameExchangeManager::StartTransmission(Ptr edca, MHz_u allowedWidth) } // let EMLSR manager decide whether to prevent or allow this UL TXOP - if (auto delay = emlsrManager->GetDelayUntilAccessRequest( + if (const auto [startTxop, delay] = emlsrManager->GetDelayUntilAccessRequest( m_linkId, DynamicCast(edca)->GetAccessCategory()); - delay.IsStrictlyPositive()) - { - NotifyChannelReleased(edca); - Simulator::Schedule(delay, - &Txop::StartAccessAfterEvent, - edca, - m_linkId, - Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT, // queued frames cannot be - // transmitted until RX ends - Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy - return false; - } + !startTxop) - // in case of aux PHY that is not TX capable, the main PHY can transmit if the medium is - // sensed idle for a PIFS after the end of channel switch (assuming main PHY is switching) - if (auto mainPhy = m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId()); - m_phy != mainPhy && !emlsrManager->GetAuxPhyTxCapable()) { - NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU"); + if (delay.IsStrictlyPositive()) + { + NotifyChannelReleased(edca); + Simulator::Schedule( + delay, + &Txop::StartAccessAfterEvent, + edca, + m_linkId, + Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT, // queued frames cannot be + // transmitted until RX ends + Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy + } return false; } } diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index cf183f14e..d3df4eb5d 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -404,7 +404,7 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId) DoNotifyIcfReceived(linkId); } -Time +std::pair EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci) { auto phy = m_staMac->GetWifiPhy(linkId); @@ -413,15 +413,15 @@ EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci) auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId); // check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs - if (auto delay = DoGetDelayUntilAccessRequest(linkId); delay.IsStrictlyPositive()) + if (const auto [startTxop, delay] = DoGetDelayUntilAccessRequest(linkId); !startTxop) { - return delay; + return {false, delay}; } if (phy == mainPhy) { // no more constraints to check if medium was gained by main PHY - return Time{0}; + return {true, Time{0}}; } // an aux PHY is operating on the given link; call the appropriate method depending on @@ -433,7 +433,8 @@ EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci) // PHY switches link, the UL TXOP will be started; if the main PHY does not switch, it is // because it is going to start an UL TXOP on another link and this link will be restarted // at the end of that UL TXOP when this link will be unblocked - return Time{0}; + NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU"); + return {false, Time{0}}; } return GetDelayUnlessMainPhyTakesOverUlTxop(linkId); diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index aa6e521cf..22e075753 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -18,6 +18,7 @@ #include #include #include +#include class EmlsrCcaBusyTest; @@ -147,10 +148,11 @@ class EmlsrManager : public Object * * \param linkId the ID of the given link * \param aci the index of the given AC - * \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client - * restarts channel access, otherwise + * \return a pair consisting of a boolean value indicating whether the UL TXOP can be started + * and a Time value indicating the delay after which the EMLSR client must restart + * channel access (if needed) in case the UL TXOP is not started */ - Time GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci); + std::pair GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci); /** * Set the member variable indicating whether Aux PHYs are capable of transmitting PPDUs. @@ -357,10 +359,11 @@ class EmlsrManager : public Object * check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs. * * \param linkId the ID of the given link - * \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client - * restarts channel access, otherwise + * \return a pair consisting of a boolean value indicating whether the UL TXOP can be started + * and a Time value indicating the delay after which the EMLSR client must restart + * channel access (if needed) in case the UL TXOP is not started */ - virtual Time DoGetDelayUntilAccessRequest(uint8_t linkId) = 0; + virtual std::pair DoGetDelayUntilAccessRequest(uint8_t linkId) = 0; /** * Subclasses have to provide an implementation for this method, that is called by the base @@ -381,10 +384,11 @@ class EmlsrManager : public Object * EMLSR client restarts channel access on the given link, otherwise. * * \param linkId the ID of the given link - * \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client - * restarts channel access, otherwise + * \return a pair consisting of a boolean value indicating whether the UL TXOP can be started + * and a Time value indicating the delay after which the EMLSR client must restart + * channel access (if needed) in case the UL TXOP is not started */ - virtual Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) = 0; + virtual std::pair GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) = 0; Time m_emlsrPaddingDelay; //!< EMLSR Padding delay Time m_emlsrTransitionDelay; //!< EMLSR Transition delay