From 8fb0b402fca986419ac5192323d6f86d581f4c64 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 19 Mar 2025 11:45:11 +0100 Subject: [PATCH] wifi: Enable interrupting main PHY switch if channel access is (to be) gained on aux PHY link --- src/wifi/doc/source/wifi-design.rst | 7 ++++- src/wifi/model/eht/advanced-emlsr-manager.cc | 27 +++++++++++++++----- src/wifi/model/eht/emlsr-manager.cc | 1 + src/wifi/model/eht/emlsr-manager.h | 1 + 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/wifi/doc/source/wifi-design.rst b/src/wifi/doc/source/wifi-design.rst index cf81731bf..4d79fda38 100644 --- a/src/wifi/doc/source/wifi-design.rst +++ b/src/wifi/doc/source/wifi-design.rst @@ -1368,7 +1368,8 @@ auxiliary link. The following conditions must all hold in order to request the m to the auxiliary link: * the main PHY is not in TX state -* the main PHY is not switching nor is it trying to get channel access on another auxiliary link +* the main PHY is not switching (unless switching can be interrupted, see below) nor is it trying + to get channel access on another auxiliary link * no MediumSyncDelay timer is running on the auxiliary link or the maximum number of TXOP attempts has not yet been reached * the main PHY is expected to get channel access on the auxiliary link more quickly. More precisely, @@ -1485,6 +1486,10 @@ and the new channel switch starts. This opportunity is exploited in some situati * If the main PHY is switching while an aux PHY is receiving an ICF, the switch can be interrupted so that the main PHY can start switching to the aux PHY link and be ready to operate on that link upon reception of the ICF. +* If channel access is gained, or is about to be gained, on a link on which a non-TX capable aux PHY + is operating and the main PHY is switching, the main PHY switch can be interrupted and the main + PHY can start switching to the aux PHY link, provided that the main PHY was not switching to start + a (DL or UL) TXOP and the other conditions to request the main PHY to switch are satisfied. AP EMLSR Manager ---------------- diff --git a/src/wifi/model/eht/advanced-emlsr-manager.cc b/src/wifi/model/eht/advanced-emlsr-manager.cc index 19217038e..1abad3188 100644 --- a/src/wifi/model/eht/advanced-emlsr-manager.cc +++ b/src/wifi/model/eht/advanced-emlsr-manager.cc @@ -746,12 +746,14 @@ AdvancedEmlsrManager::RequestMainPhyToSwitch(uint8_t linkId, AcIndex aci, const // the aux PHY is not TX capable; check if main PHY has to switch to the aux PHY's link auto mainPhy = GetStaMac()->GetDevice()->GetPhy(m_mainPhyId); - const auto mainPhyLinkId = GetStaMac()->GetLinkForPhy(mainPhy); - // if main PHY is not operating on a link, it is switching, hence do not request another switch - if (!mainPhyLinkId.has_value()) + // if main PHY is not operating on a link and is trying to start a (DL or UL) TXOP, then do + // not request another switch + if (m_mainPhySwitchInfo.disconnected && + (!m_interruptSwitching || m_mainPhySwitchInfo.reason == "DlTxopIcfReceivedByAuxPhy" || + m_mainPhySwitchInfo.reason == "UlTxopAuxPhyNotTxCapable")) { - NS_LOG_DEBUG("Main PHY is not operating on any link"); + NS_LOG_DEBUG("Main PHY is not operating on any link and cannot switch to another link"); return false; } @@ -787,9 +789,11 @@ AdvancedEmlsrManager::RequestMainPhyToSwitch(uint8_t linkId, AcIndex aci, const return false; } - // DoGetDelayUntilAccessRequest has already checked if the main PHY is receiving an ICF + // DoGetDelayUntilAccessRequest has already checked if the main PHY is receiving an ICF and + // above it is checked whether we can request another switch while already switching if (const auto state = mainPhy->GetState()->GetState(); - state != WifiPhyState::IDLE && state != WifiPhyState::CCA_BUSY && state != WifiPhyState::RX) + state != WifiPhyState::IDLE && state != WifiPhyState::CCA_BUSY && + state != WifiPhyState::RX && state != WifiPhyState::SWITCHING) { NS_LOG_DEBUG("Cannot request main PHY to switch when in state " << state); return false; @@ -812,6 +816,17 @@ AdvancedEmlsrManager::RequestMainPhyToSwitch(uint8_t linkId, AcIndex aci, const return true; } + const auto mainPhyLinkId = GetStaMac()->GetLinkForPhy(mainPhy); + if (!mainPhyLinkId.has_value()) + { + NS_ASSERT(m_mainPhySwitchInfo.disconnected); + NS_LOG_DEBUG("The main PHY is not connected to any link"); + // we don't know when the main PHY will be connected to the link it is switching to, nor + // which backoff value it will possibly generate; therefore, request it to switch to the + // aux PHY link + return true; + } + // let AC X be the AC that is about to gain channel access on the aux PHY link, request to // switch the main PHY if we do not expect any AC, with priority higher than or equal to that // of AC X and with frames to send on the main PHY link, to gain channel access on the main PHY diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index ace37d75e..5ba1bb359 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -906,6 +906,7 @@ EmlsrManager::SwitchMainPhy(uint8_t linkId, m_mainPhySwitchInfo.to = linkId; m_mainPhySwitchInfo.start = Simulator::Now(); m_mainPhySwitchInfo.disconnected = true; + m_mainPhySwitchInfo.reason = traceInfo.GetName(); const auto newMainPhyChannel = GetChannelForMainPhy(linkId); diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index 6ebce0bfb..f7394f2f9 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -510,6 +510,7 @@ class EmlsrManager : public Object //!< is switching or waiting to be connected to a link uint8_t from{}; //!< ID of the link which the main PHY is/has been leaving uint8_t to{}; //!< ID of the link which the main PHY is moving to + std::string reason; //!< the reason for switching the main PHY }; Time m_emlsrPaddingDelay; //!< EMLSR Padding delay