From 41c64d18bec047ba575faad42ca830eb3cada576 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 4 Sep 2024 16:21:34 +0200 Subject: [PATCH] wifi: Add queue scheduler functions to (un)block all queues --- .../model/wifi-mac-queue-scheduler-impl.h | 129 +++++++++++++++++- src/wifi/model/wifi-mac-queue-scheduler.h | 30 ++++ 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/src/wifi/model/wifi-mac-queue-scheduler-impl.h b/src/wifi/model/wifi-mac-queue-scheduler-impl.h index 1a2c465f4..d9c3d5b93 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler-impl.h +++ b/src/wifi/model/wifi-mac-queue-scheduler-impl.h @@ -87,6 +87,12 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler const Mac48Address& txAddress, const std::set& tids, const std::set& linkIds) final; + /** @copydoc ns3::WifiMacQueueScheduler::BlockAllQueues */ + void BlockAllQueues(WifiQueueBlockedReason reason, const std::set& linkIds) final; + /** @copydoc ns3::WifiMacQueueScheduler::UnblockAllQueues */ + void UnblockAllQueues(WifiQueueBlockedReason reason, const std::set& linkIds) final; + /** @copydoc ns3::WifiMacQueueScheduler::GetAllQueuesBlockedOnLink */ + bool GetAllQueuesBlockedOnLink(uint8_t linkId, WifiQueueBlockedReason reason) final; /** @copydoc ns3::WifiMacQueueScheduler::GetQueueLinkMask */ std::optional GetQueueLinkMask(AcIndex ac, const WifiContainerQueueId& queueId, @@ -267,6 +273,24 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler const std::set& tids, const std::set& linkIds); + /** + * Block or unblock the given set of links for all the container queues for the given reason. + * + * @param block true to block the queues, false to unblock + * @param reason the reason for blocking the queues + * @param linkIds set of links to block (empty to block all setup links) + */ + void DoBlockAllQueues(bool block, + WifiQueueBlockedReason reason, + const std::set& linkIds); + + /** + * When it is requested to block all the queues, an entry is added to this map to store the + * reason and the IDs of the links to block. This information is used to block queues that + * will be created afterwards. + */ + std::map> m_blockAllInfo; + std::vector m_perAcInfo{AC_UNDEF}; //!< vector of per-AC information NS_LOG_TEMPLATE_DECLARE; //!< the log component }; @@ -366,7 +390,19 @@ WifiMacQueueSchedulerImpl::InitQueueInfo(AcIndex ac, PtrGetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(rxAddr)) { // the mask is not modified if linkId is already in the map - queueInfoIt->second.linkIds.emplace(linkId, Mask{}); + auto [it, inserted] = queueInfoIt->second.linkIds.try_emplace(linkId); + + if (inserted) + { + // linkId was not in the map, set the mask if all queues are blocked + for (const auto& [reason, linkIds] : m_blockAllInfo) + { + if (linkIds.contains(linkId)) + { + it->second.set(static_cast(reason), true); + } + } + } } else { @@ -390,7 +426,16 @@ WifiMacQueueSchedulerImpl::InitQueueInfo(AcIndex ac, Ptrfirst != *linkId) { - linkIdsMap = {{*linkId, Mask{}}}; + Mask mask; + for (const auto& [reason, linkIds] : m_blockAllInfo) + { + if (linkIds.contains(*linkId)) + { + mask.set(static_cast(reason), true); + } + } + + linkIdsMap = {{*linkId, mask}}; } } @@ -517,7 +562,7 @@ WifiMacQueueSchedulerImpl::DoBlockQueues( auto queueInfoIt = InitQueueInfo(ac, Create(Create(), hdr)); for (auto& [linkId, mask] : queueInfoIt->second.linkIds) { - if (linkIds.empty() || linkIds.count(linkId) > 0) + if (linkIds.empty() || linkIds.contains(linkId)) { mask.set(static_cast(reason), block); } @@ -553,6 +598,84 @@ WifiMacQueueSchedulerImpl::UnblockQueues( DoBlockQueues(false, reason, ac, types, rxAddress, txAddress, tids, linkIds); } +template +void +WifiMacQueueSchedulerImpl::DoBlockAllQueues(bool block, + WifiQueueBlockedReason reason, + const std::set& linkIds) +{ + for (auto& perAcInfo : m_perAcInfo) + { + for (auto& [queueId, queueInfo] : perAcInfo.queueInfoMap) + { + for (auto& [linkId, mask] : queueInfo.linkIds) + { + if (linkIds.empty() || linkIds.contains(linkId)) + { + mask.set(static_cast(reason), block); + } + } + } + } +} + +template +void +WifiMacQueueSchedulerImpl::BlockAllQueues(WifiQueueBlockedReason reason, + const std::set& linkIds) +{ + DoBlockAllQueues(true, reason, linkIds); + + if (linkIds.empty()) + { + m_blockAllInfo[reason] = GetMac()->GetLinkIds(); // all links blocked + } + else + { + m_blockAllInfo[reason].merge(std::set{linkIds}); + } +} + +template +void +WifiMacQueueSchedulerImpl::UnblockAllQueues(WifiQueueBlockedReason reason, + const std::set& linkIds) +{ + DoBlockAllQueues(false, reason, linkIds); + + auto infoIt = m_blockAllInfo.find(reason); + + if (infoIt == m_blockAllInfo.end()) + { + return; // all queues were not blocked for the given reason + } + std::erase_if(infoIt->second, + [&](uint8_t id) { return linkIds.empty() || linkIds.contains(id); }); + + if (infoIt->second.empty()) + { + // no more links blocked for the given reason + m_blockAllInfo.erase(infoIt); + } +} + +template +bool +WifiMacQueueSchedulerImpl::GetAllQueuesBlockedOnLink( + uint8_t linkId, + WifiQueueBlockedReason reason) +{ + for (const auto& [r, linkIds] : m_blockAllInfo) + { + if ((reason == WifiQueueBlockedReason::REASONS_COUNT || reason == r) && + linkIds.contains(linkId)) + { + return true; + } + } + return false; +} + template std::optional WifiMacQueueSchedulerImpl::GetQueueLinkMask(AcIndex ac, diff --git a/src/wifi/model/wifi-mac-queue-scheduler.h b/src/wifi/model/wifi-mac-queue-scheduler.h index f79780998..a631e8860 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler.h +++ b/src/wifi/model/wifi-mac-queue-scheduler.h @@ -175,6 +175,36 @@ class WifiMacQueueScheduler : public Object const std::set& tids = {}, const std::set& linkIds = {}) = 0; + /** + * Block the given set of links for all the container queues for the given reason. + * + * @param reason the reason for blocking the queues + * @param linkIds set of links to block (empty to block all setup links) + */ + virtual void BlockAllQueues(WifiQueueBlockedReason reason, + const std::set& linkIds = {}) = 0; + + /** + * Unblock the given set of links for all the container queues for the given reason. + * + * @param reason the reason for unblocking the queues + * @param linkIds set of links to unblock (empty to unblock all setup links) + */ + virtual void UnblockAllQueues(WifiQueueBlockedReason reason, + const std::set& linkIds = {}) = 0; + + /** + * Return whether all the container queues are blocked for the given link for the given + * reason, if different than REASONS_COUNT, or for any reason, otherwise. + * + * @param linkId the ID of the given link + * @param reason the reason to check (if different than REASONS_COUNT) + * @return whether all the container queues are blocked for the given link + */ + virtual bool GetAllQueuesBlockedOnLink( + uint8_t linkId, + WifiQueueBlockedReason reason = WifiQueueBlockedReason::REASONS_COUNT) = 0; + /// Bitset identifying the reasons to block individual links for a container queue using Mask = std::bitset(WifiQueueBlockedReason::REASONS_COUNT)>;