wifi: Queue scheduler allows (un)blocking links for specific container queues

This commit is contained in:
Stefano Avallone
2023-02-12 12:01:06 +01:00
parent 17bfd553d7
commit cd401ecf26
2 changed files with 228 additions and 0 deletions

View File

@@ -74,6 +74,26 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler
const WifiContainerQueueId& prevQueueId) final;
/** \copydoc ns3::WifiMacQueueScheduler::GetLinkIds */
std::list<uint8_t> GetLinkIds(AcIndex ac, Ptr<const WifiMpdu> mpdu) final;
/** \copydoc ns3::WifiMacQueueScheduler::BlockQueues */
void BlockQueues(WifiQueueBlockedReason reason,
AcIndex ac,
const std::list<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds) final;
/** \copydoc ns3::WifiMacQueueScheduler::UnblockQueues */
void UnblockQueues(WifiQueueBlockedReason reason,
AcIndex ac,
const std::list<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds) final;
/** \copydoc ns3::WifiMacQueueScheduler::GetQueueLinkMask */
std::optional<Mask> GetQueueLinkMask(AcIndex ac,
const WifiContainerQueueId& queueId,
uint8_t linkId) final;
/** \copydoc ns3::WifiMacQueueScheduler::HasToDropBeforeEnqueue */
Ptr<WifiMpdu> HasToDropBeforeEnqueue(AcIndex ac, Ptr<WifiMpdu> mpdu) final;
/** \copydoc ns3::WifiMacQueueScheduler::NotifyEnqueue */
@@ -226,6 +246,29 @@ class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler
*/
virtual void DoNotifyRemove(AcIndex ac, const std::list<Ptr<WifiMpdu>>& 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<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds);
std::vector<PerAcInfo> m_perAcInfo{AC_UNDEF}; //!< vector of per-AC information
NS_LOG_TEMPLATE_DECLARE; //!< the log component
};
@@ -399,6 +442,114 @@ WifiMacQueueSchedulerImpl<Priority, Compare>::GetLinkIds(AcIndex ac, Ptr<const W
return linkIds;
}
template <class Priority, class Compare>
void
WifiMacQueueSchedulerImpl<Priority, Compare>::DoBlockQueues(
bool block,
WifiQueueBlockedReason reason,
AcIndex ac,
const std::list<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds)
{
NS_LOG_FUNCTION(this << block << reason << ac << rxAddress << txAddress);
std::list<WifiMacHeader> 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<WifiMpdu>(Create<Packet>(), hdr));
for (auto& [linkId, mask] : queueInfoIt->second.linkIds)
{
if (linkIds.empty() || linkIds.count(linkId) > 0)
{
mask.set(static_cast<std::size_t>(reason), block);
}
}
}
}
template <class Priority, class Compare>
void
WifiMacQueueSchedulerImpl<Priority, Compare>::BlockQueues(
WifiQueueBlockedReason reason,
AcIndex ac,
const std::list<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds)
{
DoBlockQueues(true, reason, ac, types, rxAddress, txAddress, tids, linkIds);
}
template <class Priority, class Compare>
void
WifiMacQueueSchedulerImpl<Priority, Compare>::UnblockQueues(
WifiQueueBlockedReason reason,
AcIndex ac,
const std::list<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids,
const std::set<uint8_t>& linkIds)
{
DoBlockQueues(false, reason, ac, types, rxAddress, txAddress, tids, linkIds);
}
template <class Priority, class Compare>
std::optional<WifiMacQueueScheduler::Mask>
WifiMacQueueSchedulerImpl<Priority, Compare>::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 <class Priority, class Compare>
std::optional<WifiContainerQueueId>
WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac, uint8_t linkId)

View File

@@ -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<uint8_t> GetLinkIds(AcIndex ac, Ptr<const WifiMpdu> 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<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids = {},
const std::set<uint8_t>& 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<WifiContainerQueueType>& types,
const Mac48Address& rxAddress,
const Mac48Address& txAddress,
const std::set<uint8_t>& tids = {},
const std::set<uint8_t>& linkIds = {}) = 0;
/// Bitset identifying the reasons to block individual links for a container queue
using Mask = std::bitset<static_cast<std::size_t>(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<Mask> GetQueueLinkMask(AcIndex ac,
const WifiContainerQueueId& queueId,
uint8_t linkId) = 0;
/**
* Check whether an MPDU has to be dropped before enqueuing the given MPDU.
*