20#ifndef WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
21#define WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
31#include <unordered_map>
49template <
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);
239template <
class Priority,
class Compare>
245template <
class Priority,
class Compare>
249 static TypeId tid =
TypeId(
"ns3::WifiMacQueueSchedulerImpl")
251 .SetGroupName(
"Wifi");
255template <
class Priority,
class Compare>
263template <
class Priority,
class Compare>
269 if (
auto queue =
mac->GetTxopQueue(ac); queue !=
nullptr)
271 m_perAcInfo.at(ac).wifiMacQueue = queue;
272 queue->SetScheduler(
this);
278template <
class Priority,
class Compare>
283 return m_perAcInfo.at(ac).wifiMacQueue;
286template <
class Priority,
class Compare>
291 return m_perAcInfo.at(ac).sortedQueues;
294template <
class Priority,
class Compare>
302 auto [queueInfoIt, ret] = m_perAcInfo[ac].queueInfoMap.insert({queueId,
QueueInfo()});
308 auto queueType = std::get<WifiContainerQueueType>(queueId);
314 auto linkId = GetMac()->GetLinkIdByAddress(std::get<Mac48Address>(queueId));
316 queueInfoIt->second.linkIds = {*linkId};
322template <
class Priority,
class Compare>
326 const Priority& priority)
332 "Cannot set the priority of an empty queue");
335 auto queueInfoIt = InitQueueInfo(ac, queueId);
336 typename SortedQueues::iterator sortedQueuesIt;
338 if (queueInfoIt->second.priorityIt.has_value())
343 if (queueInfoIt->second.priorityIt.value()->first == priority)
348 auto handle = m_perAcInfo[ac].sortedQueues.extract(queueInfoIt->second.priorityIt.value());
349 handle.key() = priority;
350 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert(std::move(handle));
355 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert({priority, std::ref(*queueInfoIt)});
358 queueInfoIt->second.priorityIt = sortedQueuesIt;
361template <
class Priority,
class Compare>
366 auto queueInfoIt = InitQueueInfo(ac, queueId);
368 if (queueInfoIt->second.linkIds.empty())
372 std::list<uint8_t> linkIds(GetMac()->GetNLinks());
373 std::iota(linkIds.begin(), linkIds.end(), 0);
376 return queueInfoIt->second.linkIds;
379template <
class Priority,
class Compare>
383 const std::list<uint8_t>& linkIds)
386 auto [queueInfoIt, ret] = m_perAcInfo[ac].queueInfoMap.insert({queueId,
QueueInfo()});
387 queueInfoIt->second.linkIds = linkIds;
390template <
class Priority,
class Compare>
391std::optional<WifiContainerQueueId>
395 return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin());
398template <
class Priority,
class Compare>
399std::optional<WifiContainerQueueId>
406 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(prevQueueId);
407 NS_ABORT_IF(queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
408 !queueInfoIt->second.priorityIt.has_value());
410 auto sortedQueuesIt = queueInfoIt->second.priorityIt.value();
411 NS_ABORT_IF(sortedQueuesIt == m_perAcInfo[ac].sortedQueues.end());
413 return DoGetNext(ac, linkId, ++sortedQueuesIt);
416template <
class Priority,
class Compare>
417std::optional<WifiContainerQueueId>
421 typename SortedQueues::iterator sortedQueuesIt)
426 while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
428 const auto& queueInfoPair = sortedQueuesIt->second.get();
429 const auto& linkIds = queueInfoPair.second.linkIds;
431 if (linkIds.empty() || std::find(linkIds.begin(), linkIds.end(), linkId) != linkIds.end())
438 std::optional<typename SortedQueues::iterator> prevQueueIt;
439 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.begin())
444 GetWifiMacQueue(ac)->ExtractExpiredMpdus(queueInfoPair.first);
446 if (GetWifiMacQueue(ac)->GetNBytes(queueInfoPair.first) == 0)
448 sortedQueuesIt = (prevQueueIt.has_value() ? std::next(prevQueueIt.value())
449 : m_perAcInfo[ac].sortedQueues.begin());
458 std::optional<WifiContainerQueueId> queueId;
460 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
462 queueId = sortedQueuesIt->second.get().first;
467template <
class Priority,
class Compare>
472 return HasToDropBeforeEnqueuePriv(ac, mpdu);
475template <
class Priority,
class Compare>
482 DoNotifyEnqueue(ac, mpdu);
484 if (
auto queueInfoIt =
486 queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
487 !queueInfoIt->second.priorityIt.has_value())
490 "No info for the queue the MPDU was stored into (forgot to call SetPriority()?)");
494template <
class Priority,
class Compare>
502 DoNotifyDequeue(ac, mpdus);
504 std::list<WifiContainerQueueId> queueIds;
506 for (
const auto& mpdu : mpdus)
511 for (
const auto& queueId : queueIds)
513 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
517 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
518 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
519 if (queueInfoIt->second.priorityIt.has_value())
521 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
522 queueInfoIt->second.priorityIt.reset();
528template <
class Priority,
class Compare>
536 DoNotifyRemove(ac, mpdus);
538 std::list<WifiContainerQueueId> queueIds;
540 for (
const auto& mpdu : mpdus)
545 for (
const auto& queueId : queueIds)
547 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
551 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
552 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
553 if (queueInfoIt->second.priorityIt.has_value())
555 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
556 queueInfoIt->second.priorityIt.reset();
Test DROP_OLDEST setting.
Smart pointer class similar to boost::intrusive_ptr.
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.
void DoDispose() override
Destructor implementation.
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::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...
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.
virtual void DoNotifyEnqueue(AcIndex ac, Ptr< WifiMpdu > mpdu)=0
Notify the scheduler that the given MPDU has been enqueued by the given Access Category.
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...
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 Ptr< WifiMpdu > HasToDropBeforeEnqueuePriv(AcIndex ac, Ptr< WifiMpdu > mpdu)=0
Check whether an MPDU has to be dropped before enqueuing the given MPDU.
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...
std::multimap< Priority, std::reference_wrapper< QueueInfoPair >, Compare > SortedQueues
List of container queues sorted in decreasing order of priority.
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 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.
std::tuple< WifiContainerQueueType, Mac48Address, uint8_t > WifiContainerQueueId
Tuple (queue type, Address, TID) identifying a container queue.
@ WIFI_QOSDATA_BROADCAST_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