wifi: EMLSR Manager handles MediumSyncDelay timers
This commit is contained in:
committed by
Stefano Avallone
parent
2a2287737c
commit
cf3c8182f2
@@ -23,6 +23,7 @@
|
||||
#include "ns3/channel-access-manager.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/wifi-mpdu.h"
|
||||
#include "ns3/wifi-net-device.h"
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
namespace ns3
|
||||
@@ -133,6 +134,7 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
|
||||
SwitchMainPhy(*m_linkIdForMainPhyAfterTxop, false);
|
||||
// Reconnect the aux PHY to its original link
|
||||
Simulator::ScheduleNow(&StaWifiMac::NotifySwitchingEmlsrLink, GetStaMac(), phy, linkId);
|
||||
SetCcaEdThresholdOnLinkSwitch(phy, linkId);
|
||||
}
|
||||
m_linkIdForMainPhyAfterTxop.reset();
|
||||
}
|
||||
|
||||
@@ -137,6 +137,10 @@ EmlsrManager::DoDispose()
|
||||
MakeCallback(&EmlsrManager::TxDropped, this));
|
||||
m_staMac = nullptr;
|
||||
m_transitionTimeoutEvent.Cancel();
|
||||
for (auto& [id, status] : m_mediumSyncDelayStatus)
|
||||
{
|
||||
status.timer.Cancel();
|
||||
}
|
||||
Object::DoDispose();
|
||||
}
|
||||
|
||||
@@ -201,6 +205,17 @@ EmlsrManager::GetEhtFem(uint8_t linkId) const
|
||||
return StaticCast<EhtFrameExchangeManager>(m_staMac->GetFrameExchangeManager(linkId));
|
||||
}
|
||||
|
||||
std::optional<Time>
|
||||
EmlsrManager::GetElapsedMediumSyncDelayTimer(uint8_t linkId) const
|
||||
{
|
||||
if (const auto statusIt = m_mediumSyncDelayStatus.find(linkId);
|
||||
statusIt != m_mediumSyncDelayStatus.cend() && statusIt->second.timer.IsRunning())
|
||||
{
|
||||
return m_mediumSyncDuration - Simulator::GetDelayLeft(statusIt->second.timer);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::SetTransitionTimeout(Time timeout)
|
||||
{
|
||||
@@ -408,9 +423,40 @@ EmlsrManager::NotifyTxopEnd(uint8_t linkId)
|
||||
}
|
||||
}
|
||||
|
||||
StartMediumSyncDelayTimer(linkId);
|
||||
|
||||
DoNotifyTxopEnd(linkId);
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::SetCcaEdThresholdOnLinkSwitch(Ptr<WifiPhy> phy, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << phy << linkId);
|
||||
|
||||
// if a MediumSyncDelay timer is running for the link on which the main PHY is going to
|
||||
// operate, set the CCA ED threshold to the MediumSyncDelay OFDM ED threshold
|
||||
if (auto statusIt = m_mediumSyncDelayStatus.find(linkId);
|
||||
statusIt != m_mediumSyncDelayStatus.cend() && statusIt->second.timer.IsRunning())
|
||||
{
|
||||
NS_LOG_DEBUG("Setting CCA ED threshold of PHY " << phy << " to " << +m_msdOfdmEdThreshold
|
||||
<< " on link " << +linkId);
|
||||
|
||||
// store the current CCA ED threshold in the m_prevCcaEdThreshold map, if not present
|
||||
m_prevCcaEdThreshold.try_emplace(phy, phy->GetCcaEdThreshold());
|
||||
|
||||
phy->SetCcaEdThreshold(m_msdOfdmEdThreshold);
|
||||
}
|
||||
// otherwise, restore the previous value for the CCA ED threshold (if any)
|
||||
else if (auto threshIt = m_prevCcaEdThreshold.find(phy);
|
||||
threshIt != m_prevCcaEdThreshold.cend())
|
||||
{
|
||||
NS_LOG_DEBUG("Resetting CCA ED threshold of PHY " << phy << " to " << threshIt->second
|
||||
<< " on link " << +linkId);
|
||||
phy->SetCcaEdThreshold(threshIt->second);
|
||||
m_prevCcaEdThreshold.erase(threshIt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::SwitchMainPhy(uint8_t linkId, bool noSwitchDelay)
|
||||
{
|
||||
@@ -462,6 +508,7 @@ EmlsrManager::SwitchMainPhy(uint8_t linkId, bool noSwitchDelay)
|
||||
}
|
||||
});
|
||||
|
||||
SetCcaEdThresholdOnLinkSwitch(mainPhy, linkId);
|
||||
NotifyMainPhySwitch(*currMainPhyLinkId, linkId);
|
||||
}
|
||||
|
||||
@@ -489,6 +536,89 @@ EmlsrManager::SwitchAuxPhy(uint8_t currLinkId, uint8_t nextLinkId)
|
||||
auxPhy->SetSlot(MicroSeconds(9));
|
||||
}
|
||||
});
|
||||
|
||||
SetCcaEdThresholdOnLinkSwitch(auxPhy, nextLinkId);
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::StartMediumSyncDelayTimer(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
// iterate over all the other EMLSR links
|
||||
for (auto id : m_staMac->GetLinkIds())
|
||||
{
|
||||
if (id != linkId && m_staMac->IsEmlsrLink(id))
|
||||
{
|
||||
const auto [it, inserted] = m_mediumSyncDelayStatus.try_emplace(id);
|
||||
|
||||
// reset the max number of TXOP attempts
|
||||
it->second.msdNTxopsLeft = m_msdMaxNTxops;
|
||||
|
||||
if (!it->second.timer.IsRunning())
|
||||
{
|
||||
// set the MSD OFDM ED threshold
|
||||
auto phy = m_staMac->GetWifiPhy(id);
|
||||
NS_ASSERT_MSG(phy,
|
||||
"Expected a PHY to be operating on link "
|
||||
<< +id << " after terminating a TXOP");
|
||||
NS_LOG_DEBUG("Setting CCA ED threshold on link "
|
||||
<< +id << " to " << +m_msdOfdmEdThreshold << " PHY " << phy);
|
||||
m_prevCcaEdThreshold[phy] = phy->GetCcaEdThreshold();
|
||||
phy->SetCcaEdThreshold(m_msdOfdmEdThreshold);
|
||||
}
|
||||
|
||||
// (re)start the timer
|
||||
it->second.timer.Cancel();
|
||||
it->second.timer = Simulator::Schedule(m_mediumSyncDuration,
|
||||
&EmlsrManager::MediumSyncDelayTimerExpired,
|
||||
this,
|
||||
id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::CancelMediumSyncDelayTimer(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
auto timerIt = m_mediumSyncDelayStatus.find(linkId);
|
||||
|
||||
NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && timerIt->second.timer.IsRunning());
|
||||
|
||||
timerIt->second.timer.Cancel();
|
||||
MediumSyncDelayTimerExpired(linkId);
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::MediumSyncDelayTimerExpired(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
auto timerIt = m_mediumSyncDelayStatus.find(linkId);
|
||||
|
||||
NS_ASSERT(timerIt != m_mediumSyncDelayStatus.cend() && !timerIt->second.timer.IsRunning());
|
||||
|
||||
// reset the MSD OFDM ED threshold
|
||||
auto phy = m_staMac->GetWifiPhy(linkId);
|
||||
|
||||
if (!phy)
|
||||
{
|
||||
// no PHY is operating on this link. This may happen when a MediumSyncDelay timer expires
|
||||
// on the link left "uncovered" by the main PHY that is operating on another link (and the
|
||||
// aux PHY of that link did not switch). In this case, do nothing, since the CCA ED
|
||||
// threshold on the main PHY will be restored once the main PHY switches back to its link
|
||||
return;
|
||||
}
|
||||
|
||||
auto threshIt = m_prevCcaEdThreshold.find(phy);
|
||||
NS_ASSERT_MSG(threshIt != m_prevCcaEdThreshold.cend(),
|
||||
"No value to restore for CCA ED threshold on PHY " << phy);
|
||||
NS_LOG_DEBUG("Resetting CCA ED threshold of PHY " << phy << " to " << threshIt->second
|
||||
<< " on link " << +linkId);
|
||||
phy->SetCcaEdThreshold(threshIt->second);
|
||||
m_prevCcaEdThreshold.erase(threshIt);
|
||||
}
|
||||
|
||||
MgtEmlOmn
|
||||
|
||||
@@ -176,6 +176,25 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
void NotifyTxopEnd(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Check whether the MediumSyncDelay timer is running for the STA operating on the given link.
|
||||
* If so, returns the time elapsed since the timer started.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return the time elapsed since the MediumSyncDelay timer started, if this timer is running
|
||||
* for the STA operating on the given link
|
||||
*/
|
||||
std::optional<Time> GetElapsedMediumSyncDelayTimer(uint8_t linkId) const;
|
||||
|
||||
/**
|
||||
* Cancel the MediumSyncDelay timer associated with the given link and take the appropriate
|
||||
* actions. This function must not be called when the MediumSyncDelay timer is not running
|
||||
* on the given link.
|
||||
*
|
||||
* \param linkId the ID of the link associated with the MediumSyncDelay timer to cancel
|
||||
*/
|
||||
void CancelMediumSyncDelayTimer(uint8_t linkId);
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
|
||||
@@ -235,6 +254,15 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
void SwitchAuxPhy(uint8_t currLinkId, uint8_t nextLinkId);
|
||||
|
||||
/**
|
||||
* Set the CCA ED threshold (if needed) on the given PHY that is switching channel to
|
||||
* operate on the given link.
|
||||
*
|
||||
* \param phy the given PHY
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetCcaEdThresholdOnLinkSwitch(Ptr<WifiPhy> phy, uint8_t linkId);
|
||||
|
||||
/**
|
||||
* \return the EML Operating Mode Notification to send
|
||||
*/
|
||||
@@ -268,6 +296,22 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
void SendEmlOmn();
|
||||
|
||||
/**
|
||||
* Start the MediumSyncDelay timer and take the appropriate actions, if the timer is not
|
||||
* already running.
|
||||
*
|
||||
* \param linkId the ID of the link on which a TXOP was carried out that caused the STAs
|
||||
* operating on other links to lose medium synchronization
|
||||
*/
|
||||
void StartMediumSyncDelayTimer(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Take the appropriate actions when the MediumSyncDelay timer expires or is cancelled.
|
||||
*
|
||||
* \param linkId the ID of the link associated with the MediumSyncDelay timer to cancel
|
||||
*/
|
||||
void MediumSyncDelayTimerExpired(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Notify the subclass of the reception of a management frame addressed to us.
|
||||
*
|
||||
@@ -337,6 +381,16 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
virtual void NotifyMainPhySwitch(uint8_t currLinkId, uint8_t nextLinkId) = 0;
|
||||
|
||||
/**
|
||||
* Information about the status of the MediumSyncDelay timer associated with a link.
|
||||
*/
|
||||
struct MediumSyncDelayStatus
|
||||
{
|
||||
EventId timer; //!< the MediumSyncDelay timer
|
||||
std::optional<uint8_t> msdNTxopsLeft; //!< number of TXOP attempts left while the
|
||||
//!< MediumSyncDelay timer is running
|
||||
};
|
||||
|
||||
Ptr<StaWifiMac> m_staMac; //!< the MAC of the managed non-AP MLD
|
||||
std::optional<Time> m_emlsrTransitionTimeout; /**< Transition timeout advertised by APs with
|
||||
EMLSR activated */
|
||||
@@ -344,6 +398,13 @@ class EmlsrManager : public Object
|
||||
int8_t m_msdOfdmEdThreshold; //!< MediumSyncDelay OFDM ED threshold
|
||||
std::optional<uint8_t> m_msdMaxNTxops; //!< MediumSyncDelay max number of TXOPs
|
||||
|
||||
std::map<uint8_t, MediumSyncDelayStatus>
|
||||
m_mediumSyncDelayStatus; //!< the status of MediumSyncDelay timers (link ID-indexed)
|
||||
std::map<Ptr<WifiPhy>, double> m_prevCcaEdThreshold; //!< the CCA sensitivity threshold (dBm)
|
||||
//!< to restore once the MediumSyncDelay
|
||||
//!< timer expires or the PHY moves to a
|
||||
//!< link on which the timer is not running
|
||||
|
||||
std::set<uint8_t> m_emlsrLinks; //!< ID of the EMLSR links (empty if EMLSR mode is disabled)
|
||||
std::optional<std::set<uint8_t>> m_nextEmlsrLinks; /**< ID of the links that will become the
|
||||
EMLSR links when the pending
|
||||
|
||||
Reference in New Issue
Block a user