From 60725a119bd2be64a172ccf1b282c0c47e0c982c Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Sat, 10 May 2025 12:45:45 +0200 Subject: [PATCH] wifi: Add a parameter to scheduler GetNext() to skip blocked container queues --- .../model/wifi-mac-queue-scheduler-impl.h | 53 ++++++++++++------- src/wifi/model/wifi-mac-queue-scheduler.h | 28 ++++++---- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/wifi/model/wifi-mac-queue-scheduler-impl.h b/src/wifi/model/wifi-mac-queue-scheduler-impl.h index 5d3fb1fd1..6309aff4d 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler-impl.h +++ b/src/wifi/model/wifi-mac-queue-scheduler-impl.h @@ -58,15 +58,18 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler /** @copydoc ns3::WifiMacQueueScheduler::SetWifiMac */ void SetWifiMac(Ptr mac) final; - /** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional) */ - std::optional GetNext(AcIndex ac, std::optional linkId) final; + /** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional,bool) */ + std::optional GetNext(AcIndex ac, + std::optional linkId, + bool skipBlockedQueues = true) final; /** * @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional, - * const WifiContainerQueueId&) + * const WifiContainerQueueId&,bool) */ std::optional GetNext(AcIndex ac, std::optional linkId, - const WifiContainerQueueId& prevQueueId) final; + const WifiContainerQueueId& prevQueueId, + bool skipBlockedQueues = true) final; /** @copydoc ns3::WifiMacQueueScheduler::GetLinkIds */ std::list GetLinkIds(AcIndex ac, Ptr mpdu, @@ -200,19 +203,23 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler typename QueueInfoMap::iterator InitQueueInfo(AcIndex ac, Ptr mpdu); /** - * Get the next queue to serve. The search starts from the given one. The returned - * queue is guaranteed to contain at least an MPDU whose lifetime has not expired. - * Queues containing MPDUs that cannot be sent over the given link are ignored. + * Get the next queue to serve. The search starts from the given one. The returned queue is + * guaranteed to contain at least an MPDU whose lifetime has not expired. Queues containing + * MPDUs that cannot be sent over the given link, if any, or on any link, otherwise, are ignored + * if and only if skipBlockedQueues is true. * * @param ac the Access Category that we want to serve * @param linkId the ID of the link on which MPDUs contained in the returned queue must be * allowed to be sent * @param sortedQueuesIt iterator pointing to the queue we start the search from + * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given + * link, if any, or on any link, otherwise, must be ignored * @return the ID of the selected container queue (if any) */ std::optional DoGetNext(AcIndex ac, std::optional linkId, - typename SortedQueues::iterator sortedQueuesIt); + typename SortedQueues::iterator sortedQueuesIt, + bool skipBlockedQueues); /** * Check whether an MPDU has to be dropped before enqueuing the given MPDU. @@ -703,19 +710,22 @@ WifiMacQueueSchedulerImpl::GetQueueLinkMask(AcIndex ac, template std::optional -WifiMacQueueSchedulerImpl::GetNext(AcIndex ac, std::optional linkId) +WifiMacQueueSchedulerImpl::GetNext(AcIndex ac, + std::optional linkId, + bool skipBlockedQueues) { - NS_LOG_FUNCTION(this << +ac << linkId.has_value()); - return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin()); + NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues); + return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin(), skipBlockedQueues); } template std::optional WifiMacQueueSchedulerImpl::GetNext(AcIndex ac, std::optional linkId, - const WifiContainerQueueId& prevQueueId) + const WifiContainerQueueId& prevQueueId, + bool skipBlockedQueues) { - NS_LOG_FUNCTION(this << +ac << linkId.has_value()); + NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues); auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(prevQueueId); NS_ABORT_IF(queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() || @@ -724,7 +734,7 @@ WifiMacQueueSchedulerImpl::GetNext(AcIndex ac, auto sortedQueuesIt = queueInfoIt->second.priorityIt.value(); NS_ABORT_IF(sortedQueuesIt == m_perAcInfo[ac].sortedQueues.end()); - return DoGetNext(ac, linkId, ++sortedQueuesIt); + return DoGetNext(ac, linkId, ++sortedQueuesIt, skipBlockedQueues); } template @@ -732,9 +742,10 @@ std::optional WifiMacQueueSchedulerImpl::DoGetNext( AcIndex ac, std::optional linkId, - typename SortedQueues::iterator sortedQueuesIt) + typename SortedQueues::iterator sortedQueuesIt, + bool skipBlockedQueues) { - NS_LOG_FUNCTION(this << +ac << linkId.has_value()); + NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues); NS_ASSERT(static_cast(ac) < AC_UNDEF); while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end()) @@ -743,11 +754,13 @@ WifiMacQueueSchedulerImpl::DoGetNext( const auto& linkIds = queueInfoPair.second.linkIds; typename std::decay_t::const_iterator linkIt; - if (!linkId.has_value() || - ((linkIt = linkIds.find(*linkId)) != linkIds.cend() && linkIt->second.none())) + if (!skipBlockedQueues || + std::any_of(linkIds.cbegin(), linkIds.cend(), [&linkId](const auto& linkIdMask) { + return (!linkId.has_value() || linkId == linkIdMask.first) && + linkIdMask.second.none(); + })) { - // Packets in this queue can be sent over the link we got channel access on. - // Now remove packets with expired lifetime from this queue. + // Remove packets with expired lifetime from this queue. // In case the queue becomes empty, the queue is removed from the sorted // list and sortedQueuesIt is invalidated; thus, store an iterator to the // previous queue in the sorted list (if any) to resume the search afterwards. diff --git a/src/wifi/model/wifi-mac-queue-scheduler.h b/src/wifi/model/wifi-mac-queue-scheduler.h index a631e8860..85c5e8b15 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler.h +++ b/src/wifi/model/wifi-mac-queue-scheduler.h @@ -91,32 +91,38 @@ class WifiMacQueueScheduler : public Object virtual void SetWifiMac(Ptr mac); /** - * Get the next queue to serve, which is guaranteed to contain at least an MPDU - * whose lifetime has not expired. Queues containing MPDUs that cannot be sent - * over the given link (if any) are ignored. + * Get the next queue to serve, which is guaranteed to contain at least an MPDU whose lifetime + * has not expired. Queues containing MPDUs that cannot be sent over the given link, if any, or + * on any link, otherwise, are ignored if and only if skipBlockedQueues is true. * * @param ac the Access Category that we want to serve * @param linkId the ID of the link on which MPDUs contained in the returned queue must be * allowed to be sent + * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given + * link, if any, or on any link, otherwise, must be ignored * @return the ID of the selected container queue (if any) */ virtual std::optional GetNext(AcIndex ac, - std::optional linkId) = 0; + std::optional linkId, + bool skipBlockedQueues = true) = 0; /** - * Get the next queue to serve after the given one. The returned queue is - * guaranteed to contain at least an MPDU whose lifetime has not expired. - * Queues containing MPDUs that cannot be sent over the given link (if any) are ignored. + * Get the next queue to serve after the given one. The returned queue is guaranteed to contain + * at least an MPDU whose lifetime has not expired. Queues containing MPDUs that cannot be sent + * over the given link, if any, or on any link, otherwise, are ignored if and only if + * skipBlockedQueues is true. * * @param ac the Access Category that we want to serve * @param linkId the ID of the link on which MPDUs contained in the returned queue must be * allowed to be sent * @param prevQueueId the ID of the container queue served previously + * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given + * link, if any, or on any link, otherwise, must be ignored * @return the ID of the selected container queue (if any) */ - virtual std::optional GetNext( - AcIndex ac, - std::optional linkId, - const WifiContainerQueueId& prevQueueId) = 0; + virtual std::optional GetNext(AcIndex ac, + std::optional linkId, + const WifiContainerQueueId& prevQueueId, + bool skipBlockedQueues = true) = 0; /** * Get the list of the IDs of the links the given MPDU (belonging to the given