wifi: Add a parameter to scheduler GetNext() to skip blocked container queues

This commit is contained in:
Stefano Avallone
2025-05-10 12:45:45 +02:00
parent eefc7bba31
commit 60725a119b
2 changed files with 50 additions and 31 deletions

View File

@@ -58,15 +58,18 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler
/** @copydoc ns3::WifiMacQueueScheduler::SetWifiMac */
void SetWifiMac(Ptr<WifiMac> mac) final;
/** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>) */
std::optional<WifiContainerQueueId> GetNext(AcIndex ac, std::optional<uint8_t> linkId) final;
/** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>,bool) */
std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
std::optional<uint8_t> linkId,
bool skipBlockedQueues = true) final;
/**
* @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>,
* const WifiContainerQueueId&)
* const WifiContainerQueueId&,bool)
*/
std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
std::optional<uint8_t> linkId,
const WifiContainerQueueId& prevQueueId) final;
const WifiContainerQueueId& prevQueueId,
bool skipBlockedQueues = true) final;
/** @copydoc ns3::WifiMacQueueScheduler::GetLinkIds */
std::list<uint8_t> GetLinkIds(AcIndex ac,
Ptr<const WifiMpdu> mpdu,
@@ -200,19 +203,23 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler
typename QueueInfoMap::iterator InitQueueInfo(AcIndex ac, Ptr<const WifiMpdu> 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 <i>skipBlockedQueues</i> 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<WifiContainerQueueId> DoGetNext(AcIndex ac,
std::optional<uint8_t> 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<Priority, Compare>::GetQueueLinkMask(AcIndex ac,
template <class Priority, class Compare>
std::optional<WifiContainerQueueId>
WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac, std::optional<uint8_t> linkId)
WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac,
std::optional<uint8_t> 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 <class Priority, class Compare>
std::optional<WifiContainerQueueId>
WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac,
std::optional<uint8_t> 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<Priority, Compare>::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 <class Priority, class Compare>
@@ -732,9 +742,10 @@ std::optional<WifiContainerQueueId>
WifiMacQueueSchedulerImpl<Priority, Compare>::DoGetNext(
AcIndex ac,
std::optional<uint8_t> 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<uint8_t>(ac) < AC_UNDEF);
while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
@@ -743,11 +754,13 @@ WifiMacQueueSchedulerImpl<Priority, Compare>::DoGetNext(
const auto& linkIds = queueInfoPair.second.linkIds;
typename std::decay_t<decltype(linkIds)>::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.

View File

@@ -91,32 +91,38 @@ class WifiMacQueueScheduler : public Object
virtual void SetWifiMac(Ptr<WifiMac> 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 <i>skipBlockedQueues</i> 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<WifiContainerQueueId> GetNext(AcIndex ac,
std::optional<uint8_t> linkId) = 0;
std::optional<uint8_t> 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
* <i>skipBlockedQueues</i> 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<WifiContainerQueueId> GetNext(
AcIndex ac,
std::optional<uint8_t> linkId,
const WifiContainerQueueId& prevQueueId) = 0;
virtual std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
std::optional<uint8_t> linkId,
const WifiContainerQueueId& prevQueueId,
bool skipBlockedQueues = true) = 0;
/**
* Get the list of the IDs of the links the given MPDU (belonging to the given