wifi: Extend EMLSR main PHY switch back trace
This commit is contained in:
@@ -32,6 +32,7 @@ This file is a best-effort approach to solving this issue; we will do our best b
|
||||
* (lr-wpan) - Update correct use of extended addresses in ``lr-wpan\examples\lr-wpan-data.cc``.
|
||||
* (wifi) Callbacks connected to the `WifiMac::IcfDropReason` trace source are now passed a `struct IcfDropInfo` object that has three fields indicating the reason for dropping the ICF, the ID of the link on which the ICF was dropped and the MAC address of the sender of the ICF.
|
||||
* (wifi) Obsoleted the `Support40MHzOperation` and `Support160MHzOperation` attributes from the HT/VHT configurations. These capabilities are now directly derived from the `ChannelSettings` attribute.
|
||||
* (wifi) The `EmlsrSwitchMainPhyBackTrace` has been extended to provide the time elapsed since the switch main PHY back timer started, the reason why the main PHY switches back before the expiration of the switch main PHY back timer and whether the main PHY is switching while it is requested to switch back.
|
||||
|
||||
### Changes to build system
|
||||
|
||||
|
||||
@@ -1548,6 +1548,17 @@ EMLSR clients:
|
||||
false, the previous switch is interrupted and the main PHY starts switching to the previous
|
||||
link (in this case, the time elapsed since the CTS timeout occurred is zero). This holds true
|
||||
for both the case aux PHYs do not switch link and the case aux PHYs switch link.
|
||||
* ``EmlsrSwitchMainPhyBackTrace``: main PHY is switching back to the preferred link after that it
|
||||
did not manage to gain channel access on an aux PHY link before the expiration of the switch
|
||||
main PHY back timer, whose duration is set to the value of the
|
||||
``ns3::AdvancedEmlsrManager::SwitchMainPhyBackDelay`` attribute. The main PHY can switch back
|
||||
before the timer expiration in case it is determined that channel access is not expected to be
|
||||
gained within the timer expiration plus a channel switch delay. This trace has three parameters:
|
||||
the time elapsed since the switch main PHY back timer started, the reason for switching back
|
||||
before the timer expiration (if that is the case) and a boolean value indicating whether
|
||||
the main PHY is switching when it is requested to switch back. This trace is provided by the
|
||||
``AdvancedEmlsrManager`` and is only fired when aux PHYs are not TX capable and do not switch
|
||||
link.
|
||||
|
||||
Ack manager
|
||||
###########
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
@@ -302,14 +303,15 @@ AdvancedEmlsrManager::ReceivedMacHdr(Ptr<WifiPhy> phy,
|
||||
const auto mainPhyInvolved =
|
||||
(phy->GetPhyId() == GetMainPhyId()) ||
|
||||
(m_mainPhySwitchInfo.end >= Simulator::Now() && m_mainPhySwitchInfo.to == *linkId);
|
||||
const auto delay =
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) + phy->GetChannelSwitchDelay();
|
||||
|
||||
if (m_switchMainPhyBackEvent.IsPending() && mainPhyInvolved &&
|
||||
!GetExpectedAccessWithinDelay(*linkId,
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) +
|
||||
phy->GetChannelSwitchDelay()))
|
||||
if (WifiExpectedAccessReason reason;
|
||||
m_switchMainPhyBackEvent.IsPending() && mainPhyInvolved &&
|
||||
(reason = GetStaMac()->GetChannelAccessManager(*linkId)->GetExpectedAccessWithin(delay)) !=
|
||||
WifiExpectedAccessReason::ACCESS_EXPECTED)
|
||||
{
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
SwitchMainPhyBackDelayExpired(*linkId);
|
||||
SwitchMainPhyBackDelayExpired(*linkId, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,17 +454,19 @@ AdvancedEmlsrManager::CheckNavAndCcaLastPifs(Ptr<WifiPhy> phy, uint8_t linkId, P
|
||||
auto txopNotStarted = [=, this]() {
|
||||
// check when access may be granted to determine whether to switch the main PHY back
|
||||
// to the preferred link (if aux PHYs do not switch link)
|
||||
if (!m_switchAuxPhy &&
|
||||
!GetExpectedAccessWithinDelay(linkId,
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) +
|
||||
phy->GetChannelSwitchDelay()))
|
||||
const auto delay =
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) + phy->GetChannelSwitchDelay();
|
||||
|
||||
if (WifiExpectedAccessReason reason;
|
||||
!m_switchAuxPhy &&
|
||||
(reason = GetStaMac()->GetChannelAccessManager(linkId)->GetExpectedAccessWithin(
|
||||
delay)) != WifiExpectedAccessReason::ACCESS_EXPECTED)
|
||||
{
|
||||
NS_LOG_DEBUG("No AC is expected to get backoff soon, switch main PHY back");
|
||||
if (auto mainPhy = GetStaMac()->GetDevice()->GetPhy(GetMainPhyId());
|
||||
!mainPhy->IsStateSwitching())
|
||||
{
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
SwitchMainPhyBackDelayExpired(linkId);
|
||||
SwitchMainPhyBackDelayExpired(linkId, reason);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -501,10 +505,21 @@ AdvancedEmlsrManager::CheckNavAndCcaLastPifs(Ptr<WifiPhy> phy, uint8_t linkId, P
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired(uint8_t linkId)
|
||||
AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired(
|
||||
uint8_t linkId,
|
||||
std::optional<WifiExpectedAccessReason> stopReason)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
NS_ASSERT(!m_switchMainPhyBackEvent.IsPending());
|
||||
if (g_log.IsEnabled(ns3::LOG_FUNCTION))
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (stopReason.has_value())
|
||||
{
|
||||
ss << stopReason.value();
|
||||
}
|
||||
NS_LOG_FUNCTION(this << linkId << ss.str());
|
||||
}
|
||||
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
|
||||
if (m_switchAuxPhy)
|
||||
{
|
||||
@@ -541,7 +556,8 @@ AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired(uint8_t linkId)
|
||||
// this is the link on which the main PHY is operating. If an AC with traffic is
|
||||
// expected to get channel access soon (within a channel switch delay), restart
|
||||
// the timer to have the main PHY stay a bit longer on this link
|
||||
if (GetExpectedAccessWithinDelay(linkId, phy->GetChannelSwitchDelay()))
|
||||
if (GetStaMac()->GetChannelAccessManager(linkId)->GetExpectedAccessWithin(
|
||||
phy->GetChannelSwitchDelay()) == WifiExpectedAccessReason::ACCESS_EXPECTED)
|
||||
{
|
||||
extension = Max(extension, phy->GetChannelSwitchDelay());
|
||||
}
|
||||
@@ -555,12 +571,16 @@ AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired(uint8_t linkId)
|
||||
Simulator::Schedule(extension,
|
||||
&AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired,
|
||||
this,
|
||||
linkId);
|
||||
linkId,
|
||||
stopReason);
|
||||
return;
|
||||
}
|
||||
|
||||
// no need to wait further, switch the main PHY back to the preferred link
|
||||
SwitchMainPhyBackToPreferredLink(linkId, EmlsrSwitchMainPhyBackTrace(false));
|
||||
const auto elapsed = Simulator::Now() - m_mainPhySwitchInfo.start;
|
||||
const auto isSwitching = GetStaMac()->GetDevice()->GetPhy(GetMainPhyId())->IsStateSwitching();
|
||||
SwitchMainPhyBackToPreferredLink(linkId,
|
||||
EmlsrSwitchMainPhyBackTrace(elapsed, stopReason, isSwitching));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -585,10 +605,10 @@ AdvancedEmlsrManager::InterruptSwitchMainPhyBackTimerIfNeeded()
|
||||
|
||||
const auto delay =
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) + mainPhy->GetChannelSwitchDelay();
|
||||
if (!GetExpectedAccessWithinDelay(*linkId, delay))
|
||||
if (auto reason = GetStaMac()->GetChannelAccessManager(*linkId)->GetExpectedAccessWithin(delay);
|
||||
reason != WifiExpectedAccessReason::ACCESS_EXPECTED)
|
||||
{
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
SwitchMainPhyBackDelayExpired(*linkId);
|
||||
SwitchMainPhyBackDelayExpired(*linkId, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,7 +788,8 @@ AdvancedEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex
|
||||
Simulator::Schedule(mainPhy->GetChannelSwitchDelay() + m_switchMainPhyBackDelay,
|
||||
&AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired,
|
||||
this,
|
||||
linkId);
|
||||
linkId,
|
||||
std::nullopt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -944,15 +965,15 @@ AdvancedEmlsrManager::SwitchMainPhyIfTxopToBeGainedByAuxPhy(uint8_t linkId,
|
||||
linkId,
|
||||
edca);
|
||||
}
|
||||
|
||||
else if (!m_switchAuxPhy &&
|
||||
!GetExpectedAccessWithinDelay(linkId,
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) +
|
||||
mainPhy->GetChannelSwitchDelay()))
|
||||
else if (WifiExpectedAccessReason reason;
|
||||
!m_switchAuxPhy &&
|
||||
(reason = GetStaMac()->GetChannelAccessManager(linkId)->GetExpectedAccessWithin(
|
||||
Simulator::GetDelayLeft(m_switchMainPhyBackEvent) +
|
||||
mainPhy->GetChannelSwitchDelay())) !=
|
||||
WifiExpectedAccessReason::ACCESS_EXPECTED)
|
||||
{
|
||||
NS_LOG_DEBUG("No AC is expected to get backoff soon, switch main PHY back");
|
||||
m_switchMainPhyBackEvent.Cancel();
|
||||
SwitchMainPhyBackDelayExpired(linkId);
|
||||
SwitchMainPhyBackDelayExpired(linkId, reason);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -976,7 +997,8 @@ AdvancedEmlsrManager::SwitchMainPhyIfTxopToBeGainedByAuxPhy(uint8_t linkId,
|
||||
Simulator::Schedule(switchDelay + m_switchMainPhyBackDelay,
|
||||
&AdvancedEmlsrManager::SwitchMainPhyBackDelayExpired,
|
||||
this,
|
||||
linkId);
|
||||
linkId,
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "default-emlsr-manager.h"
|
||||
|
||||
#include "ns3/channel-access-manager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ns3
|
||||
@@ -105,14 +107,18 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
|
||||
void SwitchMainPhyIfTxopToBeGainedByAuxPhy(uint8_t linkId, AcIndex aci, const Time& delay);
|
||||
|
||||
/**
|
||||
* This method is called when the switch main PHY back delay timer (which is started when the
|
||||
* main PHY switches to the link of an aux PHY that does not switch and is not TX capable)
|
||||
* expires and decides whether to delay the request to switch the main PHY back to the preferred
|
||||
* link or to execute it immediately.
|
||||
* This method is called when the switch main PHY back timer (which is started when the main PHY
|
||||
* switches to the link of an aux PHY that does not switch and is not TX capable) expires and
|
||||
* decides whether to delay the request to switch the main PHY back to the preferred link or to
|
||||
* execute it immediately. This method can also be called to terminate a running switch main PHY
|
||||
* back timer, in case it is determined that channel access is not expected to be gained before
|
||||
* the expiration of the timer plus the channel switch delay.
|
||||
*
|
||||
* @param linkId the ID of the link that the main PHY is leaving
|
||||
* @param stopReason the reason for terminating the switch main PHY back timer before expiration
|
||||
*/
|
||||
void SwitchMainPhyBackDelayExpired(uint8_t linkId);
|
||||
void SwitchMainPhyBackDelayExpired(uint8_t linkId,
|
||||
std::optional<WifiExpectedAccessReason> stopReason);
|
||||
|
||||
private:
|
||||
void DoNotifyTxopEnd(uint8_t linkId) override;
|
||||
@@ -149,16 +155,26 @@ struct EmlsrSwitchMainPhyBackTrace : public EmlsrMainPhySwitchTraceImpl<EmlsrSwi
|
||||
{
|
||||
static constexpr std::string_view m_name = "TxopNotGainedOnAuxPhyLink"; //!< trace name
|
||||
|
||||
bool nothingToTx; //!< if true, the main PHY managed to gain a TXOP but had nothing to transmit
|
||||
Time elapsed; //!< the time elapsed since the switch main PHY back timer started
|
||||
std::optional<WifiExpectedAccessReason>
|
||||
earlySwitchReason; //!< the reason why the main PHY switches back before the expiration of
|
||||
//!< the switch main PHY back timer
|
||||
bool isSwitching; //!< whether the main PHY is switching while it is requested to switch back
|
||||
|
||||
/**
|
||||
* Constructor provided because this struct is not an aggregate (it has a base struct), hence
|
||||
* we cannot use designated initializers.
|
||||
*
|
||||
* @param nothing the value for the nothingToTx field
|
||||
* @param time the value for the elapsed field
|
||||
* @param reason the value for the earlySwitchReason field
|
||||
* @param switching the value for the isSwitching field
|
||||
*/
|
||||
EmlsrSwitchMainPhyBackTrace(bool nothing)
|
||||
: nothingToTx(nothing)
|
||||
EmlsrSwitchMainPhyBackTrace(Time time,
|
||||
std::optional<WifiExpectedAccessReason> reason,
|
||||
bool switching)
|
||||
: elapsed(time),
|
||||
earlySwitchReason(reason),
|
||||
isSwitching(switching)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -960,6 +960,7 @@ EmlsrManager::SwitchMainPhy(uint8_t linkId,
|
||||
|
||||
m_mainPhySwitchInfo.from = currMainPhyLinkId.value_or(m_mainPhySwitchInfo.from);
|
||||
m_mainPhySwitchInfo.to = linkId;
|
||||
m_mainPhySwitchInfo.start = Simulator::Now();
|
||||
m_mainPhySwitchInfo.end = Simulator::Now() + timeToSwitchEnd;
|
||||
|
||||
NotifyMainPhySwitch(currMainPhyLinkId, linkId, auxPhy, timeToSwitchEnd);
|
||||
@@ -1122,28 +1123,6 @@ EmlsrManager::MediumSyncDelayNTxopsExceeded(uint8_t linkId)
|
||||
return timerIt->second.msdNTxopsLeft == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
EmlsrManager::GetExpectedAccessWithinDelay(uint8_t linkId, const Time& delay) const
|
||||
{
|
||||
const auto deadline = Simulator::Now() + delay;
|
||||
for (const auto& [acIndex, ac] : wifiAcList)
|
||||
{
|
||||
if (auto edca = m_staMac->GetQosTxop(acIndex); edca->HasFramesToTransmit(linkId))
|
||||
{
|
||||
const auto backoffEnd =
|
||||
m_staMac->GetChannelAccessManager(linkId)->GetBackoffEndFor(edca);
|
||||
|
||||
if (backoffEnd <= deadline)
|
||||
{
|
||||
NS_LOG_DEBUG("Backoff end for " << acIndex << " on link " << +linkId << ": "
|
||||
<< backoffEnd.As(Time::US));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MgtEmlOmn
|
||||
EmlsrManager::GetEmlOmn()
|
||||
{
|
||||
|
||||
@@ -504,20 +504,10 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
void CancelAllSleepEvents();
|
||||
|
||||
/**
|
||||
* Get whether channel access is expected to be granted on the given link within the given
|
||||
* delay to an Access Category that has traffic to send on the given link.
|
||||
*
|
||||
* @param linkId the ID of the given link
|
||||
* @param delay the given delay
|
||||
* @return whether channel access is expected to be granted on the given link within the given
|
||||
* delay
|
||||
*/
|
||||
bool GetExpectedAccessWithinDelay(uint8_t linkId, const Time& delay) const;
|
||||
|
||||
/// Store information about a main PHY switch.
|
||||
struct MainPhySwitchInfo
|
||||
{
|
||||
Time start; //!< start of channel switching
|
||||
Time end; //!< end of channel switching
|
||||
uint8_t from{}; //!< ID of the link which the main PHY is/has been leaving
|
||||
uint8_t to{}; //!< ID of the link which the main PHY is moving to
|
||||
|
||||
Reference in New Issue
Block a user