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