A Discrete-Event Network Simulator
API
wifi-mac-queue.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005, 2009 INRIA
4 * Copyright (c) 2009 MIRKO BANCHI
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20 * Mirko Banchi <mk.banchi@gmail.com>
21 * Stefano Avallone <stavallo@unina.it>
22 */
23
24#include "ns3/simulator.h"
25#include "wifi-mac-queue.h"
27#include <functional>
28
29namespace ns3 {
30
31NS_LOG_COMPONENT_DEFINE ("WifiMacQueue");
32
33NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
34NS_OBJECT_TEMPLATE_CLASS_DEFINE (Queue, WifiMacQueueItem);
35
36TypeId
38{
39 static TypeId tid = TypeId ("ns3::WifiMacQueue")
41 .SetGroupName ("Wifi")
42 .AddConstructor<WifiMacQueue> ()
43 .AddAttribute ("MaxSize",
44 "The max queue size",
45 QueueSizeValue (QueueSize ("500p")),
46 MakeQueueSizeAccessor (&QueueBase::SetMaxSize,
48 MakeQueueSizeChecker ())
49 .AddAttribute ("MaxDelay", "If a packet stays longer than this delay in the queue, it is dropped.",
50 TimeValue (MilliSeconds (500)),
53 .AddAttribute ("DropPolicy", "Upon enqueue with full queue, drop oldest (DropOldest) or newest (DropNewest) packet",
57 WifiMacQueue::DROP_NEWEST, "DropNewest"))
58 .AddTraceSource ("Expired", "MPDU dropped because its lifetime expired.",
60 "ns3::WifiMacQueueItem::TracedCallback")
61 ;
62 return tid;
63}
64
66 : m_ac (ac),
67 NS_LOG_TEMPLATE_DEFINE ("WifiMacQueue")
68{
69}
70
72{
74 m_nQueuedPackets.clear ();
75 m_nQueuedBytes.clear ();
76}
77
78bool
79WifiMacQueue::TtlExceeded (ConstIterator &it, const Time& now)
80{
81 if (now > (*it)->GetTimeStamp () + m_maxDelay)
82 {
83 NS_LOG_DEBUG ("Removing packet that stayed in the queue for too long (" <<
84 now - (*it)->GetTimeStamp () << ")");
85 auto curr = it++;
86 m_traceExpired (DoRemove (curr));
87 return true;
88 }
89 return false;
90}
91
92bool
94{
95 NS_ASSERT (item != nullptr && item->IsQueued ());
96 auto it = item->m_queueIt;
97 return TtlExceeded (it, now);
98}
99
100void
102{
103 NS_LOG_FUNCTION (this << delay);
104 m_maxDelay = delay;
105}
106
107Time
109{
110 return m_maxDelay;
111}
112
113bool
115{
116 NS_LOG_FUNCTION (this << *item);
117
118 return Insert (end (), item);
119}
120
121bool
123{
124 NS_LOG_FUNCTION (this << *item);
125
126 return Insert (begin (), item);
127}
128
129bool
131{
132 NS_LOG_FUNCTION (this << *item);
133 NS_ASSERT_MSG (GetMaxSize ().GetUnit () == QueueSizeUnit::PACKETS,
134 "WifiMacQueues must be in packet mode");
135
136 // insert the item if the queue is not full
137 if (QueueBase::GetNPackets () < GetMaxSize ().GetValue ())
138 {
139 return DoEnqueue (pos, item);
140 }
141
142 // the queue is full; scan the list in the attempt to remove stale packets
143 ConstIterator it = begin ();
144 const Time now = Simulator::Now ();
145 while (it != end ())
146 {
147 if (it == pos && TtlExceeded (it, now))
148 {
149 return DoEnqueue (it, item);
150 }
151 if (TtlExceeded (it, now))
152 {
153 return DoEnqueue (pos, item);
154 }
155 it++;
156 }
157
158 // the queue is still full, remove the oldest item if the policy is drop oldest
160 {
161 NS_LOG_DEBUG ("Remove the oldest item in the queue");
162 if (pos == begin ())
163 {
164 // Avoid invalidating pos
165 DoRemove (begin ());
166 pos = begin ();
167 }
168 else
169 {
170 DoRemove (begin ());
171 }
172 }
173
174 return DoEnqueue (pos, item);
175}
176
179{
180 NS_LOG_FUNCTION (this);
181 const Time now = Simulator::Now ();
182 for (ConstIterator it = begin (); it != end (); )
183 {
184 if (!TtlExceeded (it, now))
185 {
186 return DoDequeue (it);
187 }
188 }
189 NS_LOG_DEBUG ("The queue is empty");
190 return 0;
191}
192
193void
195{
196 NS_LOG_FUNCTION (this << *mpdu);
197
198 if (mpdu->IsQueued ())
199 {
200 NS_ASSERT (mpdu->m_queueAc == m_ac);
201 NS_ASSERT (*mpdu->m_queueIt == mpdu);
202
203 DoDequeue (mpdu->m_queueIt);
204 }
205}
206
209{
210 NS_LOG_FUNCTION (this);
211 const Time now = Simulator::Now ();
212 for (auto it = begin (); it != end (); it++)
213 {
214 // skip packets that stayed in the queue for too long. They will be
215 // actually removed from the queue by the next call to a non-const method
216 if (now <= (*it)->GetTimeStamp () + m_maxDelay)
217 {
218 return DoPeek (it);
219 }
220 }
221 NS_LOG_DEBUG ("The queue is empty");
222 return 0;
223}
224
227{
228 NS_LOG_FUNCTION (this << dest << item);
229 NS_ASSERT (item == nullptr || item->IsQueued ());
230
231 ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
232 const Time now = Simulator::Now ();
233 while (it != end ())
234 {
235 // skip packets that stayed in the queue for too long. They will be
236 // actually removed from the queue by the next call to a non-const method
237 if (now <= (*it)->GetTimeStamp () + m_maxDelay)
238 {
239 if (((*it)->GetHeader ().IsData () || (*it)->GetHeader ().IsQosData ())
240 && (*it)->GetDestinationAddress () == dest)
241 {
242 return *it;
243 }
244 }
245 it++;
246 }
247 NS_LOG_DEBUG ("The queue is empty");
248 return nullptr;
249}
250
253{
254 NS_LOG_FUNCTION (this << +tid << item);
255 NS_ASSERT (item == nullptr || item->IsQueued ());
256
257 ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
258 const Time now = Simulator::Now ();
259 while (it != end ())
260 {
261 // skip packets that stayed in the queue for too long. They will be
262 // actually removed from the queue by the next call to a non-const method
263 if (now <= (*it)->GetTimeStamp () + m_maxDelay)
264 {
265 if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid)
266 {
267 return *it;
268 }
269 }
270 it++;
271 }
272 NS_LOG_DEBUG ("The queue is empty");
273 return nullptr;
274}
275
278{
279 NS_LOG_FUNCTION (this << +tid << dest << item);
280 NS_ASSERT (item == nullptr || item->IsQueued ());
281
282 ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
283 const Time now = Simulator::Now ();
284 while (it != end ())
285 {
286 // skip packets that stayed in the queue for too long. They will be
287 // actually removed from the queue by the next call to a non-const method
288 if (now <= (*it)->GetTimeStamp () + m_maxDelay)
289 {
290 if ((*it)->GetHeader ().IsQosData () && (*it)->GetDestinationAddress () == dest
291 && (*it)->GetHeader ().GetQosTid () == tid)
292 {
293 return *it;
294 }
295 }
296 it++;
297 }
298 NS_LOG_DEBUG ("The queue is empty");
299 return nullptr;
300}
301
305{
306 NS_LOG_FUNCTION (this << item);
307 NS_ASSERT (item == nullptr || item->IsQueued ());
308
309 ConstIterator it = (item != nullptr ? std::next (item->m_queueIt) : begin ());
310 const Time now = Simulator::Now ();
311 while (it != end ())
312 {
313 // skip packets that stayed in the queue for too long. They will be
314 // actually removed from the queue by the next call to a non-const method
315 if (now <= (*it)->GetTimeStamp () + m_maxDelay)
316 {
317 if (!(*it)->GetHeader ().IsQosData () || !blockedPackets
318 || !blockedPackets->IsBlocked ((*it)->GetHeader ().GetAddr1 (), (*it)->GetHeader ().GetQosTid ()))
319 {
320 return *it;
321 }
322 }
323 it++;
324 }
325 NS_LOG_DEBUG ("The queue is empty");
326 return nullptr;
327}
328
331{
332 NS_LOG_FUNCTION (this);
333
334 const Time now = Simulator::Now ();
335 for (ConstIterator it = begin (); it != end (); )
336 {
337 if (!TtlExceeded (it, now))
338 {
339 return DoRemove (it);
340 }
341 }
342 NS_LOG_DEBUG ("The queue is empty");
343 return 0;
344}
345
348{
349 NS_LOG_FUNCTION (this << item << removeExpired);
350 NS_ASSERT (item != 0 && item->IsQueued ());
351
352 if (!removeExpired)
353 {
354 ConstIterator next = std::next (item->m_queueIt);
355 DoRemove (item->m_queueIt);
356 return (next == end () ? nullptr : *next);
357 }
358
359 const Time now = Simulator::Now ();
360
361 // remove stale items queued before the given position
362 ConstIterator it = begin ();
363 while (it != end ())
364 {
365 if (*it == item)
366 {
367 ConstIterator next = std::next (item->m_queueIt);
368 DoRemove (item->m_queueIt);
369 return (next == end () ? nullptr : *next);
370 }
371 else if (!TtlExceeded (it, now))
372 {
373 it++;
374 }
375 }
376 NS_LOG_DEBUG ("Invalid iterator");
377 return nullptr;
378}
379
380void
382{
383 NS_LOG_FUNCTION (this << *currentItem << *newItem);
384 NS_ASSERT (currentItem->IsQueued ());
385 NS_ASSERT (currentItem->m_queueAc == m_ac);
386 NS_ASSERT (*currentItem->m_queueIt == currentItem);
387 NS_ASSERT (!newItem->IsQueued ());
388
389 auto pos = std::next (currentItem->m_queueIt);
390 DoDequeue (currentItem->m_queueIt);
391 bool ret = Insert (pos, newItem);
392 // The size of a WifiMacQueue is measured as number of packets. We dequeued
393 // one packet, so there is certainly room for inserting one packet
394 NS_ABORT_IF (!ret);
395}
396
399{
400 NS_LOG_FUNCTION (this << dest);
401
402 uint32_t nPackets = 0;
403 const Time now = Simulator::Now ();
404
405 for (ConstIterator it = begin (); it != end (); )
406 {
407 if (!TtlExceeded (it, now))
408 {
409 if ((*it)->GetHeader ().IsData () && (*it)->GetDestinationAddress () == dest)
410 {
411 nPackets++;
412 }
413
414 it++;
415 }
416 }
417 NS_LOG_DEBUG ("returns " << nPackets);
418 return nPackets;
419}
420
423{
424 NS_LOG_FUNCTION (this << dest);
425 uint32_t nPackets = 0;
426 const Time now = Simulator::Now ();
427
428 for (ConstIterator it = begin (); it != end (); )
429 {
430 if (!TtlExceeded (it, now))
431 {
432 if ((*it)->GetHeader ().IsQosData () && (*it)->GetDestinationAddress () == dest
433 && (*it)->GetHeader ().GetQosTid () == tid)
434 {
435 nPackets++;
436 }
437
438 it++;
439 }
440 }
441 NS_LOG_DEBUG ("returns " << nPackets);
442 return nPackets;
443}
444
445bool
447{
448 NS_LOG_FUNCTION (this);
449 const Time now = Simulator::Now ();
450
451 for (ConstIterator it = begin (); it != end (); )
452 {
453 if (!TtlExceeded (it, now))
454 {
455 NS_LOG_DEBUG ("returns false");
456 return false;
457 }
458 }
459 NS_LOG_DEBUG ("returns true");
460 return true;
461}
462
465{
466 NS_LOG_FUNCTION (this);
467 const Time now = Simulator::Now ();
468
469 // remove packets that stayed in the queue for too long
470 for (ConstIterator it = begin (); it != end (); )
471 {
472 if (!TtlExceeded (it, now))
473 {
474 it++;
475 }
476 }
477 return QueueBase::GetNPackets ();
478}
479
482{
483 NS_LOG_FUNCTION (this);
484 const Time now = Simulator::Now ();
485
486 // remove packets that stayed in the queue for too long
487 for (ConstIterator it = begin (); it != end (); )
488 {
489 if (!TtlExceeded (it, now))
490 {
491 it++;
492 }
493 }
494 return QueueBase::GetNBytes ();
495}
496
499{
500 WifiAddressTidPair addressTidPair (dest, tid);
501 auto it = m_nQueuedPackets.find (addressTidPair);
502 if (it == m_nQueuedPackets.end ())
503 {
504 return 0;
505 }
506 return m_nQueuedPackets.at (addressTidPair);
507}
508
510WifiMacQueue::GetNBytes (uint8_t tid, Mac48Address dest) const
511{
512 WifiAddressTidPair addressTidPair (dest, tid);
513 auto it = m_nQueuedBytes.find (addressTidPair);
514 if (it == m_nQueuedBytes.end ())
515 {
516 return 0;
517 }
518 return m_nQueuedBytes.at (addressTidPair);
519}
520
521bool
523{
524 Iterator ret;
525 if (Queue<WifiMacQueueItem>::DoEnqueue (pos, item, ret))
526 {
527 // update statistics about queued packets
528 if (item->GetHeader ().IsQosData ())
529 {
530 WifiAddressTidPair addressTidPair (item->GetHeader ().GetAddr1 (), item->GetHeader ().GetQosTid ());
531 auto it = m_nQueuedPackets.find (addressTidPair);
532 if (it == m_nQueuedPackets.end ())
533 {
534 m_nQueuedPackets[addressTidPair] = 0;
535 m_nQueuedBytes[addressTidPair] = 0;
536 }
537 m_nQueuedPackets[addressTidPair]++;
538 m_nQueuedBytes[addressTidPair] += item->GetSize ();
539 }
540 // set item's information about its position in the queue
541 item->m_queueAc = m_ac;
542 item->m_queueIt = ret;
543 return true;
544 }
545 return false;
546}
547
549WifiMacQueue::DoDequeue (ConstIterator pos)
550{
551 NS_LOG_FUNCTION (this);
552
554
555 if (item != 0 && item->GetHeader ().IsQosData ())
556 {
557 WifiAddressTidPair addressTidPair (item->GetHeader ().GetAddr1 (), item->GetHeader ().GetQosTid ());
558 NS_ASSERT (m_nQueuedPackets.find (addressTidPair) != m_nQueuedPackets.end ());
559 NS_ASSERT (m_nQueuedPackets[addressTidPair] >= 1);
560 NS_ASSERT (m_nQueuedBytes[addressTidPair] >= item->GetSize ());
561
562 m_nQueuedPackets[addressTidPair]--;
563 m_nQueuedBytes[addressTidPair] -= item->GetSize ();
564 }
565
566 if (item != 0)
567 {
568 NS_ASSERT (item->IsQueued ());
569 item->m_queueAc = AC_UNDEF;
570 }
571
572 return item;
573}
574
576WifiMacQueue::DoRemove (ConstIterator pos)
577{
579
580 if (item != 0 && item->GetHeader ().IsQosData ())
581 {
582 WifiAddressTidPair addressTidPair (item->GetHeader ().GetAddr1 (), item->GetHeader ().GetQosTid ());
583 NS_ASSERT (m_nQueuedPackets.find (addressTidPair) != m_nQueuedPackets.end ());
584 NS_ASSERT (m_nQueuedPackets[addressTidPair] >= 1);
585 NS_ASSERT (m_nQueuedBytes[addressTidPair] >= item->GetSize ());
586
587 m_nQueuedPackets[addressTidPair]--;
588 m_nQueuedBytes[addressTidPair] -= item->GetSize ();
589 }
590
591 if (item != 0)
592 {
593 NS_ASSERT (item->IsQueued ());
594 item->m_queueAc = AC_UNDEF;
595 }
596
597 return item;
598}
599
600} //namespace ns3
Hold variables of type enum.
Definition: enum.h:55
an EUI-48 address
Definition: mac48-address.h:44
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Introspection did not find any typical Config paths.
uint32_t GetNPackets(void) const
Definition: queue.cc:90
void SetMaxSize(QueueSize size)
Set the maximum size of this queue.
Definition: queue.cc:200
uint32_t GetNBytes(void) const
Definition: queue.cc:98
QueueSize GetMaxSize(void) const
Definition: queue.cc:217
Template class for packet Queues.
Definition: queue.h:262
Ptr< Item > DoDequeue(ConstIterator pos)
Pull the item to dequeue from the queue.
Definition: queue.h:539
Ptr< Item > DoRemove(ConstIterator pos)
Pull the item to drop from the queue.
Definition: queue.h:568
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
This queue implements the timeout procedure described in (Section 9.19.2.6 "Retransmit procedures" pa...
bool DoEnqueue(ConstIterator pos, Ptr< WifiMacQueueItem > item)
Wrapper for the DoEnqueue method provided by the base class that additionally sets the iterator field...
Time m_maxDelay
Time to live for packets in the queue.
Ptr< const WifiMacQueueItem > PeekByTidAndAddress(uint8_t tid, Mac48Address dest, Ptr< const WifiMacQueueItem > item=nullptr) const
Search and return, if present in the queue, the first packet having the receiver address equal to des...
bool PushFront(Ptr< WifiMacQueueItem > item)
Enqueue the given Wifi MAC queue item at the front of the queue.
uint32_t GetNPacketsByTidAndAddress(uint8_t tid, Mac48Address dest)
Return the number of QoS packets having TID equal to tid and destination address equal to dest.
uint32_t GetNPacketsByAddress(Mac48Address dest)
Return the number of packets having destination address specified by dest.
std::unordered_map< WifiAddressTidPair, uint32_t, WifiAddressTidHash > m_nQueuedBytes
Per (MAC address, TID) pair queued bytes.
Ptr< const WifiMacQueueItem > PeekFirstAvailable(const Ptr< QosBlockedDestinations > blockedPackets=nullptr, Ptr< const WifiMacQueueItem > item=nullptr) const
Return first available packet for transmission.
bool TtlExceeded(Ptr< const WifiMacQueueItem > item, const Time &now)
Remove the given item if it has been in the queue for too long.
Ptr< WifiMacQueueItem > DoDequeue(ConstIterator pos)
Wrapper for the DoDequeue method provided by the base class that additionally resets the iterator fie...
Time GetMaxDelay(void) const
Return the maximum delay before the packet is discarded.
std::unordered_map< WifiAddressTidPair, uint32_t, WifiAddressTidHash > m_nQueuedPackets
Per (MAC address, TID) pair queued packets.
void SetMaxDelay(Time delay)
Set the maximum delay before the packet is discarded.
Ptr< const WifiMacQueueItem > PeekByAddress(Mac48Address dest, Ptr< const WifiMacQueueItem > item=nullptr) const
Search and return, if present in the queue, the first packet (either Data frame or QoS Data frame) ha...
bool Insert(ConstIterator pos, Ptr< WifiMacQueueItem > item)
Enqueue the given Wifi MAC queue item before the given position.
Ptr< const WifiMacQueueItem > Peek(void) const override
Peek the packet in the front of the queue.
Ptr< WifiMacQueueItem > DoRemove(ConstIterator pos)
Wrapper for the DoRemove method provided by the base class that additionally resets the iterator fiel...
bool Enqueue(Ptr< WifiMacQueueItem > item) override
Enqueue the given Wifi MAC queue item at the end of the queue.
Ptr< const WifiMacQueueItem > PeekByTid(uint8_t tid, Ptr< const WifiMacQueueItem > item=nullptr) const
Search and return, if present in the queue, the first packet having the TID equal to tid.
uint32_t GetNPackets(void)
static TypeId GetTypeId(void)
Get the type ID.
WifiMacQueue(AcIndex ac=AC_UNDEF)
Constructor.
TracedCallback< Ptr< const WifiMacQueueItem > > m_traceExpired
Traced callback: fired when a packet is dropped due to lifetime expiration.
Ptr< WifiMacQueueItem > Dequeue(void) override
Dequeue the packet in the front of the queue.
AcIndex m_ac
the access category
void Replace(Ptr< const WifiMacQueueItem > currentItem, Ptr< WifiMacQueueItem > newItem)
Replace the given current item with the given new item.
DropPolicy m_dropPolicy
Drop behavior of queue.
void DequeueIfQueued(Ptr< const WifiMacQueueItem > mpdu)
Dequeue the given MPDU if it is stored in this queue.
Ptr< WifiMacQueueItem > Remove(void) override
Remove the packet in the front of the queue.
uint32_t GetNBytes(void)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:77
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_TEMPLATE_DEFINE(name)
Initialize a reference to a Log component.
Definition: log.h:239
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_TEMPLATE_CLASS_DEFINE(type, param)
Explicitly instantiate a template class and register the resulting instance with the TypeId system.
Definition: object-base.h:67
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
@ PACKETS
Use number of packets for queue size.
Definition: queue-size.h:44
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:71
@ AC_UNDEF
Total number of ACs.
Definition: qos-utils.h:85
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
std::pair< Mac48Address, uint8_t > WifiAddressTidPair
(MAC address, TID) pair
Definition: qos-utils.h:32
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:162