diff --git a/src/wifi/model/wifi-mac-queue-scheduler-impl.h b/src/wifi/model/wifi-mac-queue-scheduler-impl.h index 796bbc4ac..f30f81e26 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler-impl.h +++ b/src/wifi/model/wifi-mac-queue-scheduler-impl.h @@ -74,6 +74,26 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler const WifiContainerQueueId& prevQueueId) final; /** \copydoc ns3::WifiMacQueueScheduler::GetLinkIds */ std::list GetLinkIds(AcIndex ac, Ptr mpdu) final; + /** \copydoc ns3::WifiMacQueueScheduler::BlockQueues */ + void BlockQueues(WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds) final; + /** \copydoc ns3::WifiMacQueueScheduler::UnblockQueues */ + void UnblockQueues(WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds) final; + /** \copydoc ns3::WifiMacQueueScheduler::GetQueueLinkMask */ + std::optional GetQueueLinkMask(AcIndex ac, + const WifiContainerQueueId& queueId, + uint8_t linkId) final; /** \copydoc ns3::WifiMacQueueScheduler::HasToDropBeforeEnqueue */ Ptr HasToDropBeforeEnqueue(AcIndex ac, Ptr mpdu) final; /** \copydoc ns3::WifiMacQueueScheduler::NotifyEnqueue */ @@ -226,6 +246,29 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler */ virtual void DoNotifyRemove(AcIndex ac, const std::list>& mpdus) = 0; + /** + * Block or unblock the given set of links for the container queues of the given types and + * Access Category that hold frames having the given Receiver Address (RA), + * Transmitter Address (TA) and TID (if needed) for the given reason. + * + * \param block true to block the queues, false to unblock + * \param reason the reason for blocking the queues + * \param ac the given Access Category + * \param types the types of the queues to block + * \param rxAddress the Receiver Address (RA) of the frames + * \param txAddress the Transmitter Address (TA) of the frames + * \param tids the TIDs optionally identifying the queues to block + * \param linkIds set of links to block (empty to block all setup links) + */ + void DoBlockQueues(bool block, + WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds); + std::vector m_perAcInfo{AC_UNDEF}; //!< vector of per-AC information NS_LOG_TEMPLATE_DECLARE; //!< the log component }; @@ -399,6 +442,114 @@ WifiMacQueueSchedulerImpl::GetLinkIds(AcIndex ac, Ptr +void +WifiMacQueueSchedulerImpl::DoBlockQueues( + bool block, + WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds) +{ + NS_LOG_FUNCTION(this << block << reason << ac << rxAddress << txAddress); + std::list headers; + + for (const auto queueType : types) + { + switch (queueType) + { + case WIFI_CTL_QUEUE: + headers.emplace_back(WIFI_MAC_CTL_BACKREQ); + break; + case WIFI_MGT_QUEUE: + headers.emplace_back(WIFI_MAC_MGT_ACTION); + break; + case WIFI_QOSDATA_QUEUE: + NS_ASSERT_MSG(!tids.empty(), + "TID must be specified for queues containing QoS data frames"); + for (const auto tid : tids) + { + headers.emplace_back(WIFI_MAC_QOSDATA); + headers.back().SetQosTid(tid); + } + break; + case WIFI_DATA_QUEUE: + headers.emplace_back(WIFI_MAC_DATA); + break; + } + } + for (auto& hdr : headers) + { + hdr.SetAddr1(rxAddress); + hdr.SetAddr2(txAddress); + + auto queueInfoIt = InitQueueInfo(ac, Create(Create(), hdr)); + for (auto& [linkId, mask] : queueInfoIt->second.linkIds) + { + if (linkIds.empty() || linkIds.count(linkId) > 0) + { + mask.set(static_cast(reason), block); + } + } + } +} + +template +void +WifiMacQueueSchedulerImpl::BlockQueues( + WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds) +{ + DoBlockQueues(true, reason, ac, types, rxAddress, txAddress, tids, linkIds); +} + +template +void +WifiMacQueueSchedulerImpl::UnblockQueues( + WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids, + const std::set& linkIds) +{ + DoBlockQueues(false, reason, ac, types, rxAddress, txAddress, tids, linkIds); +} + +template +std::optional +WifiMacQueueSchedulerImpl::GetQueueLinkMask(AcIndex ac, + const WifiContainerQueueId& queueId, + uint8_t linkId) +{ + NS_LOG_FUNCTION(this << +ac << +linkId); + + const auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId); + + if (queueInfoIt == m_perAcInfo[ac].queueInfoMap.cend()) + { + // the given container queue does not exist + return std::nullopt; + } + + const auto& linkIds = queueInfoIt->second.linkIds; + if (const auto linkIt = linkIds.find(linkId); linkIt != linkIds.cend()) + { + return linkIt->second; + } + + return std::nullopt; +} + template std::optional WifiMacQueueSchedulerImpl::GetNext(AcIndex ac, uint8_t linkId) diff --git a/src/wifi/model/wifi-mac-queue-scheduler.h b/src/wifi/model/wifi-mac-queue-scheduler.h index c22aa7dc7..4f6ea1105 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler.h +++ b/src/wifi/model/wifi-mac-queue-scheduler.h @@ -44,6 +44,26 @@ enum class WifiQueueBlockedReason : uint8_t REASONS_COUNT = 0 }; +/** + * \brief Stream insertion operator. + * + * \param os the stream + * \param reason the reason to block container queues + * \returns a reference to the stream + */ +inline std::ostream& +operator<<(std::ostream& os, WifiQueueBlockedReason reason) +{ + switch (reason) + { + case WifiQueueBlockedReason::REASONS_COUNT: + return (os << "REASONS_COUNT"); + default: + NS_ABORT_MSG("Unknown queue blocked reason"); + return (os << "unknown"); + } +} + /** * \ingroup wifi * @@ -101,9 +121,66 @@ class WifiMacQueueScheduler : public Object */ virtual std::list GetLinkIds(AcIndex ac, Ptr mpdu) = 0; + /** + * Block the given set of links for the container queues of the given types and + * Access Category that hold frames having the given Receiver Address (RA), + * Transmitter Address (TA) and TID (if needed) for the given reason, such that + * frames in these queues are not transmitted on the given set of links. + * + * \param reason the reason for blocking the queues + * \param ac the given Access Category + * \param types the types of the queues to block + * \param rxAddress the Receiver Address (RA) of the frames + * \param txAddress the Transmitter Address (TA) of the frames + * \param tids the TIDs optionally identifying the queues to block + * \param linkIds set of links to block (empty to block all setup links) + */ + virtual void BlockQueues(WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids = {}, + const std::set& linkIds = {}) = 0; + /** + * Unblock the given set of links for the container queues of the given types and + * Access Category that hold frames having the given Receiver Address (RA), + * Transmitter Address (TA) and TID (if needed) for the given reason, such that + * frames in these queues can be transmitted on the given set of links. + * + * \param reason the reason for unblocking the queues + * \param ac the given Access Category + * \param types the types of the queues to unblock + * \param rxAddress the Receiver Address (RA) of the frames + * \param txAddress the Transmitter Address (TA) of the frames + * \param tids the TIDs optionally identifying the queues to unblock + * \param linkIds set of links to unblock (empty to unblock all setup links) + */ + virtual void UnblockQueues(WifiQueueBlockedReason reason, + AcIndex ac, + const std::list& types, + const Mac48Address& rxAddress, + const Mac48Address& txAddress, + const std::set& tids = {}, + const std::set& linkIds = {}) = 0; + /// Bitset identifying the reasons to block individual links for a container queue using Mask = std::bitset(WifiQueueBlockedReason::REASONS_COUNT)>; + /** + * Get the mask associated with the given container queue indicating whether the given link + * is blocked and for which reason, provided that the given container queue exists and has + * a mask for the given link. + * + * \param ac the given Access Category + * \param queueId the ID of the given container queue + * \param linkId the ID of the given link + * \return the mask associated with the given container queue for the given link + */ + virtual std::optional GetQueueLinkMask(AcIndex ac, + const WifiContainerQueueId& queueId, + uint8_t linkId) = 0; + /** * Check whether an MPDU has to be dropped before enqueuing the given MPDU. *