wifi: CAM detects if a PHY switched channel to operate on another EMLSR link

This commit is contained in:
Stefano Avallone
2023-04-03 17:08:26 +02:00
committed by Stefano Avallone
parent 1fd119e9ce
commit 4058d7b933
3 changed files with 75 additions and 5 deletions

View File

@@ -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<WifiPhy> 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<WifiPhy> phy)
}
}
void
ChannelAccessManager::NotifySwitchingEmlsrLink(Ptr<WifiPhy> 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<WifiPhy> 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<EhtFrameExchangeManager>(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

View File

@@ -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<Time>& per20MhzDurations);
/**
* \param phyListener the PHY listener that sent this notification
* \param duration expected duration of channel switching period
*
* Notify the Txop that a channel switching period has just started.
* During switching state, new packets can be enqueued in Txop/QosTxop
* but they won't access to the medium until the end of the channel switching.
*/
void NotifySwitchingStartNow(Time duration);
void NotifySwitchingStartNow(PhyListener* phyListener, Time duration);
/**
* Notify the Txop that the device has been put in sleep mode.
*/
@@ -276,6 +278,19 @@ class ChannelAccessManager : public Object
*/
void ResetState();
/**
* Notify that the given PHY is about to switch to the given operating channel, which is
* used by the given link. This notification is sent by the EMLSR Manager when a PHY object
* switches operating channel to operate on another link.
*
* \param phy the PHY object that is going to switch channel
* \param channel the new operating channel of the given PHY
* \param linkId the ID of the link on which the given PHY is going to operate
*/
void NotifySwitchingEmlsrLink(Ptr<WifiPhy> phy,
const WifiPhyOperatingChannel& channel,
uint8_t linkId);
protected:
void DoInitialize() override;
void DoDispose() override;
@@ -390,6 +405,16 @@ class ChannelAccessManager : public Object
Time m_eifsNoDifs; //!< EIFS no DIFS time
EventId m_accessTimeout; //!< the access timeout ID
/// Information associated with each PHY that is going to operate on another EMLSR link
struct EmlsrLinkSwitchInfo
{
WifiPhyOperatingChannel channel; //!< new operating channel
uint8_t linkId; //!< ID of the EMLSR link on which the PHY is going to operate
};
/// Store information about the PHY objects that are going to operate on another EMLSR link
std::unordered_map<Ptr<WifiPhy>, EmlsrLinkSwitchInfo> m_switchingEmlsrLinks;
/// Maps each PHY listener to the associated PHY
using PhyListenerMap = std::unordered_map<Ptr<WifiPhy>, std::unique_ptr<PhyListener>>;

View File

@@ -836,6 +836,7 @@ ChannelAccessManagerTest<TxopType>::AddSwitchingEvt(uint64_t at, uint64_t durati
Simulator::Schedule(MicroSeconds(at) - Now(),
&ChannelAccessManager::NotifySwitchingStartNow,
m_ChannelAccessManager,
nullptr,
MicroSeconds(duration));
}