wifi: Add StaWifiMac and EHT FEM methods to handle EMLSR link switching

This commit is contained in:
Stefano Avallone
2023-04-03 17:06:38 +02:00
committed by Stefano Avallone
parent 0f04ea7caf
commit 1fd119e9ce
6 changed files with 137 additions and 7 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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<WifiPhy> 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,

View File

@@ -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<WifiPhy> phy, uint8_t linkId, Time delay);
protected:
void ForwardPsduDown(Ptr<const WifiPsdu> psdu, WifiTxVector& txVector) override;
void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector& txVector) override;

View File

@@ -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<WifiPhy> 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)
{

View File

@@ -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<WifiPhy> 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