From 5ae9fabf493b89b7d24bea9c8b1ead80861fba24 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Fri, 29 Sep 2023 09:55:15 +0200 Subject: [PATCH] wifi: PHY operates on EMLSR link until another PHY completes channel switching --- src/wifi/model/eht/default-emlsr-manager.cc | 5 +- .../model/eht/eht-frame-exchange-manager.cc | 8 +-- src/wifi/model/eht/emlsr-manager.cc | 16 ++++-- src/wifi/model/sta-wifi-mac.cc | 50 ++++++++++++------- src/wifi/model/sta-wifi-mac.h | 3 +- 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/wifi/model/eht/default-emlsr-manager.cc b/src/wifi/model/eht/default-emlsr-manager.cc index 67aa52ef8..bcbb5171a 100644 --- a/src/wifi/model/eht/default-emlsr-manager.cc +++ b/src/wifi/model/eht/default-emlsr-manager.cc @@ -133,7 +133,10 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId) auto phy = m_auxPhyToReconnect; SwitchMainPhy(*m_linkIdForMainPhyAfterTxop, false); // Reconnect the aux PHY to its original link - Simulator::ScheduleNow(&StaWifiMac::NotifySwitchingEmlsrLink, GetStaMac(), phy, linkId); + Simulator::ScheduleNow([=, this]() { + // the Aux PHY is not actually switching (hence no switching delay) + GetStaMac()->NotifySwitchingEmlsrLink(phy, linkId, Seconds(0)); + }); SetCcaEdThresholdOnLinkSwitch(phy, linkId); } m_linkIdForMainPhyAfterTxop.reset(); diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index dd42bdfda..1fda0309e 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -407,12 +407,14 @@ EhtFrameExchangeManager::NotifySwitchingEmlsrLink(Ptr phy, uint8_t link // if we receive the notification from a PHY that is not connected to us, it means that // we have been already connected to another PHY operating on this link, hence we do not - // have to reset the connected PHY - if (phy == m_phy) + // have to reset the connected PHY. Similarly, we do not have to reset the connected PHY if + // the link does not change (this occurs when changing the channel width of aux PHYs upon + // enabling the EMLSR mode). + if (phy == m_phy && linkId != m_linkId) { ResetPhy(); } - m_staMac->NotifySwitchingEmlsrLink(phy, linkId); + m_staMac->NotifySwitchingEmlsrLink(phy, linkId, delay); } void diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index ab14fca43..695189523 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -882,12 +882,22 @@ EmlsrManager::ApplyMaxChannelWidthAndModClassOnAuxPhys() // this channel switch must not have such a consequence. We already have a method // for doing so, i.e., inform the MAC that the PHY is switching channel to operate // on the "same" link. - m_staMac->GetChannelAccessManager(linkId)->NotifySwitchingEmlsrLink(auxPhy, - channel, - linkId); + auto cam = m_staMac->GetChannelAccessManager(linkId); + cam->NotifySwitchingEmlsrLink(auxPhy, channel, linkId); void (WifiPhy::*fp)(const WifiPhyOperatingChannel&) = &WifiPhy::SetOperatingChannel; Simulator::ScheduleNow(fp, auxPhy, channel); + + // the way the ChannelAccessManager handles EMLSR link switch implies that a PHY listener + // is removed when the channel switch starts and another one is attached when the channel + // switch ends. In the meantime, no PHY is connected to the ChannelAccessManager. Inform + // the ChannelAccessManager that this channel switch is related to EMLSR operations, so + // that the ChannelAccessManager does not complain if events requiring access to the PHY + // occur during the channel switch. + cam->NotifyStartUsingOtherEmlsrLink(); + Simulator::Schedule(auxPhy->GetChannelSwitchDelay(), + &ChannelAccessManager::NotifyStopUsingOtherEmlsrLink, + cam); } } diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index f6d578b40..50a82f812 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -2024,34 +2024,50 @@ StaWifiMac::PhyCapabilitiesChanged() */ void -StaWifiMac::NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId) +StaWifiMac::NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId, Time delay) { - NS_LOG_FUNCTION(this << phy << linkId); + NS_LOG_FUNCTION(this << phy << linkId << delay.As(Time::US)); - // if any link points to the PHY that switched channel, reset the phy pointer + // If the PHY is switching channel to operate on another link, then it is no longer operating + // on the current link. If any link (other than the current link) points to the PHY that is + // switching channel, reset the phy pointer of the link for (auto& [id, link] : GetLinks()) { - // auto& link = GetStaLink(lnk); - if (link->phy == phy) + if (link->phy == phy && id != linkId) { link->phy = nullptr; } } - auto& newLink = GetLink(linkId); - // The MAC stack associated with the new link uses the given PHY - newLink.phy = phy; - // Setup a PHY listener for the given PHY on the CAM associated with the new link - newLink.channelAccessManager->SetupPhyListener(phy); - NS_ASSERT(m_emlsrManager); - if (m_emlsrManager->GetCamStateReset()) + // lambda to connect the PHY to the new link + auto connectPhy = [=, this]() mutable { + auto& newLink = GetLink(linkId); + // The MAC stack associated with the new link uses the given PHY + newLink.phy = phy; + // Setup a PHY listener for the given PHY on the CAM associated with the new link + newLink.channelAccessManager->SetupPhyListener(phy); + NS_ASSERT(m_emlsrManager); + if (m_emlsrManager->GetCamStateReset()) + { + newLink.channelAccessManager->ResetState(); + } + // Disconnect the FEM on the new link from the current PHY + newLink.feManager->ResetPhy(); + // Connect the FEM on the new link to the given PHY + newLink.feManager->SetWifiPhy(phy); + }; + + // if there is no PHY operating on the new link, connect the PHY to the new link now. + // Otherwise, wait until the channel switch is completed, so that the PHY operating on the new + // link can possibly continue receiving frames in the meantime. + if (!GetLink(linkId).phy) { - newLink.channelAccessManager->ResetState(); + connectPhy(); + } + else + { + Simulator::Schedule(delay, connectPhy); } - // Disconnect the FEM on the new link from the current PHY - newLink.feManager->ResetPhy(); - // Connect the FEM on the new link to the given PHY - newLink.feManager->SetWifiPhy(phy); } void diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 5412543b0..0eb0b72fe 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -307,8 +307,9 @@ class StaWifiMac : public WifiMac * * \param phy the given PHY * \param linkId the ID of the EMLSR link on which the given PHY is operating + * \param delay the delay after which the channel switch will be completed */ - void NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId); + void NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId, Time delay); /** * Block transmissions on the given link for the given reason.