From 1fd119e9ce40ea18d0ec482e5b87462dbb9cbf64 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 3 Apr 2023 17:06:38 +0200 Subject: [PATCH] wifi: Add StaWifiMac and EHT FEM methods to handle EMLSR link switching --- src/wifi/model/channel-access-manager.cc | 22 ++++-- src/wifi/model/channel-access-manager.h | 5 ++ .../model/eht/eht-frame-exchange-manager.cc | 22 ++++++ .../model/eht/eht-frame-exchange-manager.h | 10 +++ src/wifi/model/sta-wifi-mac.cc | 77 +++++++++++++++++++ src/wifi/model/sta-wifi-mac.h | 8 ++ 6 files changed, 137 insertions(+), 7 deletions(-) diff --git a/src/wifi/model/channel-access-manager.cc b/src/wifi/model/channel-access-manager.cc index 88c4555ad..e04b96a71 100644 --- a/src/wifi/model/channel-access-manager.cc +++ b/src/wifi/model/channel-access-manager.cc @@ -852,6 +852,21 @@ ChannelAccessManager::NotifySwitchingStartNow(Time duration) NS_ASSERT(m_lastTxEnd <= now); NS_ASSERT(m_lastSwitchingEnd <= now); + ResetState(); + + // Notify the FEM, which will in turn notify the MAC + m_feManager->NotifySwitchingStartNow(duration); + + NS_LOG_DEBUG("switching start for " << duration); + m_lastSwitchingEnd = now + duration; +} + +void +ChannelAccessManager::ResetState() +{ + NS_LOG_FUNCTION(this); + + Time now = Simulator::Now(); m_lastRxReceivedOk = true; UpdateLastIdlePeriod(); m_lastRx.end = std::min(m_lastRx.end, now); @@ -859,7 +874,6 @@ ChannelAccessManager::NotifySwitchingStartNow(Time duration) m_lastAckTimeoutEnd = std::min(m_lastAckTimeoutEnd, now); m_lastCtsTimeoutEnd = std::min(m_lastCtsTimeoutEnd, now); - // the new operating channel may have a different width than the previous one InitLastBusyStructs(); // Cancel timeout @@ -868,9 +882,6 @@ ChannelAccessManager::NotifySwitchingStartNow(Time duration) m_accessTimeout.Cancel(); } - // Notify the FEM, which will in turn notify the MAC - m_feManager->NotifySwitchingStartNow(duration); - // Reset backoffs for (auto txop : m_txops) { @@ -883,9 +894,6 @@ ChannelAccessManager::NotifySwitchingStartNow(Time duration) txop->ResetCw(m_linkId); txop->GetLink(m_linkId).access = Txop::NOT_REQUESTED; } - - NS_LOG_DEBUG("switching start for " << duration); - m_lastSwitchingEnd = now + duration; } void diff --git a/src/wifi/model/channel-access-manager.h b/src/wifi/model/channel-access-manager.h index 689bd1be6..eef243ef2 100644 --- a/src/wifi/model/channel-access-manager.h +++ b/src/wifi/model/channel-access-manager.h @@ -271,6 +271,11 @@ class ChannelAccessManager : public Object */ bool IsBusy() const; + /** + * Reset the state variables of this channel access manager. + */ + void ResetState(); + protected: void DoInitialize() override; void DoDispose() override; diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index 00c61cbbc..aebd5fc46 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -24,6 +24,7 @@ #include "ns3/abort.h" #include "ns3/ap-wifi-mac.h" #include "ns3/log.h" +#include "ns3/sta-wifi-mac.h" #include "ns3/wifi-mac-queue.h" #undef NS_LOG_APPEND_CONTEXT @@ -237,6 +238,27 @@ EhtFrameExchangeManager::EmlsrSwitchToListening(const Mac48Address& address, con } } +void +EhtFrameExchangeManager::NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId, Time delay) +{ + NS_LOG_FUNCTION(this << phy << linkId << delay.As(Time::US)); + + // TODO Shall we assert that there is no ongoing frame exchange sequence? Or is it possible + // that there is an ongoing frame exchange sequence (in such a case, we need to force a + // timeout, just like it is done in case of a normal channel switch + + NS_ABORT_MSG_IF(!m_staMac, "This method can only be called on a STA"); + + // 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) + { + ResetPhy(); + } + m_staMac->NotifySwitchingEmlsrLink(phy, linkId); +} + void EhtFrameExchangeManager::SendEmlOperatingModeNotification( const Mac48Address& dest, diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.h b/src/wifi/model/eht/eht-frame-exchange-manager.h index 06a9bf832..1fad02f00 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.h +++ b/src/wifi/model/eht/eht-frame-exchange-manager.h @@ -77,6 +77,16 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager uint16_t aid, const Mac48Address& address) const; + /** + * Notify that the given PHY will switch channel to operate on another EMLSR link + * after the given delay. + * + * \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, Time delay); + protected: void ForwardPsduDown(Ptr psdu, WifiTxVector& txVector) override; void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector& txVector) override; diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index bd85ef889..c735a19ca 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -1922,6 +1922,83 @@ StaWifiMac::PhyCapabilitiesChanged() } } +/** + * Initial configuration: + * + * ┌───┬───┬───┐ ┌────┐ ┌───────┐ + * Link A │FEM│RSM│CAM│◄──────►│Main├──────►│Channel│ + * │ │ │ │ │PHY │ │ A │ + * └───┴───┴───┘ └────┘ └───────┘ + * + * ┌───┬───┬───┐ ┌────┐ ┌───────┐ + * Link B │FEM│RSM│CAM│ │Aux │ │Channel│ + * │ │ │ │◄──────►│PHY ├──────►│ B │ + * └───┴───┴───┘ └────┘ └───────┘ + * + * A link switching/swapping is notified by the EMLSR Manager and the Channel Access Manager + * (CAM) notifies us that a first PHY (i.e., the Main PHY) switches to Channel B. We connect + * the Main PHY to the MAC stack B: + * + * + * ┌───┬───┬───┐ ┌────┐ ┌───────┐ + * Link A │FEM│RSM│CAM│ ┌───►│Main├───┐ │Channel│ + * │ │ │ │ │ │PHY │ │ │ A │ + * └───┴───┴───┘ │ └────┘ │ └───────┘ + * │ │ + * ┌───┬───┬───┐ │ ┌────┐ │ ┌───────┐ + * Link B │FEM│RSM│CAM│◄──┘ │Aux │ └──►│Channel│ + * │ │ │ │◄─ ─ ─ ─│PHY ├──────►│ B │ + * └───┴───┴───┘INACTIVE└────┘ └───────┘ + * + * MAC stack B keeps a PHY listener associated with the Aux PHY, even though it is inactive, + * meaning that the PHY listener will only notify channel switches (no CCA, no RX). + * If the EMLSR Manager requested a link switching, this configuration will be kept until + * further requests. If the EMLSR Manager requested a link swapping, link B's CAM will be + * notified by its (inactive) PHY listener upon the channel switch performed by the Aux PHY. + * In this case, we remove the inactive PHY listener and connect the Aux PHY to MAC stack A: + * + * ┌───┬───┬───┐ ┌────┐ ┌───────┐ + * Link A │FEM│RSM│CAM│◄─┐ ┌──►│Main├───┐ │Channel│ + * │ │ │ │ │ │ │PHY │ ┌─┼──►│ A │ + * └───┴───┴───┘ │ │ └────┘ │ │ └───────┘ + * │ │ │ │ + * ┌───┬───┬───┐ │ │ ┌────┐ │ │ ┌───────┐ + * Link B │FEM│RSM│CAM│◄─┼─┘ │Aux │ │ └──►│Channel│ + * │ │ │ │ └────►│PHY ├─┘ │ B │ + * └───┴───┴───┘ └────┘ └───────┘ + */ + +void +StaWifiMac::NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId) +{ + NS_LOG_FUNCTION(this << phy << linkId); + + // if any link points to the PHY that switched channel, reset the phy pointer + for (auto& [id, link] : GetLinks()) + { + // auto& link = GetStaLink(lnk); + if (link->phy == phy) + { + 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()) + { + 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); +} + void StaWifiMac::NotifyChannelSwitching(uint8_t linkId) { diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 04ac0bc72..4e94c8753 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -308,6 +308,14 @@ class StaWifiMac : public WifiMac */ bool IsEmlsrLink(uint8_t linkId) const; + /** + * Notify that the given PHY switched channel to operate on another EMLSR link. + * + * \param phy the given PHY + * \param linkId the ID of the EMLSR link on which the given PHY is operating + */ + void NotifySwitchingEmlsrLink(Ptr phy, uint8_t linkId); + /** * Assign a fixed random variable stream number to the random variables * used by this model. Return the number of streams (possibly zero) that