20 #ifndef WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
21 #define WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
31 #include <unordered_map>
49 template <
class Priority,
class Compare = std::less<Priority>>
54 friend class ::WifiMacQueueDropOldestTest;
70 std::optional<WifiContainerQueueId>
GetNext(
AcIndex ac, uint8_t linkId)
final;
80 const std::list<uint8_t>& linkIds)
final;
111 using QueueInfoMap = std::unordered_map<WifiContainerQueueId, QueueInfo>;
125 using SortedQueues = std::multimap<Priority, std::reference_wrapper<QueueInfoPair>, Compare>;
132 std::optional<typename SortedQueues::iterator>
193 typename SortedQueues::iterator sortedQueuesIt);
239 template <
class Priority,
class Compare>
245 template <
class Priority,
class Compare>
249 static TypeId tid =
TypeId(
"ns3::WifiMacQueueSchedulerImpl")
251 .SetGroupName(
"Wifi");
255 template <
class Priority,
class Compare>
263 template <
class Priority,
class Compare>
269 if (
auto queue =
mac->GetTxopQueue(ac); queue !=
nullptr)
271 m_perAcInfo.at(ac).wifiMacQueue = queue;
272 queue->SetScheduler(
this);
278 template <
class Priority,
class Compare>
283 return m_perAcInfo.at(ac).wifiMacQueue;
286 template <
class Priority,
class Compare>
291 return m_perAcInfo.at(ac).sortedQueues;
294 template <
class Priority,
class Compare>
302 auto [queueInfoIt, ret] = m_perAcInfo[ac].queueInfoMap.insert({queueId,
QueueInfo()});
308 auto queueType = std::get<WifiContainerQueueType>(queueId);
309 auto address = std::get<Mac48Address>(queueId);
317 auto linkId = GetMac()->GetLinkIdByAddress(
address);
319 queueInfoIt->second.linkIds = {*linkId};
325 template <
class Priority,
class Compare>
329 const Priority& priority)
335 "Cannot set the priority of an empty queue");
338 auto queueInfoIt = InitQueueInfo(ac, queueId);
339 typename SortedQueues::iterator sortedQueuesIt;
341 if (queueInfoIt->second.priorityIt.has_value())
346 if (queueInfoIt->second.priorityIt.value()->first == priority)
351 auto handle = m_perAcInfo[ac].sortedQueues.extract(queueInfoIt->second.priorityIt.value());
352 handle.key() = priority;
353 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert(std::move(handle));
358 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert({priority, std::ref(*queueInfoIt)});
361 queueInfoIt->second.priorityIt = sortedQueuesIt;
364 template <
class Priority,
class Compare>
369 auto queueInfoIt = InitQueueInfo(ac, queueId);
371 if (queueInfoIt->second.linkIds.empty())
375 std::list<uint8_t> linkIds(GetMac()->GetNLinks());
376 std::iota(linkIds.begin(), linkIds.end(), 0);
379 return queueInfoIt->second.linkIds;
382 template <
class Priority,
class Compare>
386 const std::list<uint8_t>& linkIds)
389 auto [queueInfoIt, ret] = m_perAcInfo[ac].queueInfoMap.insert({queueId,
QueueInfo()});
390 queueInfoIt->second.linkIds = linkIds;
393 template <
class Priority,
class Compare>
394 std::optional<WifiContainerQueueId>
398 return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin());
401 template <
class Priority,
class Compare>
402 std::optional<WifiContainerQueueId>
409 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(prevQueueId);
410 NS_ABORT_IF(queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
411 !queueInfoIt->second.priorityIt.has_value());
413 auto sortedQueuesIt = queueInfoIt->second.priorityIt.value();
414 NS_ABORT_IF(sortedQueuesIt == m_perAcInfo[ac].sortedQueues.end());
416 return DoGetNext(ac, linkId, ++sortedQueuesIt);
419 template <
class Priority,
class Compare>
420 std::optional<WifiContainerQueueId>
424 typename SortedQueues::iterator sortedQueuesIt)
429 while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
431 const auto& queueInfoPair = sortedQueuesIt->second.get();
432 const auto& linkIds = queueInfoPair.second.linkIds;
434 if (linkIds.empty() || std::find(linkIds.begin(), linkIds.end(), linkId) != linkIds.end())
441 std::optional<typename SortedQueues::iterator> prevQueueIt;
442 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.begin())
447 GetWifiMacQueue(ac)->ExtractExpiredMpdus(queueInfoPair.first);
449 if (GetWifiMacQueue(ac)->GetNBytes(queueInfoPair.first) == 0)
451 sortedQueuesIt = (prevQueueIt.has_value() ? std::next(prevQueueIt.value())
452 : m_perAcInfo[ac].sortedQueues.begin());
461 std::optional<WifiContainerQueueId> queueId;
463 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
465 queueId = sortedQueuesIt->second.get().first;
470 template <
class Priority,
class Compare>
475 return HasToDropBeforeEnqueuePriv(ac, mpdu);
478 template <
class Priority,
class Compare>
485 DoNotifyEnqueue(ac, mpdu);
487 if (
auto queueInfoIt =
489 queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
490 !queueInfoIt->second.priorityIt.has_value())
493 "No info for the queue the MPDU was stored into (forgot to call SetPriority()?)");
497 template <
class Priority,
class Compare>
505 DoNotifyDequeue(ac, mpdus);
507 std::list<WifiContainerQueueId> queueIds;
509 for (
const auto& mpdu : mpdus)
514 for (
const auto& queueId : queueIds)
516 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
520 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
521 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
522 if (queueInfoIt->second.priorityIt.has_value())
524 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
525 queueInfoIt->second.priorityIt.reset();
531 template <
class Priority,
class Compare>
539 DoNotifyRemove(ac, mpdus);
541 std::list<WifiContainerQueueId> queueIds;
543 for (
const auto& mpdu : mpdus)
548 for (
const auto& queueId : queueIds)
550 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
554 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
555 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
556 if (queueInfoIt->second.priorityIt.has_value())
558 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
559 queueInfoIt->second.priorityIt.reset();
Test DROP_OLDEST setting.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static WifiContainerQueueId GetQueueId(Ptr< const WifiMpdu > mpdu)
Return the QueueId identifying the container queue in which the given MPDU is (or is to be) enqueued.
WifiMacQueueScheduler is an abstract base class defining the public interface for a wifi MAC queue sc...
virtual void SetWifiMac(Ptr< WifiMac > mac)
Set the wifi MAC.
void DoDispose() override
Destructor implementation.
WifiMacQueueSchedulerImpl is a template class enabling the definition of different types of priority ...
std::pair< const WifiContainerQueueId, QueueInfo > QueueInfoPair
typedef for a QueueInfoMap element
NS_LOG_TEMPLATE_DECLARE
the log component
void SetWifiMac(Ptr< WifiMac > mac) final
Set the wifi MAC.
virtual void DoNotifyDequeue(AcIndex ac, const std::list< Ptr< WifiMpdu >> &mpdus)=0
Notify the scheduler that the given list of MPDUs have been dequeued by the given Access Category.
void DoDispose() override
Destructor implementation.
std::unordered_map< WifiContainerQueueId, QueueInfo > QueueInfoMap
Map identifiers (QueueIds) to information associated with container queues.
std::optional< WifiContainerQueueId > GetNext(AcIndex ac, uint8_t linkId, const WifiContainerQueueId &prevQueueId) final
Get the next queue to serve after the given one.
void NotifyEnqueue(AcIndex ac, Ptr< WifiMpdu > mpdu) final
Notify the scheduler that the given MPDU has been enqueued by the given Access Category.
QueueInfoMap::iterator InitQueueInfo(AcIndex ac, const WifiContainerQueueId &queueId)
Add the information associated with the given container queue (if not already present) to the map cor...
void NotifyRemove(AcIndex ac, const std::list< Ptr< WifiMpdu >> &mpdus) final
Notify the scheduler that the given list of MPDUs have been removed by the given Access Category.
virtual void DoNotifyEnqueue(AcIndex ac, Ptr< WifiMpdu > mpdu)=0
Notify the scheduler that the given MPDU has been enqueued by the given Access Category.
virtual Ptr< WifiMpdu > HasToDropBeforeEnqueuePriv(AcIndex ac, Ptr< WifiMpdu > mpdu)=0
Check whether an MPDU has to be dropped before enqueuing the given MPDU.
Ptr< WifiMacQueue > GetWifiMacQueue(AcIndex ac) const
Get the wifi MAC queue associated with the given Access Category.
void SetLinkIds(AcIndex ac, const WifiContainerQueueId &queueId, const std::list< uint8_t > &linkIds) final
Set the list of the IDs of the links the given container queue (belonging to the given Access Categor...
static TypeId GetTypeId()
Get the type ID.
std::optional< WifiContainerQueueId > DoGetNext(AcIndex ac, uint8_t linkId, typename SortedQueues::iterator sortedQueuesIt)
Get the next queue to serve.
std::vector< PerAcInfo > m_perAcInfo
vector of per-AC information
const SortedQueues & GetSortedQueues(AcIndex ac) const
Get a const reference to the sorted list of container queues for the given Access Category.
Ptr< WifiMpdu > HasToDropBeforeEnqueue(AcIndex ac, Ptr< WifiMpdu > mpdu) final
Check whether an MPDU has to be dropped before enqueuing the given MPDU.
std::list< uint8_t > GetLinkIds(AcIndex ac, const WifiContainerQueueId &queueId) final
Get the list of the IDs of the links the given container queue (belonging to the given Access Categor...
WifiMacQueueSchedulerImpl()
Constructor.
std::optional< WifiContainerQueueId > GetNext(AcIndex ac, uint8_t linkId) final
Get the next queue to serve, which is guaranteed to contain at least an MPDU whose lifetime has not e...
virtual void DoNotifyRemove(AcIndex ac, const std::list< Ptr< WifiMpdu >> &mpdus)=0
Notify the scheduler that the given list of MPDUs have been removed by the given Access Category.
void NotifyDequeue(AcIndex ac, const std::list< Ptr< WifiMpdu >> &mpdus) final
Notify the scheduler that the given list of MPDUs have been dequeued by the given Access Category.
std::multimap< Priority, std::reference_wrapper< QueueInfoPair >, Compare > SortedQueues
List of container queues sorted in decreasing order of priority.
void SetPriority(AcIndex ac, const WifiContainerQueueId &queueId, const Priority &priority)
Set the priority for the given container queue belonging to the given Access Category.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_TEMPLATE_DEFINE(name)
Initialize a reference to a Log component.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
@ AC_UNDEF
Total number of ACs.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_QOSDATA_BROADCAST_QUEUE
std::tuple< WifiContainerQueueType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, Address, TID) identifying a container queue.
Information specific to a wifi MAC queue.
SortedQueues sortedQueues
sorted list of container queues
Ptr< WifiMacQueue > wifiMacQueue
pointer to the WifiMacQueue object
QueueInfoMap queueInfoMap
information associated with container queues
Information associated with a container queue.
std::list< uint8_t > linkIds
IDs of the links over which packets contained in this queue can be sent over.
std::optional< typename SortedQueues::iterator > priorityIt
iterator pointing to the entry for this queue in the sorted list