From b7e2cb8e07673f7ec533b8c554d35e830eb185a1 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 15 Apr 2024 17:16:36 +0200 Subject: [PATCH] wifi: Enable ChannelAccessManager to send alerts before backoff expiration --- src/wifi/model/channel-access-manager.cc | 50 +++++++++++++++++++----- src/wifi/model/channel-access-manager.h | 19 +++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/wifi/model/channel-access-manager.cc b/src/wifi/model/channel-access-manager.cc index bb2a026b3..b046878a8 100644 --- a/src/wifi/model/channel-access-manager.cc +++ b/src/wifi/model/channel-access-manager.cc @@ -185,7 +185,20 @@ ChannelAccessManager::GetTypeId() "and subsequently the medium becomes busy.", BooleanValue(false), MakeBooleanAccessor(&ChannelAccessManager::m_proactiveBackoff), - MakeBooleanChecker()); + MakeBooleanChecker()) + .AddAttribute("NSlotsLeft", + "Fire the NSlotsLeftAlert trace source when the backoff counter with " + "the minimum value among all ACs reaches this value or it is started " + "with a value less than this attribute. If this value is zero, the " + "trace source is never fired.", + UintegerValue(0), + MakeUintegerAccessor(&ChannelAccessManager::m_nSlotsLeft), + MakeUintegerChecker()) + .AddTraceSource("NSlotsLeftAlert", + "The backoff counter of the AC with the given index reached the " + "threshold set through the NSlotsLeft attribute.", + MakeTraceSourceAccessor(&ChannelAccessManager::m_nSlotsLeftCallback), + "ns3::ChannelAccessManager::NSlotsLeftCallback"); return tid; } @@ -754,26 +767,43 @@ ChannelAccessManager::DoRestartAccessTimeoutIfNeeded() * Is there a Txop which needs to access the medium, and, * if there is one, how many slots for AIFS+backoff does it require ? */ - bool accessTimeoutNeeded = false; + Ptr nextTxop; auto expectedBackoffEnd = Simulator::GetMaximumSimulationTime(); const auto accessGrantStart = GetAccessGrantStart(); + const auto now = Simulator::Now(); for (auto txop : m_txops) { if (txop->GetAccessStatus(m_linkId) == Txop::REQUESTED) { - Time tmp = GetBackoffEndFor(txop, accessGrantStart); - if (tmp > Simulator::Now()) + if (auto backoffEnd = GetBackoffEndFor(txop, accessGrantStart); + backoffEnd > now && backoffEnd < expectedBackoffEnd) { - accessTimeoutNeeded = true; - expectedBackoffEnd = std::min(expectedBackoffEnd, tmp); + expectedBackoffEnd = backoffEnd; + nextTxop = txop; } } } - NS_LOG_DEBUG("Access timeout needed: " << accessTimeoutNeeded); - if (accessTimeoutNeeded) + NS_LOG_DEBUG("Access timeout needed: " << (nextTxop != nullptr)); + if (nextTxop) { - NS_LOG_DEBUG("expected backoff end=" << expectedBackoffEnd); - Time expectedBackoffDelay = expectedBackoffEnd - Simulator::Now(); + const auto aci = nextTxop->GetWifiMacQueue()->GetAc(); + NS_LOG_DEBUG("expected backoff end=" << expectedBackoffEnd << " by " << aci); + auto expectedBackoffDelay = expectedBackoffEnd - now; + + if (m_nSlotsLeft > 0) + { + if (const auto slots = m_nSlotsLeft * GetSlot(); expectedBackoffDelay > slots) + { + // make the timer expire when the specified number of slots are left + expectedBackoffDelay -= slots; + } + else + { + // notify that a number of slots less than or equal to the specified value are left + m_nSlotsLeftCallback(m_linkId, aci, expectedBackoffDelay); + } + } + if (m_accessTimeout.IsPending() && Simulator::GetDelayLeft(m_accessTimeout) > expectedBackoffDelay) { diff --git a/src/wifi/model/channel-access-manager.h b/src/wifi/model/channel-access-manager.h index ef5bccd04..bfcd014c3 100644 --- a/src/wifi/model/channel-access-manager.h +++ b/src/wifi/model/channel-access-manager.h @@ -15,6 +15,7 @@ #include "ns3/event-id.h" #include "ns3/nstime.h" #include "ns3/object.h" +#include "ns3/traced-callback.h" #include #include @@ -32,6 +33,7 @@ class WifiPhy; class PhyListener; class Txop; class FrameExchangeManager; +enum AcIndex : uint8_t; // opaque enum declaration /** * \brief Manage a set of ns3::Txop @@ -501,6 +503,23 @@ class ChannelAccessManager : public Object Ptr m_phy; //!< pointer to the unique active PHY Ptr m_feManager; //!< pointer to the Frame Exchange Manager uint8_t m_linkId; //!< the ID of the link this object is associated with + uint8_t m_nSlotsLeft; //!< fire the NSlotsLeftAlert trace source when the + //!< backoff counter with the minimum value among all + //!< ACs reaches this value + + /** + * TracedCallback signature for NSlotsLeft alerts. + * + * \param linkId the ID of this link + * \param aci the index of the AC that triggered the NSlotsLeft alert + * \param backoffDelay delay until backoff counts down to zero + */ + typedef void (*NSlotsLeftCallback)(uint8_t linkId, AcIndex aci, const Time& backoffDelay); + + /// TracedCallback for NSlotsLeft alerts typedef + using NSlotsLeftTracedCallback = TracedCallback; + + NSlotsLeftTracedCallback m_nSlotsLeftCallback; //!< traced callback for NSlotsLeft alerts }; } // namespace ns3