wifi: PHY operates on EMLSR link until another PHY completes channel switching

This commit is contained in:
Stefano Avallone
2023-09-29 09:55:15 +02:00
committed by Stefano Avallone
parent 7dfb732a0d
commit 5ae9fabf49
5 changed files with 57 additions and 25 deletions

View File

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

View File

@@ -407,12 +407,14 @@ EhtFrameExchangeManager::NotifySwitchingEmlsrLink(Ptr<WifiPhy> 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

View File

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

View File

@@ -2024,34 +2024,50 @@ StaWifiMac::PhyCapabilitiesChanged()
*/
void
StaWifiMac::NotifySwitchingEmlsrLink(Ptr<WifiPhy> phy, uint8_t linkId)
StaWifiMac::NotifySwitchingEmlsrLink(Ptr<WifiPhy> 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

View File

@@ -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<WifiPhy> phy, uint8_t linkId);
void NotifySwitchingEmlsrLink(Ptr<WifiPhy> phy, uint8_t linkId, Time delay);
/**
* Block transmissions on the given link for the given reason.