A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-mac-queue-scheduler-impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
9#ifndef WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
10#define WIFI_MAC_QUEUE_SCHEDULER_IMPL_H
11
13#include "wifi-mac-queue.h"
14#include "wifi-mac.h"
15
16#include <algorithm>
17#include <functional>
18#include <iterator>
19#include <list>
20#include <map>
21#include <numeric>
22#include <sstream>
23#include <unordered_map>
24#include <vector>
25
27
28namespace ns3
29{
30
31class WifiMpdu;
32class WifiMacQueue;
33
34/**
35 * \ingroup wifi
36 *
37 * WifiMacQueueSchedulerImpl is a template class enabling the definition of
38 * different types of priority values for the container queues. The function to
39 * compare priority values can be customized as well.
40 */
41template <class Priority, class Compare = std::less<Priority>>
43{
44 public:
45 /// allow WifiMacQueueDropOldestTest class access
46 friend class ::WifiMacQueueDropOldestTest;
47
48 /**
49 * \brief Get the type ID.
50 * \return the object TypeId
51 */
52 static TypeId GetTypeId();
53
54 /**
55 * Constructor
56 */
58
59 /** \copydoc ns3::WifiMacQueueScheduler::SetWifiMac */
60 void SetWifiMac(Ptr<WifiMac> mac) final;
61 /** \copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>) */
62 std::optional<WifiContainerQueueId> GetNext(AcIndex ac, std::optional<uint8_t> linkId) final;
63 /**
64 * \copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>,
65 * const WifiContainerQueueId&)
66 */
67 std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
68 std::optional<uint8_t> linkId,
69 const WifiContainerQueueId& prevQueueId) final;
70 /** \copydoc ns3::WifiMacQueueScheduler::GetLinkIds */
71 std::list<uint8_t> GetLinkIds(AcIndex ac,
73 const std::list<WifiQueueBlockedReason>& ignoredReasons) final;
74 /** \copydoc ns3::WifiMacQueueScheduler::BlockQueues */
76 AcIndex ac,
77 const std::list<WifiContainerQueueType>& types,
78 const Mac48Address& rxAddress,
79 const Mac48Address& txAddress,
80 const std::set<uint8_t>& tids,
81 const std::set<uint8_t>& linkIds) final;
82 /** \copydoc ns3::WifiMacQueueScheduler::UnblockQueues */
84 AcIndex ac,
85 const std::list<WifiContainerQueueType>& types,
86 const Mac48Address& rxAddress,
87 const Mac48Address& txAddress,
88 const std::set<uint8_t>& tids,
89 const std::set<uint8_t>& linkIds) final;
90 /** \copydoc ns3::WifiMacQueueScheduler::GetQueueLinkMask */
91 std::optional<Mask> GetQueueLinkMask(AcIndex ac,
92 const WifiContainerQueueId& queueId,
93 uint8_t linkId) final;
94 /** \copydoc ns3::WifiMacQueueScheduler::HasToDropBeforeEnqueue */
96 /** \copydoc ns3::WifiMacQueueScheduler::NotifyEnqueue */
97 void NotifyEnqueue(AcIndex ac, Ptr<WifiMpdu> mpdu) final;
98 /** \copydoc ns3::WifiMacQueueScheduler::NotifyDequeue */
99 void NotifyDequeue(AcIndex ac, const std::list<Ptr<WifiMpdu>>& mpdus) final;
100 /** \copydoc ns3::WifiMacQueueScheduler::NotifyRemove */
101 void NotifyRemove(AcIndex ac, const std::list<Ptr<WifiMpdu>>& mpdus) final;
102
103 protected:
104 /** \copydoc ns3::Object::DoDispose */
105 void DoDispose() override;
106
107 /**
108 * Set the priority for the given container queue belonging to the given Access Category.
109 *
110 * \param ac the Access Category of the container queue
111 * \param queueId the ID of the given container queue
112 * \param priority the priority value
113 */
114 void SetPriority(AcIndex ac, const WifiContainerQueueId& queueId, const Priority& priority);
115
116 struct QueueInfo;
117
118 /**
119 * Map identifiers (QueueIds) to information associated with container queues.
120 *
121 * Empty queues shall be kept in this data structure because queue information
122 * (such as the set of link IDs) may be configured just once.
123 */
124 using QueueInfoMap = std::unordered_map<WifiContainerQueueId, QueueInfo>;
125
126 /// typedef for a QueueInfoMap element
127 using QueueInfoPair = std::pair<const WifiContainerQueueId, QueueInfo>;
128
129 /**
130 * List of container queues sorted in decreasing order of priority.
131 *
132 * Empty queues shall not be kept in this data structure.
133 *
134 * \note We cannot store iterators to QueueInfoMap because if rehashing occurs due
135 * to an insertion, all iterators are invalidated. References are not invalidated
136 * instead. Therefore, we store reference wrappers (which can be reassigned).
137 */
138 using SortedQueues = std::multimap<Priority, std::reference_wrapper<QueueInfoPair>, Compare>;
139
140 /**
141 * Information associated with a container queue.
142 */
144 {
145 std::optional<typename SortedQueues::iterator>
146 priorityIt; /**< iterator pointing to the entry
147 for this queue in the sorted list */
148 std::map<uint8_t, Mask> linkIds; /**< Maps ID of each link on which packets contained
149 in this queue can be sent to a bitset indicating
150 whether the link is blocked (at least one bit is
151 non-zero) and for which reason */
152 };
153
154 /**
155 * Information specific to a wifi MAC queue
156 */
158 {
159 SortedQueues sortedQueues; //!< sorted list of container queues
160 QueueInfoMap queueInfoMap; //!< information associated with container queues
161 Ptr<WifiMacQueue> wifiMacQueue; //!< pointer to the WifiMacQueue object
162 };
163
164 /**
165 * Get a const reference to the sorted list of container queues for the given
166 * Access Category.
167 *
168 * \param ac the given Access Category
169 * \return a const reference to the sorted list of container queues for the given Access
170 * Category
171 */
173
174 /**
175 * Get the wifi MAC queue associated with the given Access Category.
176 *
177 * \param ac the given Access Category
178 * \return the wifi MAC queue associated with the given Access Category
179 */
181
182 private:
183 /**
184 * If no information for the container queue used to store the given MPDU of the given
185 * Access Category is present in the queue info map, add the information for such a
186 * container queue and initialize the list of the IDs of the links over which packets
187 * contained in that container queue can be sent.
188 *
189 * \param ac the given Access Category
190 * \param mpdu the given MPDU
191 * \return an iterator to the information associated with the container queue used to
192 * store the given MPDU of the given Access Category
193 */
194 typename QueueInfoMap::iterator InitQueueInfo(AcIndex ac, Ptr<const WifiMpdu> mpdu);
195
196 /**
197 * Get the next queue to serve. The search starts from the given one. The returned
198 * queue is guaranteed to contain at least an MPDU whose lifetime has not expired.
199 * Queues containing MPDUs that cannot be sent over the given link are ignored.
200 *
201 * \param ac the Access Category that we want to serve
202 * \param linkId the ID of the link on which MPDUs contained in the returned queue must be
203 * allowed to be sent
204 * \param sortedQueuesIt iterator pointing to the queue we start the search from
205 * \return the ID of the selected container queue (if any)
206 */
207 std::optional<WifiContainerQueueId> DoGetNext(AcIndex ac,
208 std::optional<uint8_t> linkId,
209 typename SortedQueues::iterator sortedQueuesIt);
210
211 /**
212 * Check whether an MPDU has to be dropped before enqueuing the given MPDU.
213 *
214 * \param ac the Access Category of the MPDU being enqueued
215 * \param mpdu the MPDU to enqueue
216 * \return a pointer to the MPDU to drop, if any, or a null pointer, otherwise
217 */
219 /**
220 * Notify the scheduler that the given MPDU has been enqueued by the given Access
221 * Category. The container queue in which the MPDU has been enqueued must be
222 * assigned a priority value.
223 *
224 * \param ac the Access Category of the enqueued MPDU
225 * \param mpdu the enqueued MPDU
226 */
227 virtual void DoNotifyEnqueue(AcIndex ac, Ptr<WifiMpdu> mpdu) = 0;
228 /**
229 * Notify the scheduler that the given list of MPDUs have been dequeued by the
230 * given Access Category. The container queues which became empty after dequeuing
231 * the MPDUs are removed from the sorted list of queues.
232 *
233 * \param ac the Access Category of the dequeued MPDUs
234 * \param mpdus the list of dequeued MPDUs
235 */
236 virtual void DoNotifyDequeue(AcIndex ac, const std::list<Ptr<WifiMpdu>>& mpdus) = 0;
237 /**
238 * Notify the scheduler that the given list of MPDUs have been removed by the
239 * given Access Category. The container queues which became empty after removing
240 * the MPDUs are removed from the sorted list of queues.
241 *
242 * \param ac the Access Category of the removed MPDUs
243 * \param mpdus the list of removed MPDUs
244 */
245 virtual void DoNotifyRemove(AcIndex ac, const std::list<Ptr<WifiMpdu>>& mpdus) = 0;
246
247 /**
248 * Block or unblock the given set of links for the container queues of the given types and
249 * Access Category that hold frames having the given Receiver Address (RA),
250 * Transmitter Address (TA) and TID (if needed) for the given reason.
251 *
252 * \param block true to block the queues, false to unblock
253 * \param reason the reason for blocking the queues
254 * \param ac the given Access Category
255 * \param types the types of the queues to block
256 * \param rxAddress the Receiver Address (RA) of the frames
257 * \param txAddress the Transmitter Address (TA) of the frames
258 * \param tids the TIDs optionally identifying the queues to block
259 * \param linkIds set of links to block (empty to block all setup links)
260 */
261 void DoBlockQueues(bool block,
263 AcIndex ac,
264 const std::list<WifiContainerQueueType>& types,
265 const Mac48Address& rxAddress,
266 const Mac48Address& txAddress,
267 const std::set<uint8_t>& tids,
268 const std::set<uint8_t>& linkIds);
269
270 std::vector<PerAcInfo> m_perAcInfo{AC_UNDEF}; //!< vector of per-AC information
271 NS_LOG_TEMPLATE_DECLARE; //!< the log component
272};
273
274/**
275 * Implementation of the templates declared above.
276 */
277
278template <class Priority, class Compare>
283
284template <class Priority, class Compare>
285TypeId
287{
288 static TypeId tid = TypeId("ns3::WifiMacQueueSchedulerImpl")
290 .SetGroupName("Wifi");
291 return tid;
292}
293
294template <class Priority, class Compare>
295void
301
302template <class Priority, class Compare>
303void
305{
306 for (auto ac : {AC_BE, AC_BK, AC_VI, AC_VO, AC_BE_NQOS, AC_BEACON})
307 {
308 if (auto queue = mac->GetTxopQueue(ac); queue != nullptr)
309 {
310 m_perAcInfo.at(ac).wifiMacQueue = queue;
311 queue->SetScheduler(this);
312 }
313 }
315}
316
317template <class Priority, class Compare>
320{
321 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
322 return m_perAcInfo.at(ac).wifiMacQueue;
323}
324
325template <class Priority, class Compare>
328{
329 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
330 return m_perAcInfo.at(ac).sortedQueues;
331}
332
333template <class Priority, class Compare>
334typename WifiMacQueueSchedulerImpl<Priority, Compare>::QueueInfoMap::iterator
336{
337 NS_LOG_FUNCTION(this << ac << *mpdu);
338
339 auto queueId = WifiMacQueueContainer::GetQueueId(mpdu);
340 // insert queueId in the queue info map if not present yet
341 auto [queueInfoIt, ret] = m_perAcInfo[ac].queueInfoMap.insert({queueId, QueueInfo()});
342
343 // Initialize/update the set of link IDs depending on the container queue type
344 if (GetMac() && GetMac()->GetNLinks() > 1 &&
345 mpdu->GetHeader().GetAddr2() == GetMac()->GetAddress())
346 {
347 // this is an MLD and the TA field of the frame contains the MLD address,
348 // which means that the frame can be sent on multiple links
349 const auto rxAddr = mpdu->GetHeader().GetAddr1();
350
351 // this assert checks that the RA field also contain an MLD address, unless
352 // it contains the broadcast address
353 NS_ASSERT_MSG(rxAddr.IsGroup() || GetMac()->GetMldAddress(rxAddr) == rxAddr,
354 "Address 1 (" << rxAddr << ") is not an MLD address");
355
356 // this assert checks that association (ML setup) has been established
357 // between sender and receiver (unless the receiver is the broadcast address)
358 NS_ASSERT_MSG(GetMac()->CanForwardPacketsTo(rxAddr),
359 "Cannot forward frame to " << rxAddr
360 << "; check that the receiver is associated");
361 // we have to include all the links in case of broadcast frame (we are an AP)
362 // and the links that have been setup with the receiver in case of unicast frame
363 for (const auto linkId : GetMac()->GetLinkIds())
364 {
365 if (rxAddr.IsGroup() ||
366 GetMac()->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(rxAddr))
367 {
368 // the mask is not modified if linkId is already in the map
369 queueInfoIt->second.linkIds.emplace(linkId, Mask{});
370 }
371 else
372 {
373 // this link is no (longer) setup
374 queueInfoIt->second.linkIds.erase(linkId);
375 }
376 }
377 }
378 else
379 {
380 // the TA field of the frame contains a link address, which means that the
381 // frame can only be sent on the corresponding link
382 auto linkId = GetMac() ? GetMac()->GetLinkIdByAddress(mpdu->GetHeader().GetAddr2())
383 : SINGLE_LINK_OP_ID; // make unit test happy
384 NS_ASSERT(linkId.has_value());
385 auto& linkIdsMap = queueInfoIt->second.linkIds;
386 NS_ASSERT_MSG(linkIdsMap.size() <= 1,
387 "At most one link can be associated with this container queue");
388 // set the link map to contain one entry corresponding to the computed link ID;
389 // unless the link map already contained such an entry (in which case the mask
390 // is preserved)
391 if (linkIdsMap.empty() || linkIdsMap.cbegin()->first != *linkId)
392 {
393 linkIdsMap = {{*linkId, Mask{}}};
394 }
395 }
396
397 return queueInfoIt;
398}
399
400template <class Priority, class Compare>
401void
403 const WifiContainerQueueId& queueId,
404 const Priority& priority)
405{
406 NS_LOG_FUNCTION(this << +ac);
407 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
408
409 NS_ABORT_MSG_IF(GetWifiMacQueue(ac)->GetNBytes(queueId) == 0,
410 "Cannot set the priority of an empty queue");
411
412 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
413 NS_ASSERT_MSG(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end(),
414 "No queue info for the given container queue");
415 typename SortedQueues::iterator sortedQueuesIt;
416
417 if (queueInfoIt->second.priorityIt.has_value())
418 {
419 // an element for queueId is present in the set of sorted queues. If the priority
420 // has not changed, do nothing. Otherwise, unlink the node containing such element,
421 // change the priority and insert it back
422 if (queueInfoIt->second.priorityIt.value()->first == priority)
423 {
424 return;
425 }
426
427 auto handle = m_perAcInfo[ac].sortedQueues.extract(queueInfoIt->second.priorityIt.value());
428 handle.key() = priority;
429 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert(std::move(handle));
430 }
431 else
432 {
433 // an element for queueId is not present in the set of sorted queues
434 sortedQueuesIt = m_perAcInfo[ac].sortedQueues.insert({priority, std::ref(*queueInfoIt)});
435 }
436 // update the stored iterator
437 queueInfoIt->second.priorityIt = sortedQueuesIt;
438}
439
440template <class Priority, class Compare>
441std::list<uint8_t>
443 AcIndex ac,
445 const std::list<WifiQueueBlockedReason>& ignoredReasons)
446{
447 auto queueInfoIt = InitQueueInfo(ac, mpdu);
448 std::list<uint8_t> linkIds;
449
450 // include only links that are not blocked in the returned list
451 for (auto [linkId, mask] : queueInfoIt->second.linkIds)
452 {
453 // reset the bits of the mask corresponding to the reasons to ignore
454 for (const auto reason : ignoredReasons)
455 {
456 mask.reset(static_cast<std::size_t>(reason));
457 }
458
459 if (mask.none())
460 {
461 linkIds.emplace_back(linkId);
462 }
463 }
464
465 return linkIds;
466}
467
468template <class Priority, class Compare>
469void
471 bool block,
473 AcIndex ac,
474 const std::list<WifiContainerQueueType>& types,
475 const Mac48Address& rxAddress,
476 const Mac48Address& txAddress,
477 const std::set<uint8_t>& tids,
478 const std::set<uint8_t>& linkIds)
479{
480 std::stringstream ss;
481 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
482 {
483 std::copy(linkIds.cbegin(), linkIds.cend(), std::ostream_iterator<uint16_t>(ss, " "));
484 }
485 NS_LOG_FUNCTION(this << block << reason << ac << rxAddress << txAddress << ss.str());
486 std::list<WifiMacHeader> headers;
487
488 for (const auto queueType : types)
489 {
490 switch (queueType)
491 {
492 case WIFI_CTL_QUEUE:
493 headers.emplace_back(WIFI_MAC_CTL_BACKREQ);
494 break;
495 case WIFI_MGT_QUEUE:
496 headers.emplace_back(WIFI_MAC_MGT_ACTION);
497 break;
499 NS_ASSERT_MSG(!tids.empty(),
500 "TID must be specified for queues containing QoS data frames");
501 for (const auto tid : tids)
502 {
503 headers.emplace_back(WIFI_MAC_QOSDATA);
504 headers.back().SetQosTid(tid);
505 }
506 break;
507 case WIFI_DATA_QUEUE:
508 headers.emplace_back(WIFI_MAC_DATA);
509 break;
510 }
511 }
512 for (auto& hdr : headers)
513 {
514 hdr.SetAddr1(rxAddress);
515 hdr.SetAddr2(txAddress);
516
517 auto queueInfoIt = InitQueueInfo(ac, Create<WifiMpdu>(Create<Packet>(), hdr));
518 for (auto& [linkId, mask] : queueInfoIt->second.linkIds)
519 {
520 if (linkIds.empty() || linkIds.count(linkId) > 0)
521 {
522 mask.set(static_cast<std::size_t>(reason), block);
523 }
524 }
525 }
526}
527
528template <class Priority, class Compare>
529void
532 AcIndex ac,
533 const std::list<WifiContainerQueueType>& types,
534 const Mac48Address& rxAddress,
535 const Mac48Address& txAddress,
536 const std::set<uint8_t>& tids,
537 const std::set<uint8_t>& linkIds)
538{
539 DoBlockQueues(true, reason, ac, types, rxAddress, txAddress, tids, linkIds);
540}
541
542template <class Priority, class Compare>
543void
546 AcIndex ac,
547 const std::list<WifiContainerQueueType>& types,
548 const Mac48Address& rxAddress,
549 const Mac48Address& txAddress,
550 const std::set<uint8_t>& tids,
551 const std::set<uint8_t>& linkIds)
552{
553 DoBlockQueues(false, reason, ac, types, rxAddress, txAddress, tids, linkIds);
554}
555
556template <class Priority, class Compare>
557std::optional<WifiMacQueueScheduler::Mask>
559 const WifiContainerQueueId& queueId,
560 uint8_t linkId)
561{
562 NS_LOG_FUNCTION(this << +ac << +linkId);
563
564 const auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
565
566 if (queueInfoIt == m_perAcInfo[ac].queueInfoMap.cend())
567 {
568 // the given container queue does not exist
569 return std::nullopt;
570 }
571
572 const auto& linkIds = queueInfoIt->second.linkIds;
573 if (const auto linkIt = linkIds.find(linkId); linkIt != linkIds.cend())
574 {
575 return linkIt->second;
576 }
577
578 return std::nullopt;
579}
580
581template <class Priority, class Compare>
582std::optional<WifiContainerQueueId>
584{
585 NS_LOG_FUNCTION(this << +ac << linkId.has_value());
586 return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin());
587}
588
589template <class Priority, class Compare>
590std::optional<WifiContainerQueueId>
592 std::optional<uint8_t> linkId,
593 const WifiContainerQueueId& prevQueueId)
594{
595 NS_LOG_FUNCTION(this << +ac << linkId.has_value());
596
597 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(prevQueueId);
598 NS_ABORT_IF(queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
599 !queueInfoIt->second.priorityIt.has_value());
600
601 auto sortedQueuesIt = queueInfoIt->second.priorityIt.value();
602 NS_ABORT_IF(sortedQueuesIt == m_perAcInfo[ac].sortedQueues.end());
603
604 return DoGetNext(ac, linkId, ++sortedQueuesIt);
605}
606
607template <class Priority, class Compare>
608std::optional<WifiContainerQueueId>
610 AcIndex ac,
611 std::optional<uint8_t> linkId,
612 typename SortedQueues::iterator sortedQueuesIt)
613{
614 NS_LOG_FUNCTION(this << +ac << linkId.has_value());
615 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
616
617 while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
618 {
619 const auto& queueInfoPair = sortedQueuesIt->second.get();
620 const auto& linkIds = queueInfoPair.second.linkIds;
621 typename std::decay_t<decltype(linkIds)>::const_iterator linkIt;
622
623 if (!linkId.has_value() ||
624 ((linkIt = linkIds.find(*linkId)) != linkIds.cend() && linkIt->second.none()))
625 {
626 // Packets in this queue can be sent over the link we got channel access on.
627 // Now remove packets with expired lifetime from this queue.
628 // In case the queue becomes empty, the queue is removed from the sorted
629 // list and sortedQueuesIt is invalidated; thus, store an iterator to the
630 // previous queue in the sorted list (if any) to resume the search afterwards.
631 std::optional<typename SortedQueues::iterator> prevQueueIt;
632 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.begin())
633 {
634 prevQueueIt = std::prev(sortedQueuesIt);
635 }
636
637 GetWifiMacQueue(ac)->ExtractExpiredMpdus(queueInfoPair.first);
638
639 if (GetWifiMacQueue(ac)->GetNBytes(queueInfoPair.first) == 0)
640 {
641 sortedQueuesIt = (prevQueueIt.has_value() ? std::next(prevQueueIt.value())
642 : m_perAcInfo[ac].sortedQueues.begin());
643 continue;
644 }
645 break;
646 }
647
648 sortedQueuesIt++;
649 }
650
651 std::optional<WifiContainerQueueId> queueId;
652
653 if (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
654 {
655 queueId = sortedQueuesIt->second.get().first;
656 }
657 return queueId;
658}
659
660template <class Priority, class Compare>
663{
664 NS_LOG_FUNCTION(this << +ac << *mpdu);
665 return HasToDropBeforeEnqueuePriv(ac, mpdu);
666}
667
668template <class Priority, class Compare>
669void
671{
672 NS_LOG_FUNCTION(this << +ac << *mpdu);
673 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
674
675 // add information for the queue storing the MPDU to the queue info map, if not present yet
676 auto queueInfoIt = InitQueueInfo(ac, mpdu);
677
678 DoNotifyEnqueue(ac, mpdu);
679
680 if (!queueInfoIt->second.priorityIt.has_value())
681 {
683 "No info for the queue the MPDU was stored into (forgot to call SetPriority()?)");
684 }
685}
686
687template <class Priority, class Compare>
688void
690 const std::list<Ptr<WifiMpdu>>& mpdus)
691{
692 NS_LOG_FUNCTION(this << +ac);
693 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
694
695 DoNotifyDequeue(ac, mpdus);
696
697 std::list<WifiContainerQueueId> queueIds;
698
699 for (const auto& mpdu : mpdus)
700 {
701 queueIds.push_back(WifiMacQueueContainer::GetQueueId(mpdu));
702 }
703
704 for (const auto& queueId : queueIds)
705 {
706 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
707 {
708 // The queue has now become empty and needs to be removed from the sorted
709 // list kept by the scheduler
710 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
711 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
712 if (queueInfoIt->second.priorityIt.has_value())
713 {
714 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
715 queueInfoIt->second.priorityIt.reset();
716 }
717 }
718 }
719}
720
721template <class Priority, class Compare>
722void
724 const std::list<Ptr<WifiMpdu>>& mpdus)
725{
726 NS_LOG_FUNCTION(this << +ac);
727 NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
728
729 DoNotifyRemove(ac, mpdus);
730
731 std::list<WifiContainerQueueId> queueIds;
732
733 for (const auto& mpdu : mpdus)
734 {
735 queueIds.push_back(WifiMacQueueContainer::GetQueueId(mpdu));
736 }
737
738 for (const auto& queueId : queueIds)
739 {
740 if (GetWifiMacQueue(ac)->GetNBytes(queueId) == 0)
741 {
742 // The queue has now become empty and needs to be removed from the sorted
743 // list kept by the scheduler
744 auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(queueId);
745 NS_ASSERT(queueInfoIt != m_perAcInfo[ac].queueInfoMap.end());
746 if (queueInfoIt->second.priorityIt.has_value())
747 {
748 m_perAcInfo[ac].sortedQueues.erase(queueInfoIt->second.priorityIt.value());
749 queueInfoIt->second.priorityIt.reset();
750 }
751 }
752 }
753}
754
755} // namespace ns3
756
757#endif /* WIFI_MAC_QUEUE_SCHEDULER_IMPL_H */
Test DROP_OLDEST setting.
an EUI-48 address
Smart pointer class similar to boost::intrusive_ptr.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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.
std::bitset< static_cast< std::size_t >(WifiQueueBlockedReason::REASONS_COUNT)> Mask
Bitset identifying the reasons to block individual links for a container queue.
void DoDispose() override
Destructor implementation.
WifiMacQueueSchedulerImpl is a template class enabling the definition of different types of priority ...
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)
Block or unblock the given set of links for the container queues of the given types and Access Catego...
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
Unblock the given set of links for the container queues of the given types and Access Category that h...
std::pair< const WifiContainerQueueId, QueueInfo > QueueInfoPair
typedef for a QueueInfoMap element
std::optional< Mask > GetQueueLinkMask(AcIndex ac, const WifiContainerQueueId &queueId, uint8_t linkId) final
Get the mask associated with the given container queue indicating whether the given link is blocked a...
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.
void NotifyEnqueue(AcIndex ac, Ptr< WifiMpdu > mpdu) final
Notify the scheduler that the given MPDU has been enqueued by the given Access Category.
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 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
Block the given set of links for the container queues of the given types and Access Category that hol...
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.
static TypeId GetTypeId()
Get the type ID.
std::vector< PerAcInfo > m_perAcInfo
vector of per-AC information
std::list< uint8_t > GetLinkIds(AcIndex ac, Ptr< const WifiMpdu > mpdu, const std::list< WifiQueueBlockedReason > &ignoredReasons) final
Get the list of the IDs of the links the given MPDU (belonging to the given Access Category) can be s...
std::optional< WifiContainerQueueId > GetNext(AcIndex ac, std::optional< uint8_t > linkId) final
Get the next queue to serve, which is guaranteed to contain at least an MPDU whose lifetime has not e...
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.
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.
QueueInfoMap::iterator InitQueueInfo(AcIndex ac, Ptr< const WifiMpdu > mpdu)
If no information for the container queue used to store the given MPDU of the given Access Category i...
std::optional< WifiContainerQueueId > GetNext(AcIndex ac, std::optional< uint8_t > linkId, const WifiContainerQueueId &prevQueueId) final
Get the next queue to serve after the given one.
std::multimap< Priority, std::reference_wrapper< QueueInfoPair >, Compare > SortedQueues
List of container queues sorted in decreasing order of priority.
std::optional< WifiContainerQueueId > DoGetNext(AcIndex ac, std::optional< uint8_t > linkId, typename SortedQueues::iterator sortedQueuesIt)
Get the next queue to serve.
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,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_TEMPLATE_DEFINE(name)
Initialize a reference to a Log component.
Definition log.h:225
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition qos-utils.h:62
@ AC_BE_NQOS
Non-QoS.
Definition qos-utils.h:72
@ AC_BE
Best Effort.
Definition qos-utils.h:64
@ AC_VO
Voice.
Definition qos-utils.h:70
@ AC_VI
Video.
Definition qos-utils.h:68
@ AC_BK
Background.
Definition qos-utils.h:66
@ AC_UNDEF
Total number of ACs.
Definition qos-utils.h:76
@ AC_BEACON
Beacon queue.
Definition qos-utils.h:74
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition wifi-utils.h:183
@ WIFI_MAC_CTL_BACKREQ
@ WIFI_MAC_MGT_ACTION
@ WIFI_MAC_DATA
@ WIFI_MAC_QOSDATA
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Definition log.h:95
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::map< uint8_t, Mask > linkIds
Maps ID of each link on which packets contained in this queue can be sent to a bitset indicating whet...
std::optional< typename SortedQueues::iterator > priorityIt
iterator pointing to the entry for this queue in the sorted list