diff --git a/src/wifi/model/channel-access-manager.cc b/src/wifi/model/channel-access-manager.cc index e04b96a71..1959a9aaa 100644 --- a/src/wifi/model/channel-access-manager.cc +++ b/src/wifi/model/channel-access-manager.cc @@ -19,11 +19,11 @@ #include "channel-access-manager.h" -#include "frame-exchange-manager.h" #include "txop.h" #include "wifi-phy-listener.h" #include "wifi-phy.h" +#include "ns3/eht-frame-exchange-manager.h" #include "ns3/log.h" #include "ns3/simulator.h" @@ -122,7 +122,7 @@ class PhyListener : public ns3::WifiPhyListener void NotifySwitchingStart(Time duration) override { - m_cam->NotifySwitchingStartNow(duration); + m_cam->NotifySwitchingStartNow(this, duration); } void NotifySleep() override @@ -245,6 +245,12 @@ ChannelAccessManager::SetupPhyListener(Ptr phy) } m_phy = phy; // this is the new active PHY InitLastBusyStructs(); + if (phy->IsStateSwitching()) + { + auto duration = phy->GetDelayUntilIdle(); + NS_LOG_DEBUG("switching start for " << duration); + m_lastSwitchingEnd = Simulator::Now() + duration; + } } void @@ -277,6 +283,17 @@ ChannelAccessManager::DeactivatePhyListener(Ptr phy) } } +void +ChannelAccessManager::NotifySwitchingEmlsrLink(Ptr phy, + const WifiPhyOperatingChannel& channel, + uint8_t linkId) +{ + NS_LOG_FUNCTION(this << phy << channel << linkId); + NS_ASSERT_MSG(m_switchingEmlsrLinks.count(phy) == 0, + "The given PHY is already expected to switch channel"); + m_switchingEmlsrLinks.emplace(phy, EmlsrLinkSwitchInfo{channel, linkId}); +} + void ChannelAccessManager::SetLinkId(uint8_t linkId) { @@ -845,13 +862,40 @@ ChannelAccessManager::NotifyCcaBusyStartNow(Time duration, } void -ChannelAccessManager::NotifySwitchingStartNow(Time duration) +ChannelAccessManager::NotifySwitchingStartNow(PhyListener* phyListener, Time duration) { - NS_LOG_FUNCTION(this << duration); + NS_LOG_FUNCTION(this << phyListener << duration); + Time now = Simulator::Now(); NS_ASSERT(m_lastTxEnd <= now); NS_ASSERT(m_lastSwitchingEnd <= now); + if (phyListener) // to make tests happy + { + // check if the PHY switched channel to operate on another EMLSR link + decltype(m_switchingEmlsrLinks)::const_iterator emlsrInfoIt; + + for (const auto& [phyRef, listener] : m_phyListeners) + { + Ptr phy = phyRef; + if (listener.get() == phyListener && + (emlsrInfoIt = m_switchingEmlsrLinks.find(phy)) != m_switchingEmlsrLinks.cend() && + phy->GetOperatingChannel() == emlsrInfoIt->second.channel) + { + // the PHY associated with the given PHY listener switched channel to + // operate on another EMLSR link as expected. We don't need this listener + // anymore. The MAC will connect a new listener to the ChannelAccessManager + // instance associated with the link the PHY is now operating on + RemovePhyListener(phy); + auto ehtFem = DynamicCast(m_feManager); + NS_ASSERT(ehtFem); + ehtFem->NotifySwitchingEmlsrLink(phy, emlsrInfoIt->second.linkId, duration); + m_switchingEmlsrLinks.erase(emlsrInfoIt); + return; + } + } + } + ResetState(); // Notify the FEM, which will in turn notify the MAC diff --git a/src/wifi/model/channel-access-manager.h b/src/wifi/model/channel-access-manager.h index eef243ef2..14dddc121 100644 --- a/src/wifi/model/channel-access-manager.h +++ b/src/wifi/model/channel-access-manager.h @@ -21,6 +21,7 @@ #define CHANNEL_ACCESS_MANAGER_H #include "wifi-phy-common.h" +#include "wifi-phy-operating-channel.h" #include "ns3/event-id.h" #include "ns3/nstime.h" @@ -206,13 +207,14 @@ class ChannelAccessManager : public Object WifiChannelListType channelType, const std::vector