wifi: Interrupt switch main PHY back timer if medium gets busy for too long
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/wifi-net-device.h"
|
||||
#include "ns3/wifi-phy-listener.h"
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -24,6 +25,85 @@ NS_LOG_COMPONENT_DEFINE("AdvancedEmlsrManager");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(AdvancedEmlsrManager);
|
||||
|
||||
/**
|
||||
* PHY listener connected to the main PHY while operating on the link of an aux PHY that is
|
||||
* not TX capable.
|
||||
*
|
||||
* PHY notifications are forwarded to this EMLSR manager one timestep later because this EMLSR
|
||||
* manager may then decide to switch the main PHY back to the preferred link. Given that notifying
|
||||
* a PHY listener is only one of the actions that are performed when handling events such as RX end
|
||||
* or CCA busy start, it is not a good idea to request a main PHY switch while performing other
|
||||
* actions. Forwarding notifications a timestep later allows to first complete the handling of the
|
||||
* given event and then (possibly) starting a main PHY switch.
|
||||
*/
|
||||
class EmlsrPhyListener : public WifiPhyListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param emlsrManager the EMLSR manager
|
||||
*/
|
||||
EmlsrPhyListener(Ptr<AdvancedEmlsrManager> emlsrManager)
|
||||
: m_emlsrManager(emlsrManager)
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyRxStart(Time /* duration */) override
|
||||
{
|
||||
Simulator::Schedule(TimeStep(1),
|
||||
&AdvancedEmlsrManager::InterruptSwitchMainPhyBackTimerIfNeeded,
|
||||
m_emlsrManager);
|
||||
}
|
||||
|
||||
void NotifyRxEndOk() override
|
||||
{
|
||||
Simulator::Schedule(TimeStep(1),
|
||||
&AdvancedEmlsrManager::InterruptSwitchMainPhyBackTimerIfNeeded,
|
||||
m_emlsrManager);
|
||||
}
|
||||
|
||||
void NotifyRxEndError() override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyTxStart(Time /* duration */, dBm_u /* txPower */) override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyCcaBusyStart(Time /* duration */,
|
||||
WifiChannelListType /* channelType */,
|
||||
const std::vector<Time>& /* per20MhzDurations */) override
|
||||
{
|
||||
Simulator::Schedule(TimeStep(1),
|
||||
&AdvancedEmlsrManager::InterruptSwitchMainPhyBackTimerIfNeeded,
|
||||
m_emlsrManager);
|
||||
}
|
||||
|
||||
void NotifySwitchingStart(Time /* duration */) override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifySleep() override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyOff() override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyWakeup() override
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyOn() override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Ptr<AdvancedEmlsrManager> m_emlsrManager; //!< the EMLSR manager
|
||||
};
|
||||
|
||||
TypeId
|
||||
AdvancedEmlsrManager::GetTypeId()
|
||||
{
|
||||
@@ -74,6 +154,7 @@ AdvancedEmlsrManager::GetTypeId()
|
||||
AdvancedEmlsrManager::AdvancedEmlsrManager()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_phyListener = std::make_shared<EmlsrPhyListener>(this);
|
||||
}
|
||||
|
||||
AdvancedEmlsrManager::~AdvancedEmlsrManager()
|
||||
@@ -91,6 +172,11 @@ AdvancedEmlsrManager::DoDispose()
|
||||
"PhyRxMacHeaderEnd",
|
||||
MakeCallback(&AdvancedEmlsrManager::ReceivedMacHdr, this).Bind(phy));
|
||||
}
|
||||
if (!GetAuxPhyTxCapable())
|
||||
{
|
||||
GetStaMac()->GetDevice()->GetPhy(GetMainPhyId())->UnregisterListener(m_phyListener);
|
||||
}
|
||||
m_phyListener.reset();
|
||||
DefaultEmlsrManager::DoDispose();
|
||||
}
|
||||
|
||||
@@ -131,6 +217,10 @@ AdvancedEmlsrManager::DoSetWifiMac(Ptr<StaWifiMac> mac)
|
||||
"PhyRxMacHeaderEnd",
|
||||
MakeCallback(&AdvancedEmlsrManager::ReceivedMacHdr, this).Bind(phy));
|
||||
}
|
||||
if (!GetAuxPhyTxCapable())
|
||||
{
|
||||
mac->GetDevice()->GetPhy(GetMainPhyId())->RegisterListener(m_phyListener);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, Time>
|
||||
@@ -526,6 +616,35 @@ AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired(uint8_t linkId)
|
||||
SwitchMainPhyBackToPreferredLink(linkId, EmlsrSwitchMainPhyBackTrace(false));
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::InterruptSwitchMainPhyBackTimerIfNeeded()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (!m_switchMainPhyBackEvent.IsPending())
|
||||
{
|
||||
return; // nothing to do
|
||||
}
|
||||
|
||||
// a busy event occurred, check if the main PHY has to switch back to the preferred link
|
||||
auto mainPhy = GetStaMac()->GetDevice()->GetPhy(GetMainPhyId());
|
||||
auto linkId = GetStaMac()->GetLinkForPhy(GetMainPhyId());
|
||||
|
||||
if (!linkId.has_value())
|
||||
{
|
||||
NS_LOG_DEBUG("Main PHY is not operating on any link");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto delay =
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) + mainPhy->GetChannelSwitchDelay();
|
||||
if (!GetExpectedAccessWithinDelay(*linkId, delay))
|
||||
{
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
SwitchMainPhyBackDelayExpired(*linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::DoNotifyIcfReceived(uint8_t linkId)
|
||||
{
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
|
||||
#include "default-emlsr-manager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
class WifiPhyListener;
|
||||
|
||||
/**
|
||||
* @ingroup wifi
|
||||
*
|
||||
@@ -31,6 +35,14 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
|
||||
AdvancedEmlsrManager();
|
||||
~AdvancedEmlsrManager() override;
|
||||
|
||||
/**
|
||||
* This method is called by the PHY listener attached to the main PHY when a switch main PHY
|
||||
* back timer is started to notify of events that may delay the channel access for the main
|
||||
* PHY on the current link. If the expected channel access is beyond the end of the switch
|
||||
* main PHY timer expiration plus a channel switch delay, the timer is stopped immediately.
|
||||
*/
|
||||
void InterruptSwitchMainPhyBackTimerIfNeeded();
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void DoSetWifiMac(Ptr<StaWifiMac> mac) override;
|
||||
@@ -124,6 +136,9 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
|
||||
EventId m_switchMainPhyBackEvent; //!< event scheduled in case of non-TX capable aux PHY when
|
||||
//!< medium is sensed busy during the PIFS interval
|
||||
//!< preceding/following the main PHY switch end
|
||||
std::shared_ptr<WifiPhyListener>
|
||||
m_phyListener; //!< PHY listener connected to the main PHY while operating on the link of
|
||||
//!< an aux PHY that is not TX capable
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user